GL Studio C++ Runtime API
gls_matrix_affine.h
Go to the documentation of this file.
1 /*! \file
2  \brief The GlsMatrixAffine class.
3 
4  \par Copyright Information
5 
6  Copyright (c) 2017 by The DiSTI Corporation.<br>
7  11301 Corporate Blvd; Suite 100<br>
8  Orlando, Florida 32817<br>
9  USA<br>
10  <br>
11  All rights reserved.<br>
12 
13  This Software contains proprietary trade secrets of DiSTI and may not be
14 reproduced, in whole or part, in any form, or by any means of electronic,
15 mechanical, or otherwise, without the written permission of DiSTI. Said
16 permission may be derived through the purchase of applicable DiSTI product
17 licenses which detail the distribution rights of this content and any
18 Derivative Works based on this or other copyrighted DiSTI Software.
19 
20  NO WARRANTY. THE SOFTWARE IS PROVIDED "AS-IS," WITHOUT WARRANTY OF ANY KIND,
21 AND ANY USE OF THIS SOFTWARE PRODUCT IS AT YOUR OWN RISK. TO THE MAXIMUM EXTENT
22 PERMITTED BY APPLICABLE LAW, DISTI AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES
23 AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
24 IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY AND/OR FITNESS FOR A
25 PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT, WITH REGARD TO THE SOFTWARE.
26 
27  LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW,
28 IN NO EVENT SHALL DISTI OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
29 INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION,
30 DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
31 INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR
32 INABILITY TO USE THE SOFTWARE, EVEN IF DISTI HAS BEEN ADVISED OF THE POSSIBILITY
33 OF SUCH DAMAGES. DISTI'S ENTIRE LIABILITY AND YOUR EXCLUSIVE REMEDY SHALL NOT
34 EXCEED FIVE DOLLARS (US$5.00).
35 
36  The aforementioned terms and restrictions are governed by the laws of the
37 State of Florida and the United States of America.
38 
39 */
40 #ifndef GLS_MATRIXAFFINE_H
41 #define GLS_MATRIXAFFINE_H
42 
43 #include "gls_matrix.h"
44 #include "gls_quaternion.h"
45 #include "vertex.h"
46 
47 namespace disti
48 {
49 //----------------------------------------------------------------------------
50 /**
51 * The GlsMatrixAffine class provides support for a 4x4 affine transformation
52 * matrix of any numeric type. It provides ability to perform rotations,
53 * scaling, and translations. Results are cummulative, i.e. every
54 * rotate, scale, and translate call transforms the terms that already exist
55 * in the matrix. Call MakeIdentity() to start with an identity matrix, or
56 * Clear() to clear the matrix with all zeros.
57 */
58 //----------------------------------------------------------------------------
59 template<class Type>
60 class GlsMatrixAffine : public GlsMatrix<Type, 4>
61 {
62 public:
65 
66  //------------------------------------------------------------------------
67  /**
68  * Default constructor. The new matrix will be the identity matrix.
69  */
70  //------------------------------------------------------------------------
72 
73  //------------------------------------------------------------------------
74  /**
75  * Constructor.
76  *
77  * \param m a row-major, two-dimensional array used to initialize the
78  * matrix.
79  */
80  //------------------------------------------------------------------------
81  GlsMatrixAffine( const Type m[ 4 ][ 4 ] );
82 
83  //------------------------------------------------------------------------
84  /**
85  * Constructor.
86  *
87  * \param m a column-major, one-dimensional array containing all values
88  * to initialize the matrix with.
89  */
90  //------------------------------------------------------------------------
91  GlsMatrixAffine( const Type* m );
92 
93  //------------------------------------------------------------------------
94  /**
95  * Copy Constructor.
96  *
97  * \param m base class matrix to copy.
98  */
99  //------------------------------------------------------------------------
101 
102  //------------------------------------------------------------------------
103  /**
104  * Destructor.
105  */
106  //------------------------------------------------------------------------
108 
109  /** \return True if the supplied matrix is "very close" to this one.
110  */
111  bool IsVeryClose( const GlsMatrix<Type, 4>& b ) const
112  {
113  static const unsigned int SIZE = 4 * 4;
114  static const double PRECISION = 0.00001;
115 
116  for( unsigned int i = 0; i < SIZE; ++i )
117  {
118  if( fabs( this->_data[ i ] - b.Data()[ i ] ) > PRECISION )
119  return false;
120  }
121  return true;
122  }
123 
124  //------------------------------------------------------------------------
125  /**
126  * Perform a rotation transformation around a major axis around the origin,
127  * and combine this transformation with the existing matrix data.
128  *
129  * \param angle rotation angle in degrees
130  * \param axis major axis of rotation: X_AXIS, Y_AXIS, Z_AXIS
131  */
132  //------------------------------------------------------------------------
133  void Rotate( Type angle, RotationAxis axis );
134 
135  //------------------------------------------------------------------------
136  /**
137  * Perform a rotation transformation around a major axis using a specified
138  * center of rotation, and combine this transformation with the existing
139  * matrix data.
140  *
141  * \param angle rotation angle in degrees
142  * \param centerOfRotation point to rotate around
143  * \param axis major axis of rotation: X_AXIS, Y_AXIS, Z_AXIS
144  */
145  //------------------------------------------------------------------------
146  void Rotate( Type angle, const Vector& centerOfRotation, RotationAxis axis );
147 
148  //------------------------------------------------------------------------
149  /**
150  * Perform a rotation transformation around an arbitrary axis using a
151  * specified center of rotation, and combine this transformation with the
152  * existing matrix data.
153  *
154  * \param angle rotation angle in degrees
155  * \param centerOfRotation point to rotate around
156  * \param axis arbitray axis of rotation
157  */
158  //------------------------------------------------------------------------
159  void Rotate( Type angle, const Vector& centerOfRotation, const Vector& axis );
160 
161  //------------------------------------------------------------------------
162  /**
163  * Perform a scaling transformation using the origin as the anchor point,
164  * and combine this transformation with the existing matrix data.
165  *
166  * \param x scaling factor in the x direction. 1 = 100% (no scaling change)
167  * \param y scaling factor in the y direction. 1 = 100% (no scaling change)
168  * \param z scaling factor in the z direction. 1 = 100% (no scaling change)
169  */
170  //------------------------------------------------------------------------
171  void Scale( Type x, Type y, Type z );
172 
173  //------------------------------------------------------------------------
174  /**
175  * Perform a scaling transformation using an arbitrary anchor point,
176  * and combine this transformation with the existing matrix data.
177  *
178  * \param x scaling factor in the x direction. 1 = 100% (no scaling change)
179  * \param y scaling factor in the y direction. 1 = 100% (no scaling change)
180  * \param z scaling factor in the z direction. 1 = 100% (no scaling change)
181  * \param anchor The anchor point for the scaling
182  */
183  //------------------------------------------------------------------------
184  void Scale( Type x, Type y, Type z, const Vector& anchor );
185 
186  //------------------------------------------------------------------------
187  /**
188  * Perform a translation, and combine this transformation with the
189  * existing matrix data.
190  *
191  * \param x translation in the x direction
192  * \param y translation in the y direction
193  * \param z translation in the z direction
194  */
195  //------------------------------------------------------------------------
196  inline void Translate( Type x, Type y, Type z )
197  {
198  // The translation matrix is:
199  // |1 0 0 x|
200  // T = |0 1 0 y|
201  // |0 0 1 z|
202  // |0 0 0 1|
203  // We multiply it on the left: *this = T * *this;
204 
205  _matrix[ 0 ][ 0 ] += x * _matrix[ 0 ][ 3 ];
206  _matrix[ 0 ][ 1 ] += y * _matrix[ 0 ][ 3 ];
207  _matrix[ 0 ][ 2 ] += z * _matrix[ 0 ][ 3 ];
208  //_matrix[0][3] = _matrix[0][3];
209  _matrix[ 1 ][ 0 ] += x * _matrix[ 1 ][ 3 ];
210  _matrix[ 1 ][ 1 ] += y * _matrix[ 1 ][ 3 ];
211  _matrix[ 1 ][ 2 ] += z * _matrix[ 1 ][ 3 ];
212  //_matrix[1][3] = _matrix[1][3];
213  _matrix[ 2 ][ 0 ] += x * _matrix[ 2 ][ 3 ];
214  _matrix[ 2 ][ 1 ] += y * _matrix[ 2 ][ 3 ];
215  _matrix[ 2 ][ 2 ] += z * _matrix[ 2 ][ 3 ];
216  //_matrix[2][3] = _matrix[2][3];
217  _matrix[ 3 ][ 0 ] += x * _matrix[ 3 ][ 3 ];
218  _matrix[ 3 ][ 1 ] += y * _matrix[ 3 ][ 3 ];
219  _matrix[ 3 ][ 2 ] += z * _matrix[ 3 ][ 3 ];
220  //_matrix[3][3] = _matrix[3][3];
221  }
222 
223  //------------------------------------------------------------------------
224  /**
225  * Perform a translation, and combine this transformation with the
226  * existing matrix data.
227  *
228  * \param v containing the translate values
229  */
230  //------------------------------------------------------------------------
231  inline void Translate( const Vector& v ) { Translate( (Type)v.x, (Type)v.y, (Type)v.z ); }
232 
233  // LynxOS does not support 'using'
234  using _BaseClass::operator*;
235 
236  //------------------------------------------------------------------------
237  /**
238  * Return a transformed vertex using the specified vertex and the data in
239  * the matrix, e.g. w = M * v
240  */
241  //------------------------------------------------------------------------
242  inline Vector operator*( const Vector& v ) const
243  {
244  const GlsMatrix<Type, 4>& M = *this;
245  return Vector(
246  float( ( M( 0, 0 ) * v.x ) + ( M( 0, 1 ) * v.y ) + ( M( 0, 2 ) * v.z ) + M( 0, 3 ) ),
247  float( ( M( 1, 0 ) * v.x ) + ( M( 1, 1 ) * v.y ) + ( M( 1, 2 ) * v.z ) + M( 1, 3 ) ),
248  float( ( M( 2, 0 ) * v.x ) + ( M( 2, 1 ) * v.y ) + ( M( 2, 2 ) * v.z ) + M( 2, 3 ) ) );
249  }
250  inline Vertex operator*( const Vertex& v ) const
251  {
252  const GlsMatrix<Type, 4>& M = *this;
253  return Vertex(
254  float( ( M( 0, 0 ) * v.x ) + ( M( 0, 1 ) * v.y ) + ( M( 0, 2 ) * v.z ) + M( 0, 3 ) ),
255  float( ( M( 1, 0 ) * v.x ) + ( M( 1, 1 ) * v.y ) + ( M( 1, 2 ) * v.z ) + M( 1, 3 ) ),
256  float( ( M( 2, 0 ) * v.x ) + ( M( 2, 1 ) * v.y ) + ( M( 2, 2 ) * v.z ) + M( 2, 3 ) ),
257  v.color.R(),
258  v.color.G(),
259  v.color.B(),
260  v.color.A() );
261  }
262 
263  //------------------------------------------------------------------------
264  /**
265  * Transform the specified vertex using the data in the matrix, where the 4th vector component is assumed to be a 1 (position)
266  * i.e. v = M * v
267  */
268  //------------------------------------------------------------------------
269  inline void Transform( Vector& v ) const
270  {
271  // Simple version is:
272  // v = *this * v;
273 
274  // Faster version is:
275  float x = float( ( _matrix[ 0 ][ 0 ] * v.x ) + ( _matrix[ 1 ][ 0 ] * v.y ) + ( _matrix[ 2 ][ 0 ] * v.z ) + _matrix[ 3 ][ 0 ] );
276  float y = float( ( _matrix[ 0 ][ 1 ] * v.x ) + ( _matrix[ 1 ][ 1 ] * v.y ) + ( _matrix[ 2 ][ 1 ] * v.z ) + _matrix[ 3 ][ 1 ] );
277  float z = float( ( _matrix[ 0 ][ 2 ] * v.x ) + ( _matrix[ 1 ][ 2 ] * v.y ) + ( _matrix[ 2 ][ 2 ] * v.z ) + _matrix[ 3 ][ 2 ] );
278  v.x = x;
279  v.y = y;
280  v.z = z;
281  }
282 };
283 
284 /** decompose the scale factors from a GlsMatrix
285  * \param[in] m the matrix to decompose
286  * \return scale a vector that contains the x, y, and z scale factors
287  */
288 template<class Type>
290 {
291  const Vector xAxis = Vector( float( m( 0, 0 ) ), float( m( 1, 0 ) ), float( m( 2, 0 ) ) );
292  const Vector yAxis = Vector( float( m( 0, 1 ) ), float( m( 1, 1 ) ), float( m( 2, 1 ) ) );
293  const Vector zAxis = Vector( float( m( 0, 2 ) ), float( m( 1, 2 ) ), float( m( 2, 2 ) ) );
294  return Vector( xAxis.Magnitude(), yAxis.Magnitude(), zAxis.Magnitude() );
295 }
296 
297 /** decompose the rotation matrix from a GlsMatrix by dividing out the scale factor. If the x,y, or z scale is determined
298  * to be zero, the scale factors not removed from the matrix.
299  * \param[in] matrix the matrix to decompose
300  * \param[in] scale a vector that contains the x, y, and z scale factors
301  * \return the rotation matrix with the scale factors removed
302  */
303 template<class Type>
305 {
306  GlsMatrix<Type, 4> m( matrix );
307 
308  // set the translation to 0
309  m( 0, 3 ) = Type();
310  m( 1, 3 ) = Type();
311  m( 2, 3 ) = Type();
312 
313  // only decompose rotation if all scales are non-zero
314  if( 0 != scale.x && 0 != scale.y && 0 != scale.z )
315  {
316  m( 0, 0 ) /= scale.x;
317  m( 1, 0 ) /= scale.x;
318  m( 2, 0 ) /= scale.x;
319  m( 0, 1 ) /= scale.y;
320  m( 1, 1 ) /= scale.y;
321  m( 2, 1 ) /= scale.y;
322  m( 0, 2 ) /= scale.z;
323  m( 1, 2 ) /= scale.z;
324  m( 2, 2 ) /= scale.z;
325  }
326 
327  return m;
328 }
329 
330 /** decompose a GlsMatrix into its scaling, translation, and rotation counterparts. If the x,y, or z scale is determined
331  * to be zero, the rotation may not be accurate
332  * \param[in] matrix the matrix to decompose
333  * \param[out] scale a vector that contains the x, y, and z scale factors
334  * \param[out] location a vector that contains the x, y, and z translation
335  * \param[out] rotation a quaternion that contains the rotation
336  */
337 template<class Type>
338 void DecomposeMatrix( const GlsMatrix<Type, 4>& matrix, Vector& scale, Vector& location, GlsQuaternion<Type>& rotation )
339 {
340  scale = DecomposeScale( matrix );
341 
342  // decompose location
343  location = Vector( float( matrix( 0, 3 ) ), float( matrix( 1, 3 ) ), float( matrix( 2, 3 ) ) );
344 
345  rotation = GlsQuaternion<Type>( DecomposeRotationMatrix( matrix, scale ) );
346 }
347 
348 typedef GlsMatrixAffine<float> GlsMatrixAffineF;
349 typedef GlsMatrixAffine<double> GlsMatrixAffineD;
350 
351 //============================================================================
352 //
353 // CLASS IMPLEMENTATION
354 //
355 //============================================================================
356 
357 //----------------------------------------------------------------------------
358 template<class Type>
360 {
361 }
362 //----------------------------------------------------------------------------
363 template<class Type>
364 GlsMatrixAffine<Type>::GlsMatrixAffine( const Type m[ 4 ][ 4 ] )
365  : GlsMatrix<Type, 4>( m )
366 {
367 }
368 //----------------------------------------------------------------------------
369 template<class Type>
371  : GlsMatrix<Type, 4>( m )
372 {
373 }
374 //----------------------------------------------------------------------------
375 template<class Type>
377  : GlsMatrix<Type, 4>( m )
378 {
379 }
380 //----------------------------------------------------------------------------
381 template<class Type>
383 {
384 }
385 
386 //----------------------------------------------------------------------------
387 template<class Type>
389 {
390  // Find the sine and cosine of the angle of rotation to be used
391  // in the rotation transform matrix.
392  const double a( double( angle ) * DEG_TO_RAD );
393  const Type sina( (Type)sin( a ) );
394  const Type cosa( (Type)cos( a ) );
395 
396  Type temp;
397 
398  switch( axis )
399  {
400  case X_AXIS:
401  {
402  // The rotation matrix for rotation about the x axis is
403  // |1 0 0 0|
404  // R = |0 cos(a) -sin(a) 0|
405  // |0 sin(a) cos(a) 0|
406  // |0 0 0 1|
407 
408  // Multiply the current matrix by the rotation transformation
409  // *this = R * *this;
410 
411  temp = _matrix[ 0 ][ 1 ];
412  _matrix[ 0 ][ 1 ] = temp * cosa - _matrix[ 0 ][ 2 ] * sina;
413  _matrix[ 0 ][ 2 ] = temp * sina + _matrix[ 0 ][ 2 ] * cosa;
414  temp = _matrix[ 1 ][ 1 ];
415  _matrix[ 1 ][ 1 ] = temp * cosa - _matrix[ 1 ][ 2 ] * sina;
416  _matrix[ 1 ][ 2 ] = temp * sina + _matrix[ 1 ][ 2 ] * cosa;
417  temp = _matrix[ 2 ][ 1 ];
418  _matrix[ 2 ][ 1 ] = temp * cosa - _matrix[ 2 ][ 2 ] * sina;
419  _matrix[ 2 ][ 2 ] = temp * sina + _matrix[ 2 ][ 2 ] * cosa;
420  temp = _matrix[ 3 ][ 1 ];
421  _matrix[ 3 ][ 1 ] = temp * cosa - _matrix[ 3 ][ 2 ] * sina;
422  _matrix[ 3 ][ 2 ] = temp * sina + _matrix[ 3 ][ 2 ] * cosa;
423 
424  break;
425  }
426  case Y_AXIS:
427  {
428  // The rotation matrix for rotation about the y axis is
429  // | cos(a) 0 sin(a) 0|
430  // R = | 0 1 0 0|
431  // |-sin(a) 0 cos(a) 0|
432  // | 0 0 0 1|
433 
434  // Multiply the current matrix by the rotation transformation
435  // *this = R * *this;
436 
437  temp = _matrix[ 0 ][ 0 ];
438  _matrix[ 0 ][ 0 ] = temp * cosa + _matrix[ 0 ][ 2 ] * sina;
439  _matrix[ 0 ][ 2 ] = _matrix[ 0 ][ 2 ] * cosa - temp * sina;
440  temp = _matrix[ 1 ][ 0 ];
441  _matrix[ 1 ][ 0 ] = temp * cosa + _matrix[ 1 ][ 2 ] * sina;
442  _matrix[ 1 ][ 2 ] = _matrix[ 1 ][ 2 ] * cosa - temp * sina;
443  temp = _matrix[ 2 ][ 0 ];
444  _matrix[ 2 ][ 0 ] = temp * cosa + _matrix[ 2 ][ 2 ] * sina;
445  _matrix[ 2 ][ 2 ] = _matrix[ 2 ][ 2 ] * cosa - temp * sina;
446  temp = _matrix[ 3 ][ 0 ];
447  _matrix[ 3 ][ 0 ] = temp * cosa + _matrix[ 3 ][ 2 ] * sina;
448  _matrix[ 3 ][ 2 ] = _matrix[ 3 ][ 2 ] * cosa - temp * sina;
449 
450  break;
451  }
452  case Z_AXIS:
453  {
454  // The rotation matrix for rotation about the z axis is
455  // |cos(a) sin(a) 0 0|
456  // R = |-sin(a) cos(a) 0 0|
457  // | 0 0 1 0|
458  // | 0 0 0 1|
459 
460  // Multiply the current matrix by the rotation transformation
461  // *this = R * *this;
462 
463  temp = _matrix[ 0 ][ 0 ];
464  _matrix[ 0 ][ 0 ] = temp * cosa - _matrix[ 0 ][ 1 ] * sina;
465  _matrix[ 0 ][ 1 ] = temp * sina + _matrix[ 0 ][ 1 ] * cosa;
466  temp = _matrix[ 1 ][ 0 ];
467  _matrix[ 1 ][ 0 ] = temp * cosa - _matrix[ 1 ][ 1 ] * sina;
468  _matrix[ 1 ][ 1 ] = temp * sina + _matrix[ 1 ][ 1 ] * cosa;
469  temp = _matrix[ 2 ][ 0 ];
470  _matrix[ 2 ][ 0 ] = temp * cosa - _matrix[ 2 ][ 1 ] * sina;
471  _matrix[ 2 ][ 1 ] = temp * sina + _matrix[ 2 ][ 1 ] * cosa;
472  temp = _matrix[ 3 ][ 0 ];
473  _matrix[ 3 ][ 0 ] = temp * cosa - _matrix[ 3 ][ 1 ] * sina;
474  _matrix[ 3 ][ 1 ] = temp * sina + _matrix[ 3 ][ 1 ] * cosa;
475 
476  break;
477  }
478  }
479 }
480 //----------------------------------------------------------------------------
481 template<class Type>
483  const Vector& centerOfRotation,
484  RotationAxis axis )
485 {
486  // First, we must translate the center of rotation to the origin,
487  // perform the rotation and then translate back to the center of
488  // rotation.
489 
490  // Find the sine and cosine of the angle of rotation to be used
491  // in the rotation transform matrix.
492  const double a( double( angle ) * DEG_TO_RAD );
493  const Type sina( (Type)sin( a ) );
494  const Type cosa( (Type)cos( a ) );
495 
496  Type temp;
497 
498  switch( axis )
499  {
500  case X_AXIS:
501  {
502  // The rotation matrix for rotation about the x axis is
503  // |1 0 0 0|
504  // R = |0 cos(a) -sin(a) 0|
505  // |0 sin(a) cos(a) 0|
506  // |0 0 0 1|
507  //
508  // The total transformation T is:
509  // |1 0 0 x-x |
510  // T = |0 R11 R12 (-R11*y-R12*z)+y |
511  // |0 R21 R22 (-R21*y-R22*z)+z |
512  // |0 0 0 1 |
513  const Type T11( cosa ), T12( -sina ), T21( sina ), T22( cosa ),
514  // T03( centerOfRotation.x-centerOfRotation.x ),
515  T13( centerOfRotation.y - ( cosa * centerOfRotation.y - sina * centerOfRotation.z ) ),
516  T23( centerOfRotation.z - ( sina * centerOfRotation.y + cosa * centerOfRotation.z ) );
517 
518  // Multiply by the transformation matrix
519  // *this = T * *this;
520  temp = _matrix[ 0 ][ 1 ];
521  _matrix[ 0 ][ 1 ] = temp * T11 + _matrix[ 0 ][ 2 ] * T12 + _matrix[ 0 ][ 3 ] * T13;
522  _matrix[ 0 ][ 2 ] = temp * T21 + _matrix[ 0 ][ 2 ] * T22 + _matrix[ 0 ][ 3 ] * T23;
523  temp = _matrix[ 1 ][ 1 ];
524  _matrix[ 1 ][ 1 ] = temp * T11 + _matrix[ 1 ][ 2 ] * T12 + _matrix[ 1 ][ 3 ] * T13;
525  _matrix[ 1 ][ 2 ] = temp * T21 + _matrix[ 1 ][ 2 ] * T22 + _matrix[ 1 ][ 3 ] * T23;
526  temp = _matrix[ 2 ][ 1 ];
527  _matrix[ 2 ][ 1 ] = temp * T11 + _matrix[ 2 ][ 2 ] * T12 + _matrix[ 2 ][ 3 ] * T13;
528  _matrix[ 2 ][ 2 ] = temp * T21 + _matrix[ 2 ][ 2 ] * T22 + _matrix[ 2 ][ 3 ] * T23;
529  temp = _matrix[ 3 ][ 1 ];
530  _matrix[ 3 ][ 1 ] = temp * T11 + _matrix[ 3 ][ 2 ] * T12 + _matrix[ 3 ][ 3 ] * T13;
531  _matrix[ 3 ][ 2 ] = temp * T21 + _matrix[ 3 ][ 2 ] * T22 + _matrix[ 3 ][ 3 ] * T23;
532 
533  break;
534  }
535  case Y_AXIS:
536  {
537  // The rotation matrix for rotation about the y axis is
538  // | cos(a) 0 sin(a) 0|
539  // R = | 0 1 0 0|
540  // |-sin(a) 0 cos(a) 0|
541  // | 0 0 0 1|
542  //
543  // The total transformation T is:
544  // |R00 0 R02 (-R00*x-R02*z)+x |
545  // T = | 0 1 0 y-y |
546  // |R20 0 R22 (-R20*x-R22*z)+z |
547  // | 0 0 0 1 |
548  const Type T00( cosa ), T02( sina ), T20( -sina ), T22( cosa ),
549  T03( centerOfRotation.x - ( sina * centerOfRotation.z + cosa * centerOfRotation.x ) ),
550  // T13( centerOfRotation.y-centerOfRotation.y ),
551  T23( centerOfRotation.z - ( cosa * centerOfRotation.z - sina * centerOfRotation.x ) );
552 
553  // Multiply by the transformation matrix
554  // *this = T * *this;
555  temp = _matrix[ 0 ][ 0 ];
556  _matrix[ 0 ][ 0 ] = temp * T00 + _matrix[ 0 ][ 2 ] * T02 + _matrix[ 0 ][ 3 ] * T03;
557  _matrix[ 0 ][ 2 ] = temp * T20 + _matrix[ 0 ][ 2 ] * T22 + _matrix[ 0 ][ 3 ] * T23;
558  temp = _matrix[ 1 ][ 0 ];
559  _matrix[ 1 ][ 0 ] = temp * T00 + _matrix[ 1 ][ 2 ] * T02 + _matrix[ 1 ][ 3 ] * T03;
560  _matrix[ 1 ][ 2 ] = temp * T20 + _matrix[ 1 ][ 2 ] * T22 + _matrix[ 1 ][ 3 ] * T23;
561  temp = _matrix[ 2 ][ 0 ];
562  _matrix[ 2 ][ 0 ] = temp * T00 + _matrix[ 2 ][ 2 ] * T02 + _matrix[ 2 ][ 3 ] * T03;
563  _matrix[ 2 ][ 2 ] = temp * T20 + _matrix[ 2 ][ 2 ] * T22 + _matrix[ 2 ][ 3 ] * T23;
564  temp = _matrix[ 3 ][ 0 ];
565  _matrix[ 3 ][ 0 ] = temp * T00 + _matrix[ 3 ][ 2 ] * T02 + _matrix[ 3 ][ 3 ] * T03;
566  _matrix[ 3 ][ 2 ] = temp * T20 + _matrix[ 3 ][ 2 ] * T22 + _matrix[ 3 ][ 3 ] * T23;
567 
568  break;
569  }
570  case Z_AXIS:
571  {
572  // The rotation matrix for rotation about the z axis is
573  // |cos(a) -sin(a) 0 0|
574  // R = |sin(a) cos(a) 0 0|
575  // | 0 0 1 0|
576  // | 0 0 0 1|
577  //
578  // The total transformation T is:
579  // |R00 R01 0 (-R00*x-R01*y)+x |
580  // T = |R10 R11 0 (-R10*x-R11*y)+y |
581  // | 0 0 1 z-z |
582  // | 0 0 0 1 |
583  const Type T00( cosa ), T01( -sina ), T10( sina ), T11( cosa ),
584  T03( centerOfRotation.x - ( cosa * centerOfRotation.x - sina * centerOfRotation.y ) ),
585  T13( centerOfRotation.y - ( sina * centerOfRotation.x + cosa * centerOfRotation.y ) );
586  // T23( centerOfRotation.z-centerOfRotation.z );
587 
588  // Multiply by the transformation matrix
589  // *this = T * *this;
590  temp = _matrix[ 0 ][ 0 ];
591  _matrix[ 0 ][ 0 ] = temp * T00 + _matrix[ 0 ][ 1 ] * T01 + _matrix[ 0 ][ 3 ] * T03;
592  _matrix[ 0 ][ 1 ] = temp * T10 + _matrix[ 0 ][ 1 ] * T11 + _matrix[ 0 ][ 3 ] * T13;
593  temp = _matrix[ 1 ][ 0 ];
594  _matrix[ 1 ][ 0 ] = temp * T00 + _matrix[ 1 ][ 1 ] * T01 + _matrix[ 1 ][ 3 ] * T03;
595  _matrix[ 1 ][ 1 ] = temp * T10 + _matrix[ 1 ][ 1 ] * T11 + _matrix[ 1 ][ 3 ] * T13;
596  temp = _matrix[ 2 ][ 0 ];
597  _matrix[ 2 ][ 0 ] = temp * T00 + _matrix[ 2 ][ 1 ] * T01 + _matrix[ 2 ][ 3 ] * T03;
598  _matrix[ 2 ][ 1 ] = temp * T10 + _matrix[ 2 ][ 1 ] * T11 + _matrix[ 2 ][ 3 ] * T13;
599  temp = _matrix[ 3 ][ 0 ];
600  _matrix[ 3 ][ 0 ] = temp * T00 + _matrix[ 3 ][ 1 ] * T01 + _matrix[ 3 ][ 3 ] * T03;
601  _matrix[ 3 ][ 1 ] = temp * T10 + _matrix[ 3 ][ 1 ] * T11 + _matrix[ 3 ][ 3 ] * T13;
602 
603  break;
604  }
605  }
606 }
607 //----------------------------------------------------------------------------
608 template<class Type>
610  const Vector& centerOfRotation,
611  const Vector& axis )
612 {
613  // Normalize the arbitrary axis into a unit vector to be used in the
614  // calculations for the terms of the rotation matrix. Only perform
615  // the rotation if the length of the axis vector is not zero.
616  Vector u( axis );
617  u.Normalize();
618 
619  if( u.MagnitudeSquared() != 0 )
620  {
621  // The following describes the theory used to determine the rotation
622  // matrix for a rotation around an arbitrary axis:
623  //
624  // Definitions:
625  //
626  // The "dual matrix" of a vector u(x,y,z) is S, where
627  // | 0 -z y |
628  // S = | z 0 -x |
629  // |-y x 0 |
630  //
631  // The "outer product" of a vector u with itself (where uT is
632  // the transpose of u) is:
633  // |x| |xx xy xz|
634  // uuT = |y||x y z| = |xy yy yz|
635  // |z| |xz yz zz|
636  //
637  // Suppose we have a unit direction vector, u, then we can derive
638  // a rotation by a given angle about this axis:
639  //
640  // R(a,u) = uuT + (I - uuT) * cos(a) + S * sin(a)
641  //
642  // where I is the identity matrix. This actually produces a 3x3
643  // matrix which we just need to add the 4th column and row to so
644  // that we can use it for affine transformations.
645 
646  // Calculate some constants from uuT
647  const Type xx( Type( u.x * u.x ) );
648  const Type yy( Type( u.y * u.y ) );
649  const Type zz( Type( u.z * u.z ) );
650  const Type xy( Type( u.x * u.y ) );
651  const Type xz( Type( u.x * u.z ) );
652  const Type yz( Type( u.y * u.z ) );
653 
654  // Calculate the sine and cosine of the rotation angle for use
655  // in the calculation of the rotation matrix.
656  const double a( double( angle ) * DEG_TO_RAD );
657  const Type sina( (Type)sin( a ) );
658  const Type cosa( (Type)cos( a ) );
659 
660  // Now calculate M, which is the 3x3 version of the rotation
661  // matrix using the formula for rotation about an arbitrary axis.
662  // GlsMatrix<Type,3> M = UUT + ((I - UUT) * cosa) + (S * sina);
663 
664  // Assign M to the first 3 columns and rows of the final rotation
665  // matrix R.
667 
668  R( 0, 0 ) = xx + ( 1 - xx ) * cosa;
669  R( 1, 0 ) = xy - xy * cosa + u.z * sina;
670  R( 2, 0 ) = xz - xz * cosa - u.y * sina;
671 
672  R( 0, 1 ) = xy - xy * cosa - u.z * sina;
673  R( 1, 1 ) = yy + ( 1 - yy ) * cosa;
674  R( 2, 1 ) = yz - yz * cosa + u.x * sina;
675 
676  R( 0, 2 ) = xz - xz * cosa + u.y * sina;
677  R( 1, 2 ) = yz - yz * cosa - u.x * sina;
678  R( 2, 2 ) = zz + ( 1 - zz ) * cosa;
679 
680  // Multiply the current matrix by the translation, then the rotation,
681  // and then translate back using the inverse.
682  // *this = TInv * R * T * *this;
683  this->Translate( -centerOfRotation.x, -centerOfRotation.y, -centerOfRotation.z );
684  *this = R * *this;
685  this->Translate( centerOfRotation.x, centerOfRotation.y, centerOfRotation.z );
686  }
687 }
688 //----------------------------------------------------------------------------
689 template<class Type>
690 void GlsMatrixAffine<Type>::Scale( Type x, Type y, Type z )
691 {
692  // The scaling matrix, where x, y, and z are on the diagonal.
693  // x 0 0 0
694  // 0 y 0 0
695  // 0 0 z 0
696  // 0 0 0 1
697  // As can be seen most of the matrix is zero
698  // So optimized
699 
700  _matrix[ 0 ][ 0 ] = _matrix[ 0 ][ 0 ] * x;
701  _matrix[ 0 ][ 1 ] = _matrix[ 0 ][ 1 ] * y;
702  _matrix[ 0 ][ 2 ] = _matrix[ 0 ][ 2 ] * z;
703  //_matrix[0][3] = _matrix[0][3];
704 
705  _matrix[ 1 ][ 0 ] = _matrix[ 1 ][ 0 ] * x;
706  _matrix[ 1 ][ 1 ] = _matrix[ 1 ][ 1 ] * y;
707  _matrix[ 1 ][ 2 ] = _matrix[ 1 ][ 2 ] * z;
708  //_matrix[1][3] = _matrix[1][3];
709 
710  _matrix[ 2 ][ 0 ] = _matrix[ 2 ][ 0 ] * x;
711  _matrix[ 2 ][ 1 ] = _matrix[ 2 ][ 1 ] * y;
712  _matrix[ 2 ][ 2 ] = _matrix[ 2 ][ 2 ] * z;
713  //_matrix[2][3] = _matrix[2][3];
714 
715  _matrix[ 3 ][ 0 ] = _matrix[ 3 ][ 0 ] * x;
716  _matrix[ 3 ][ 1 ] = _matrix[ 3 ][ 1 ] * y;
717  _matrix[ 3 ][ 2 ] = _matrix[ 3 ][ 2 ] * z;
718  //_matrix[3][3] = _matrix[3][3];
719 
720  // Row 3 is multiplied by 1, so no need...
721 }
722 //----------------------------------------------------------------------------
723 template<class Type>
724 void GlsMatrixAffine<Type>::Scale( Type x, Type y, Type z, const Vector& anchor )
725 {
726  // First, we must translate the anchor point to the origin,
727  // perform the scaling and then translate back to the anchor
728  // point. This is the transformation matrix we are multiplying by:
729  // (Ax, Ay, Az are the components of anchor)
730  // | x 0 0 Ax-x*Ax |
731  // T = | 0 y 0 Ay-y*Ay |
732  // | 0 0 z Az-z*Az |
733  // | 0 0 0 1 |
734  const Type T00 = x;
735  const Type T11 = y;
736  const Type T22 = z;
737  const Type T03 = anchor.x * ( 1 - x );
738  const Type T13 = anchor.y * ( 1 - y );
739  const Type T23 = anchor.z * ( 1 - z );
740 
741  // Multiply the current matrix by the transformation
742  // *this = T * *this;
743 
744  _matrix[ 0 ][ 0 ] = _matrix[ 0 ][ 0 ] * T00 + _matrix[ 0 ][ 3 ] * T03;
745  _matrix[ 0 ][ 1 ] = _matrix[ 0 ][ 1 ] * T11 + _matrix[ 0 ][ 3 ] * T13;
746  _matrix[ 0 ][ 2 ] = _matrix[ 0 ][ 2 ] * T22 + _matrix[ 0 ][ 3 ] * T23;
747  //_matrix[0][3] = _matrix[0][3];
748 
749  _matrix[ 1 ][ 0 ] = _matrix[ 1 ][ 0 ] * T00 + _matrix[ 1 ][ 3 ] * T03;
750  _matrix[ 1 ][ 1 ] = _matrix[ 1 ][ 1 ] * T11 + _matrix[ 1 ][ 3 ] * T13;
751  _matrix[ 1 ][ 2 ] = _matrix[ 1 ][ 2 ] * T22 + _matrix[ 1 ][ 3 ] * T23;
752  //_matrix[1][3] = _matrix[1][3];
753 
754  _matrix[ 2 ][ 0 ] = _matrix[ 2 ][ 0 ] * T00 + _matrix[ 2 ][ 3 ] * T03;
755  _matrix[ 2 ][ 1 ] = _matrix[ 2 ][ 1 ] * T11 + _matrix[ 2 ][ 3 ] * T13;
756  _matrix[ 2 ][ 2 ] = _matrix[ 2 ][ 2 ] * T22 + _matrix[ 2 ][ 3 ] * T23;
757  //_matrix[2][3] = _matrix[2][3];
758 
759  _matrix[ 3 ][ 0 ] = _matrix[ 3 ][ 0 ] * T00 + _matrix[ 3 ][ 3 ] * T03;
760  _matrix[ 3 ][ 1 ] = _matrix[ 3 ][ 1 ] * T11 + _matrix[ 3 ][ 3 ] * T13;
761  _matrix[ 3 ][ 2 ] = _matrix[ 3 ][ 2 ] * T22 + _matrix[ 3 ][ 3 ] * T23;
762  //_matrix[3][3] = _matrix[3][3];
763 }
764 
765 //----------------------------------------------------------------------------
766 
767 #ifdef MATRIX_TYPE_FLOAT
768 typedef float GlsMatrixElementType;
769 typedef GlsMatrixAffineF GlsMatrixType;
770 # define GLS_glLoadMatrix_TYPE glLoadMatrixf
771 # define GLS_glMultMatrix_TYPE glMultMatrixf
772 #else
773 typedef double GlsMatrixElementType;
774 typedef GlsMatrixAffineD GlsMatrixType;
775 # define GLS_glLoadMatrix_TYPE glLoadMatrixd
776 # define GLS_glMultMatrix_TYPE glMultMatrixd
777 #endif
778 
779 } // namespace disti
780 
781 #endif
Definition: vertex.h:408
RotationAxis
Definition: vertex.h:72
unsigned char R(void) const
Definition: gls_color.h:208
Definition: gls_matrix.h:61
float MagnitudeSquared() const
Definition: vertex.h:334
unsigned char B(void) const
Definition: gls_color.h:214
The GlsMatrix class.
void Normalize(void)
Definition: vertex.h:307
static const double PRECISION
Definition: gls_matrix.h:313
Type * _matrix[DIM]
Definition: gls_matrix.h:334
void Translate(const Vector &v)
Definition: gls_matrix_affine.h:231
Definition: vertex.h:74
GlsMatrix< Type, 4 > DecomposeRotationMatrix(const GlsMatrix< Type, 4 > &matrix, const Vector &scale)
Definition: gls_matrix_affine.h:304
void Transform(Vector &v) const
Definition: gls_matrix_affine.h:269
VertexNoColor Vector
Definition: gls_font_base.h:66
Type _data[DIM *DIM]
Definition: gls_matrix.h:322
The disti::Vertex class. A class for manipulating 3D vertices.
unsigned char G(void) const
Definition: gls_color.h:211
Type * Data()
Definition: gls_matrix.h:131
void Translate(Type x, Type y, Type z)
Definition: gls_matrix_affine.h:196
void DecomposeMatrix(const GlsMatrix< Type, 4 > &matrix, Vector &scale, Vector &location, GlsQuaternion< Type > &rotation)
Definition: gls_matrix_affine.h:338
~GlsMatrixAffine()
Definition: gls_matrix_affine.h:382
void Rotate(Type angle, RotationAxis axis)
Definition: gls_matrix_affine.h:388
Vector DecomposeScale(const GlsMatrix< Type, 4 > &m)
Definition: gls_matrix_affine.h:289
Definition: vertex.h:83
Definition: gls_quaternion.h:59
The disti::GlsQuaternion class.
float Magnitude() const
Definition: vertex.h:326
unsigned char A(void) const
Definition: gls_color.h:217
Definition: vertex.h:76
Definition: vertex.h:75
bool IsVeryClose(const GlsMatrix< Type, 4 > &b) const
Definition: gls_matrix_affine.h:111
Definition: bmpimage.h:46
void Scale(Type x, Type y, Type z)
Definition: gls_matrix_affine.h:690
Vector operator*(const Vector &v) const
Definition: gls_matrix_affine.h:242
Definition: gls_matrix_affine.h:60
GlsMatrixAffine()
Definition: gls_matrix_affine.h:359