001         package com.croftsoft.core.media.j3d;
002    
003         import java.awt.event.KeyEvent;
004    
005         import javax.media.j3d.*;
006         import javax.vecmath.*;
007    
008         /*********************************************************************
009         *
010         * Static method library to manipulate Transform3D data.
011         * Primarily focuses on transforming a view through the 6 degrees of
012         * freedom.
013         *
014         * <P>
015         *
016         * <B>Reference:</B>
017         * <P>
018         * 
019         * Foley, et al., <U>Computer Graphics:  Principles and Practice</U>.
020         * Provides the mathematics for the 3D rotation matrices.
021         *
022         * @author
023         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
024         * @version
025         *   1998-12-06
026         *********************************************************************/
027    
028         public class  Transform3DLib
029         //////////////////////////////////////////////////////////////////////
030         //////////////////////////////////////////////////////////////////////
031         {
032    
033         /** Relative X axis */
034         public static final int  X = 0;
035    
036         /** Relative Y axis */
037         public static final int  Y = 1;
038    
039         /** Relative Z axis */
040         public static final int  Z = 2;
041    
042         private  Transform3DLib ( ) { /* empty */ }
043    
044         //////////////////////////////////////////////////////////////////////
045         //////////////////////////////////////////////////////////////////////
046    
047         /*********************************************************************
048         * Rotates the view by the given rotation matrix.
049         *
050         * @param  transform3D
051         *   The transform containing the current rotation matrix.
052         * @param  rotation
053         *   The rotation matrix to be muliplied.
054         * @return
055         *    The transform3D argument has its current rotation matrix replaced
056         *    by its old value as multiplied by the rotation argument.
057         *********************************************************************/
058         public static void  viewRotate (
059           Transform3D  transform3D, Matrix3d  rotation )
060         //////////////////////////////////////////////////////////////////////
061         {
062           Matrix3d  oldRotation = new Matrix3d ( );
063           transform3D.get ( oldRotation );
064           oldRotation.mul ( rotation );
065           transform3D.setRotation ( oldRotation );
066         }
067    
068         /*********************************************************************
069         * Pitches the view by a given number of radians.
070         *
071         * @param  transform3D
072         *   The transform containing the current rotation matrix.
073         * @param  radians
074         *   The angle to rotate the transform about its relative X axis.
075         * @return
076         *    The rotation matrix is updated in the transform3D argument.
077         *********************************************************************/
078         public static void  viewPitch (
079           Transform3D  transform3D, double  radians )
080         //////////////////////////////////////////////////////////////////////
081         {
082           double  sin = Math.sin ( radians );
083           double  cos = Math.cos ( radians );
084    
085           viewRotate ( transform3D, new Matrix3d (
086             1.0, 0.0,  0.0,
087             0.0, cos, -sin,
088             0.0, sin,  cos ) );
089         }
090    
091         /*********************************************************************
092         * Yaws the view by a given number of radians.
093         *
094         * @param  transform3D
095         *   The transform containing the current rotation matrix.
096         * @param  radians
097         *   The angle to rotate the transform about its relative Y axis.
098         * @return
099         *    The rotation matrix is updated in the transform3D argument.
100         *********************************************************************/
101         public static void  viewYaw (
102           Transform3D  transform3D, double  radians )
103         //////////////////////////////////////////////////////////////////////
104         {
105           double  sin = Math.sin ( radians );
106           double  cos = Math.cos ( radians );
107    
108           viewRotate ( transform3D, new Matrix3d (
109              cos, 0.0, sin,
110              0.0, 1.0, 0.0,
111             -sin, 0.0, cos ) );
112         }
113    
114         /*********************************************************************
115         * Rolls the view by a given number of radians.
116         *
117         * @param  transform3D
118         *   The transform containing the current rotation matrix.
119         * @param  radians
120         *   The angle to rotate the transform about its relative Z axis.
121         * @return
122         *    The rotation matrix is updated in the transform3D argument.
123         *********************************************************************/
124         public static void  viewRoll  (
125           Transform3D  transform3D, double  radians )
126         //////////////////////////////////////////////////////////////////////
127         {
128           double  sin = Math.sin ( radians );
129           double  cos = Math.cos ( radians );
130    
131           viewRotate ( transform3D, new Matrix3d (
132             cos, -sin, 0.0,
133             sin,  cos, 0.0,
134             0.0,  0.0, 1.0 ) );
135         }
136    
137         /*********************************************************************
138         * Translates the view by a given distance along a relative axis.
139         *
140         * @param  transform3D
141         *   The transform containing the current rotation and translation
142         *   matrix.
143         * @param  dimension
144         *   The relative axis to translate along.
145         *   Use the public constants X, Y, and Z provided by this class.
146         * @return
147         *    The translation vector is updated in the transform3D argument.
148         *********************************************************************/
149         public static void  viewTranslate (
150           Transform3D  transform3D,
151           int          dimension,
152           double       distance )
153         //////////////////////////////////////////////////////////////////////
154         {
155           Matrix3d  rotation    = new Matrix3d ( );
156           Vector3d  translation = new Vector3d ( );
157           transform3D.get ( rotation, translation );
158    
159           // Get the alignment of the rotated relative axes.
160           Vector3d  r = new Vector3d ( );
161           rotation.getColumn ( dimension, r );
162    
163           r.scale ( distance );
164    
165           translation.add ( r );
166    
167           transform3D.setTranslation ( translation );
168         }
169    
170         /*********************************************************************
171         * Transforms the view based upon a user keyboard input.
172         *
173         * @param  transform3D
174         *   The transform containing the current rotation and translation
175         *   matrices, usually the user's view transform.
176         * @param  keyEvent
177         *    Arrow keys in combination with no other key, the Shift key, or
178         *    the Alt key will rotate or translate the transform about the
179         *    relative X, Y, and Z axes respectively for 6 degrees of freedom.
180         * @param  deltaRotation
181         *    The number of radians to rotate the view upon a keyboard input.
182         * @param  deltaTranslation
183         *    The distance to translate the view upon a keyboard input.
184         * @return
185         *    Returns true if any changes were made to transform3D argument.
186         *********************************************************************/
187         public static boolean  viewKeyPressed (
188           Transform3D  transform3D,
189           KeyEvent     keyEvent,
190           double       deltaRotation,
191           double       deltaTranslation )
192         //////////////////////////////////////////////////////////////////////
193         {
194           boolean  moved = false;
195    
196           int  keyCode = keyEvent.getKeyCode ( );
197    
198           if ( keyEvent.isAltDown ( ) )
199           {
200             switch ( keyCode )
201             {
202               case KeyEvent.VK_UP   :
203                 viewTranslate ( transform3D, Z, -deltaTranslation );
204                 moved = true;
205                 break;
206               case KeyEvent.VK_DOWN :
207                 viewTranslate ( transform3D, Z,  deltaTranslation );
208                 moved = true;
209                 break;
210               case KeyEvent.VK_LEFT :
211                 viewRoll ( transform3D,  deltaRotation );
212                 moved = true;
213                 break;
214               case KeyEvent.VK_RIGHT:
215                 viewRoll ( transform3D, -deltaRotation );
216                 moved = true;
217                 break;
218             }
219           }
220           else if ( keyEvent.isShiftDown ( ) )
221           {
222             switch ( keyCode )
223             {
224               case KeyEvent.VK_UP   :
225                 viewTranslate (
226                   transform3D, Y,  deltaTranslation );
227                 moved = true;
228                 break;
229               case KeyEvent.VK_DOWN :
230                 viewTranslate (
231                   transform3D, Y, -deltaTranslation );
232                 moved = true;
233                 break;
234               case KeyEvent.VK_LEFT :
235                 viewYaw ( transform3D,  deltaRotation );
236                 moved = true;
237                 break;
238               case KeyEvent.VK_RIGHT:
239                 viewYaw ( transform3D, -deltaRotation );
240                 moved = true;
241                 break;
242             }
243           }
244           else
245           {
246             switch ( keyCode )
247             {
248               case KeyEvent.VK_UP   :
249                 viewPitch  ( transform3D, -deltaRotation );
250                 moved = true;
251                 break;
252               case KeyEvent.VK_DOWN :
253                 viewPitch  ( transform3D,  deltaRotation );
254                 moved = true;
255                 break;
256               case KeyEvent.VK_LEFT :
257                 viewTranslate (
258                   transform3D, X, -deltaTranslation );
259                 moved = true;
260                 break;
261               case KeyEvent.VK_RIGHT:
262                 viewTranslate (
263                   transform3D, X,  deltaTranslation );
264                 moved = true;
265                 break;
266             }
267           }
268    
269           return moved;
270         }
271    
272         //////////////////////////////////////////////////////////////////////
273         //////////////////////////////////////////////////////////////////////
274         }