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:
64  DISTI_DEPRECATED( "This identifier is forbidden by the C++ standard. Use BaseClass instead." )
67 
68  //------------------------------------------------------------------------
69  /**
70  * Default constructor. The new matrix will be the identity matrix.
71  */
72  //------------------------------------------------------------------------
74 
75  //------------------------------------------------------------------------
76  /**
77  * Constructor.
78  *
79  * \param m a row-major, two-dimensional array used to initialize the
80  * matrix.
81  */
82  //------------------------------------------------------------------------
83  GlsMatrixAffine( const Type m[ 4 ][ 4 ] );
84 
85  //------------------------------------------------------------------------
86  /**
87  * Constructor.
88  *
89  * \param m a column-major, one-dimensional array containing all values
90  * to initialize the matrix with.
91  */
92  //------------------------------------------------------------------------
93  GlsMatrixAffine( const Type* m );
94 
95  //------------------------------------------------------------------------
96  /**
97  * Copy Constructor.
98  *
99  * \param m base class matrix to copy.
100  */
101  //------------------------------------------------------------------------
103 
104  //------------------------------------------------------------------------
105  /**
106  * Destructor.
107  */
108  //------------------------------------------------------------------------
110 
111  /** \return True if the supplied matrix is "very close" to this one.
112  */
113  bool IsVeryClose( const GlsMatrix<Type, 4>& b ) const
114  {
115  static const unsigned int SIZE = 4 * 4;
116  static const double PRECISION = 0.00001;
117 
118  for( unsigned int i = 0; i < SIZE; ++i )
119  {
120  if( fabs( this->_data[ i ] - b.Data()[ i ] ) > PRECISION )
121  return false;
122  }
123  return true;
124  }
125 
126  //------------------------------------------------------------------------
127  /**
128  * Perform a rotation transformation around a major axis around the origin,
129  * and combine this transformation with the existing matrix data.
130  *
131  * \param angle rotation angle in degrees
132  * \param axis major axis of rotation: X_AXIS, Y_AXIS, Z_AXIS
133  */
134  //------------------------------------------------------------------------
135  void Rotate( Type angle, RotationAxis axis );
136 
137  //------------------------------------------------------------------------
138  /**
139  * Perform a rotation transformation around a major axis using a specified
140  * center of rotation, and combine this transformation with the existing
141  * matrix data.
142  *
143  * \param angle rotation angle in degrees
144  * \param centerOfRotation point to rotate around
145  * \param axis major axis of rotation: X_AXIS, Y_AXIS, Z_AXIS
146  */
147  //------------------------------------------------------------------------
148  void Rotate( Type angle, const Vector& centerOfRotation, RotationAxis axis );
149 
150  //------------------------------------------------------------------------
151  /**
152  * Perform a rotation transformation around an arbitrary axis using a
153  * specified center of rotation, and combine this transformation with the
154  * existing matrix data.
155  *
156  * \param angle rotation angle in degrees
157  * \param centerOfRotation point to rotate around
158  * \param axis arbitray axis of rotation
159  */
160  //------------------------------------------------------------------------
161  void Rotate( Type angle, const Vector& centerOfRotation, const Vector& axis );
162 
163  //------------------------------------------------------------------------
164  /**
165  * Perform a scaling transformation using the origin as the anchor point,
166  * and combine this transformation with the existing matrix data.
167  *
168  * \param x scaling factor in the x direction. 1 = 100% (no scaling change)
169  * \param y scaling factor in the y direction. 1 = 100% (no scaling change)
170  * \param z scaling factor in the z direction. 1 = 100% (no scaling change)
171  */
172  //------------------------------------------------------------------------
173  void Scale( Type x, Type y, Type z );
174 
175  //------------------------------------------------------------------------
176  /**
177  * Perform a scaling transformation using an arbitrary anchor point,
178  * and combine this transformation with the existing matrix data.
179  *
180  * \param x scaling factor in the x direction. 1 = 100% (no scaling change)
181  * \param y scaling factor in the y direction. 1 = 100% (no scaling change)
182  * \param z scaling factor in the z direction. 1 = 100% (no scaling change)
183  * \param anchor The anchor point for the scaling
184  */
185  //------------------------------------------------------------------------
186  void Scale( Type x, Type y, Type z, const Vector& anchor );
187 
188  //------------------------------------------------------------------------
189  /**
190  * Perform a translation, and combine this transformation with the
191  * existing matrix data.
192  *
193  * \param x translation in the x direction
194  * \param y translation in the y direction
195  * \param z translation in the z direction
196  */
197  //------------------------------------------------------------------------
198  inline void Translate( Type x, Type y, Type z )
199  {
200  // The translation matrix is:
201  // |1 0 0 x|
202  // T = |0 1 0 y|
203  // |0 0 1 z|
204  // |0 0 0 1|
205  // We multiply it on the left: *this = T * *this;
206 
207  _matrix[ 0 ][ 0 ] += x * _matrix[ 0 ][ 3 ];
208  _matrix[ 0 ][ 1 ] += y * _matrix[ 0 ][ 3 ];
209  _matrix[ 0 ][ 2 ] += z * _matrix[ 0 ][ 3 ];
210  //_matrix[0][3] = _matrix[0][3];
211  _matrix[ 1 ][ 0 ] += x * _matrix[ 1 ][ 3 ];
212  _matrix[ 1 ][ 1 ] += y * _matrix[ 1 ][ 3 ];
213  _matrix[ 1 ][ 2 ] += z * _matrix[ 1 ][ 3 ];
214  //_matrix[1][3] = _matrix[1][3];
215  _matrix[ 2 ][ 0 ] += x * _matrix[ 2 ][ 3 ];
216  _matrix[ 2 ][ 1 ] += y * _matrix[ 2 ][ 3 ];
217  _matrix[ 2 ][ 2 ] += z * _matrix[ 2 ][ 3 ];
218  //_matrix[2][3] = _matrix[2][3];
219  _matrix[ 3 ][ 0 ] += x * _matrix[ 3 ][ 3 ];
220  _matrix[ 3 ][ 1 ] += y * _matrix[ 3 ][ 3 ];
221  _matrix[ 3 ][ 2 ] += z * _matrix[ 3 ][ 3 ];
222  //_matrix[3][3] = _matrix[3][3];
223  }
224 
225  //------------------------------------------------------------------------
226  /**
227  * Perform a translation, and combine this transformation with the
228  * existing matrix data.
229  *
230  * \param v containing the translate values
231  */
232  //------------------------------------------------------------------------
233  inline void Translate( const Vector& v ) { Translate( (Type)v.x, (Type)v.y, (Type)v.z ); }
234 
235  // LynxOS does not support 'using'
236  using BaseClass::operator*;
237 
238  //------------------------------------------------------------------------
239  /**
240  * Return a transformed vertex using the specified vertex and the data in
241  * the matrix, e.g. w = M * v
242  */
243  //------------------------------------------------------------------------
244  inline Vector operator*( const Vector& v ) const
245  {
246  const GlsMatrix<Type, 4>& M = *this;
247  return Vector(
248  float( ( M( 0, 0 ) * v.x ) + ( M( 0, 1 ) * v.y ) + ( M( 0, 2 ) * v.z ) + M( 0, 3 ) ),
249  float( ( M( 1, 0 ) * v.x ) + ( M( 1, 1 ) * v.y ) + ( M( 1, 2 ) * v.z ) + M( 1, 3 ) ),
250  float( ( M( 2, 0 ) * v.x ) + ( M( 2, 1 ) * v.y ) + ( M( 2, 2 ) * v.z ) + M( 2, 3 ) ) );
251  }
252  inline Vertex operator*( const Vertex& v ) const
253  {
254  const GlsMatrix<Type, 4>& M = *this;
255  return Vertex(
256  float( ( M( 0, 0 ) * v.x ) + ( M( 0, 1 ) * v.y ) + ( M( 0, 2 ) * v.z ) + M( 0, 3 ) ),
257  float( ( M( 1, 0 ) * v.x ) + ( M( 1, 1 ) * v.y ) + ( M( 1, 2 ) * v.z ) + M( 1, 3 ) ),
258  float( ( M( 2, 0 ) * v.x ) + ( M( 2, 1 ) * v.y ) + ( M( 2, 2 ) * v.z ) + M( 2, 3 ) ),
259  v.color.R(),
260  v.color.G(),
261  v.color.B(),
262  v.color.A() );
263  }
264 
265  //------------------------------------------------------------------------
266  /**
267  * Transform the specified vertex using the data in the matrix, where the 4th vector component is assumed to be a 1 (position)
268  * i.e. v = M * v
269  */
270  //------------------------------------------------------------------------
271  inline void Transform( Vector& v ) const
272  {
273  // Simple version is:
274  // v = *this * v;
275 
276  // Faster version is:
277  float x = float( ( _matrix[ 0 ][ 0 ] * v.x ) + ( _matrix[ 1 ][ 0 ] * v.y ) + ( _matrix[ 2 ][ 0 ] * v.z ) + _matrix[ 3 ][ 0 ] );
278  float y = float( ( _matrix[ 0 ][ 1 ] * v.x ) + ( _matrix[ 1 ][ 1 ] * v.y ) + ( _matrix[ 2 ][ 1 ] * v.z ) + _matrix[ 3 ][ 1 ] );
279  float z = float( ( _matrix[ 0 ][ 2 ] * v.x ) + ( _matrix[ 1 ][ 2 ] * v.y ) + ( _matrix[ 2 ][ 2 ] * v.z ) + _matrix[ 3 ][ 2 ] );
280  v.x = x;
281  v.y = y;
282  v.z = z;
283  }
284 };
285 
286 /** decompose the scale factors from a GlsMatrix
287  * \param[in] m the matrix to decompose
288  * \return scale a vector that contains the x, y, and z scale factors
289  */
290 template<class Type>
292 {
293  const Vector xAxis = Vector( float( m( 0, 0 ) ), float( m( 1, 0 ) ), float( m( 2, 0 ) ) );
294  const Vector yAxis = Vector( float( m( 0, 1 ) ), float( m( 1, 1 ) ), float( m( 2, 1 ) ) );
295  const Vector zAxis = Vector( float( m( 0, 2 ) ), float( m( 1, 2 ) ), float( m( 2, 2 ) ) );
296  return Vector( xAxis.Magnitude(), yAxis.Magnitude(), zAxis.Magnitude() );
297 }
298 
299 /** decompose the rotation matrix from a GlsMatrix by dividing out the scale factor. If the x,y, or z scale is determined
300  * to be zero, the scale factors not removed from the matrix.
301  * \param[in] matrix the matrix to decompose
302  * \param[in] scale a vector that contains the x, y, and z scale factors
303  * \return the rotation matrix with the scale factors removed
304  */
305 template<class Type>
307 {
308  GlsMatrix<Type, 4> m( matrix );
309 
310  // set the translation to 0
311  m( 0, 3 ) = Type();
312  m( 1, 3 ) = Type();
313  m( 2, 3 ) = Type();
314 
315  // only decompose rotation if all scales are non-zero
316  if( 0 != scale.x && 0 != scale.y && 0 != scale.z )
317  {
318  m( 0, 0 ) /= scale.x;
319  m( 1, 0 ) /= scale.x;
320  m( 2, 0 ) /= scale.x;
321  m( 0, 1 ) /= scale.y;
322  m( 1, 1 ) /= scale.y;
323  m( 2, 1 ) /= scale.y;
324  m( 0, 2 ) /= scale.z;
325  m( 1, 2 ) /= scale.z;
326  m( 2, 2 ) /= scale.z;
327  }
328 
329  return m;
330 }
331 
332 /** decompose a GlsMatrix into its scaling, translation, and rotation counterparts. If the x,y, or z scale is determined
333  * to be zero, the rotation may not be accurate
334  * \param[in] matrix the matrix to decompose
335  * \param[out] scale a vector that contains the x, y, and z scale factors
336  * \param[out] location a vector that contains the x, y, and z translation
337  * \param[out] rotation a quaternion that contains the rotation
338  */
339 template<class Type>
340 void DecomposeMatrix( const GlsMatrix<Type, 4>& matrix, Vector& scale, Vector& location, GlsQuaternion<Type>& rotation )
341 {
342  scale = DecomposeScale( matrix );
343 
344  // decompose location
345  location = Vector( float( matrix( 0, 3 ) ), float( matrix( 1, 3 ) ), float( matrix( 2, 3 ) ) );
346 
347  rotation = GlsQuaternion<Type>( DecomposeRotationMatrix( matrix, scale ) );
348 }
349 
350 typedef GlsMatrixAffine<float> GlsMatrixAffineF;
351 typedef GlsMatrixAffine<double> GlsMatrixAffineD;
352 
353 //============================================================================
354 //
355 // CLASS IMPLEMENTATION
356 //
357 //============================================================================
358 
359 //----------------------------------------------------------------------------
360 template<class Type>
362 {
363 }
364 //----------------------------------------------------------------------------
365 template<class Type>
366 GlsMatrixAffine<Type>::GlsMatrixAffine( const Type m[ 4 ][ 4 ] )
367  : GlsMatrix<Type, 4>( m )
368 {
369 }
370 //----------------------------------------------------------------------------
371 template<class Type>
373  : GlsMatrix<Type, 4>( m )
374 {
375 }
376 //----------------------------------------------------------------------------
377 template<class Type>
379  : GlsMatrix<Type, 4>( m )
380 {
381 }
382 //----------------------------------------------------------------------------
383 template<class Type>
385 {
386 }
387 
388 //----------------------------------------------------------------------------
389 template<class Type>
391 {
392  // Find the sine and cosine of the angle of rotation to be used
393  // in the rotation transform matrix.
394  const double a( double( angle ) * DEG_TO_RAD );
395  const Type sina( (Type)sin( a ) );
396  const Type cosa( (Type)cos( a ) );
397 
398  Type temp;
399 
400  switch( axis )
401  {
402  case X_AXIS:
403  {
404  // The rotation matrix for rotation about the x axis is
405  // |1 0 0 0|
406  // R = |0 cos(a) -sin(a) 0|
407  // |0 sin(a) cos(a) 0|
408  // |0 0 0 1|
409 
410  // Multiply the current matrix by the rotation transformation
411  // *this = R * *this;
412 
413  temp = _matrix[ 0 ][ 1 ];
414  _matrix[ 0 ][ 1 ] = temp * cosa - _matrix[ 0 ][ 2 ] * sina;
415  _matrix[ 0 ][ 2 ] = temp * sina + _matrix[ 0 ][ 2 ] * cosa;
416  temp = _matrix[ 1 ][ 1 ];
417  _matrix[ 1 ][ 1 ] = temp * cosa - _matrix[ 1 ][ 2 ] * sina;
418  _matrix[ 1 ][ 2 ] = temp * sina + _matrix[ 1 ][ 2 ] * cosa;
419  temp = _matrix[ 2 ][ 1 ];
420  _matrix[ 2 ][ 1 ] = temp * cosa - _matrix[ 2 ][ 2 ] * sina;
421  _matrix[ 2 ][ 2 ] = temp * sina + _matrix[ 2 ][ 2 ] * cosa;
422  temp = _matrix[ 3 ][ 1 ];
423  _matrix[ 3 ][ 1 ] = temp * cosa - _matrix[ 3 ][ 2 ] * sina;
424  _matrix[ 3 ][ 2 ] = temp * sina + _matrix[ 3 ][ 2 ] * cosa;
425 
426  break;
427  }
428  case Y_AXIS:
429  {
430  // The rotation matrix for rotation about the y axis is
431  // | cos(a) 0 sin(a) 0|
432  // R = | 0 1 0 0|
433  // |-sin(a) 0 cos(a) 0|
434  // | 0 0 0 1|
435 
436  // Multiply the current matrix by the rotation transformation
437  // *this = R * *this;
438 
439  temp = _matrix[ 0 ][ 0 ];
440  _matrix[ 0 ][ 0 ] = temp * cosa + _matrix[ 0 ][ 2 ] * sina;
441  _matrix[ 0 ][ 2 ] = _matrix[ 0 ][ 2 ] * cosa - temp * sina;
442  temp = _matrix[ 1 ][ 0 ];
443  _matrix[ 1 ][ 0 ] = temp * cosa + _matrix[ 1 ][ 2 ] * sina;
444  _matrix[ 1 ][ 2 ] = _matrix[ 1 ][ 2 ] * cosa - temp * sina;
445  temp = _matrix[ 2 ][ 0 ];
446  _matrix[ 2 ][ 0 ] = temp * cosa + _matrix[ 2 ][ 2 ] * sina;
447  _matrix[ 2 ][ 2 ] = _matrix[ 2 ][ 2 ] * cosa - temp * sina;
448  temp = _matrix[ 3 ][ 0 ];
449  _matrix[ 3 ][ 0 ] = temp * cosa + _matrix[ 3 ][ 2 ] * sina;
450  _matrix[ 3 ][ 2 ] = _matrix[ 3 ][ 2 ] * cosa - temp * sina;
451 
452  break;
453  }
454  case Z_AXIS:
455  {
456  // The rotation matrix for rotation about the z axis is
457  // |cos(a) sin(a) 0 0|
458  // R = |-sin(a) cos(a) 0 0|
459  // | 0 0 1 0|
460  // | 0 0 0 1|
461 
462  // Multiply the current matrix by the rotation transformation
463  // *this = R * *this;
464 
465  temp = _matrix[ 0 ][ 0 ];
466  _matrix[ 0 ][ 0 ] = temp * cosa - _matrix[ 0 ][ 1 ] * sina;
467  _matrix[ 0 ][ 1 ] = temp * sina + _matrix[ 0 ][ 1 ] * cosa;
468  temp = _matrix[ 1 ][ 0 ];
469  _matrix[ 1 ][ 0 ] = temp * cosa - _matrix[ 1 ][ 1 ] * sina;
470  _matrix[ 1 ][ 1 ] = temp * sina + _matrix[ 1 ][ 1 ] * cosa;
471  temp = _matrix[ 2 ][ 0 ];
472  _matrix[ 2 ][ 0 ] = temp * cosa - _matrix[ 2 ][ 1 ] * sina;
473  _matrix[ 2 ][ 1 ] = temp * sina + _matrix[ 2 ][ 1 ] * cosa;
474  temp = _matrix[ 3 ][ 0 ];
475  _matrix[ 3 ][ 0 ] = temp * cosa - _matrix[ 3 ][ 1 ] * sina;
476  _matrix[ 3 ][ 1 ] = temp * sina + _matrix[ 3 ][ 1 ] * cosa;
477 
478  break;
479  }
480  }
481 }
482 //----------------------------------------------------------------------------
483 template<class Type>
485  const Vector& centerOfRotation,
486  RotationAxis axis )
487 {
488  // First, we must translate the center of rotation to the origin,
489  // perform the rotation and then translate back to the center of
490  // rotation.
491 
492  // Find the sine and cosine of the angle of rotation to be used
493  // in the rotation transform matrix.
494  const double a( double( angle ) * DEG_TO_RAD );
495  const Type sina( (Type)sin( a ) );
496  const Type cosa( (Type)cos( a ) );
497 
498  Type temp;
499 
500  switch( axis )
501  {
502  case X_AXIS:
503  {
504  // The rotation matrix for rotation about the x axis is
505  // |1 0 0 0|
506  // R = |0 cos(a) -sin(a) 0|
507  // |0 sin(a) cos(a) 0|
508  // |0 0 0 1|
509  //
510  // The total transformation T is:
511  // |1 0 0 x-x |
512  // T = |0 R11 R12 (-R11*y-R12*z)+y |
513  // |0 R21 R22 (-R21*y-R22*z)+z |
514  // |0 0 0 1 |
515  const Type T11( cosa ), T12( -sina ), T21( sina ), T22( cosa ),
516  // T03( centerOfRotation.x-centerOfRotation.x ),
517  T13( centerOfRotation.y - ( cosa * centerOfRotation.y - sina * centerOfRotation.z ) ),
518  T23( centerOfRotation.z - ( sina * centerOfRotation.y + cosa * centerOfRotation.z ) );
519 
520  // Multiply by the transformation matrix
521  // *this = T * *this;
522  temp = _matrix[ 0 ][ 1 ];
523  _matrix[ 0 ][ 1 ] = temp * T11 + _matrix[ 0 ][ 2 ] * T12 + _matrix[ 0 ][ 3 ] * T13;
524  _matrix[ 0 ][ 2 ] = temp * T21 + _matrix[ 0 ][ 2 ] * T22 + _matrix[ 0 ][ 3 ] * T23;
525  temp = _matrix[ 1 ][ 1 ];
526  _matrix[ 1 ][ 1 ] = temp * T11 + _matrix[ 1 ][ 2 ] * T12 + _matrix[ 1 ][ 3 ] * T13;
527  _matrix[ 1 ][ 2 ] = temp * T21 + _matrix[ 1 ][ 2 ] * T22 + _matrix[ 1 ][ 3 ] * T23;
528  temp = _matrix[ 2 ][ 1 ];
529  _matrix[ 2 ][ 1 ] = temp * T11 + _matrix[ 2 ][ 2 ] * T12 + _matrix[ 2 ][ 3 ] * T13;
530  _matrix[ 2 ][ 2 ] = temp * T21 + _matrix[ 2 ][ 2 ] * T22 + _matrix[ 2 ][ 3 ] * T23;
531  temp = _matrix[ 3 ][ 1 ];
532  _matrix[ 3 ][ 1 ] = temp * T11 + _matrix[ 3 ][ 2 ] * T12 + _matrix[ 3 ][ 3 ] * T13;
533  _matrix[ 3 ][ 2 ] = temp * T21 + _matrix[ 3 ][ 2 ] * T22 + _matrix[ 3 ][ 3 ] * T23;
534 
535  break;
536  }
537  case Y_AXIS:
538  {
539  // The rotation matrix for rotation about the y axis is
540  // | cos(a) 0 sin(a) 0|
541  // R = | 0 1 0 0|
542  // |-sin(a) 0 cos(a) 0|
543  // | 0 0 0 1|
544  //
545  // The total transformation T is:
546  // |R00 0 R02 (-R00*x-R02*z)+x |
547  // T = | 0 1 0 y-y |
548  // |R20 0 R22 (-R20*x-R22*z)+z |
549  // | 0 0 0 1 |
550  const Type T00( cosa ), T02( sina ), T20( -sina ), T22( cosa ),
551  T03( centerOfRotation.x - ( sina * centerOfRotation.z + cosa * centerOfRotation.x ) ),
552  // T13( centerOfRotation.y-centerOfRotation.y ),
553  T23( centerOfRotation.z - ( cosa * centerOfRotation.z - sina * centerOfRotation.x ) );
554 
555  // Multiply by the transformation matrix
556  // *this = T * *this;
557  temp = _matrix[ 0 ][ 0 ];
558  _matrix[ 0 ][ 0 ] = temp * T00 + _matrix[ 0 ][ 2 ] * T02 + _matrix[ 0 ][ 3 ] * T03;
559  _matrix[ 0 ][ 2 ] = temp * T20 + _matrix[ 0 ][ 2 ] * T22 + _matrix[ 0 ][ 3 ] * T23;
560  temp = _matrix[ 1 ][ 0 ];
561  _matrix[ 1 ][ 0 ] = temp * T00 + _matrix[ 1 ][ 2 ] * T02 + _matrix[ 1 ][ 3 ] * T03;
562  _matrix[ 1 ][ 2 ] = temp * T20 + _matrix[ 1 ][ 2 ] * T22 + _matrix[ 1 ][ 3 ] * T23;
563  temp = _matrix[ 2 ][ 0 ];
564  _matrix[ 2 ][ 0 ] = temp * T00 + _matrix[ 2 ][ 2 ] * T02 + _matrix[ 2 ][ 3 ] * T03;
565  _matrix[ 2 ][ 2 ] = temp * T20 + _matrix[ 2 ][ 2 ] * T22 + _matrix[ 2 ][ 3 ] * T23;
566  temp = _matrix[ 3 ][ 0 ];
567  _matrix[ 3 ][ 0 ] = temp * T00 + _matrix[ 3 ][ 2 ] * T02 + _matrix[ 3 ][ 3 ] * T03;
568  _matrix[ 3 ][ 2 ] = temp * T20 + _matrix[ 3 ][ 2 ] * T22 + _matrix[ 3 ][ 3 ] * T23;
569 
570  break;
571  }
572  case Z_AXIS:
573  {
574  // The rotation matrix for rotation about the z axis is
575  // |cos(a) -sin(a) 0 0|
576  // R = |sin(a) cos(a) 0 0|
577  // | 0 0 1 0|
578  // | 0 0 0 1|
579  //
580  // The total transformation T is:
581  // |R00 R01 0 (-R00*x-R01*y)+x |
582  // T = |R10 R11 0 (-R10*x-R11*y)+y |
583  // | 0 0 1 z-z |
584  // | 0 0 0 1 |
585  const Type T00( cosa ), T01( -sina ), T10( sina ), T11( cosa ),
586  T03( centerOfRotation.x - ( cosa * centerOfRotation.x - sina * centerOfRotation.y ) ),
587  T13( centerOfRotation.y - ( sina * centerOfRotation.x + cosa * centerOfRotation.y ) );
588  // T23( centerOfRotation.z-centerOfRotation.z );
589 
590  // Multiply by the transformation matrix
591  // *this = T * *this;
592  temp = _matrix[ 0 ][ 0 ];
593  _matrix[ 0 ][ 0 ] = temp * T00 + _matrix[ 0 ][ 1 ] * T01 + _matrix[ 0 ][ 3 ] * T03;
594  _matrix[ 0 ][ 1 ] = temp * T10 + _matrix[ 0 ][ 1 ] * T11 + _matrix[ 0 ][ 3 ] * T13;
595  temp = _matrix[ 1 ][ 0 ];
596  _matrix[ 1 ][ 0 ] = temp * T00 + _matrix[ 1 ][ 1 ] * T01 + _matrix[ 1 ][ 3 ] * T03;
597  _matrix[ 1 ][ 1 ] = temp * T10 + _matrix[ 1 ][ 1 ] * T11 + _matrix[ 1 ][ 3 ] * T13;
598  temp = _matrix[ 2 ][ 0 ];
599  _matrix[ 2 ][ 0 ] = temp * T00 + _matrix[ 2 ][ 1 ] * T01 + _matrix[ 2 ][ 3 ] * T03;
600  _matrix[ 2 ][ 1 ] = temp * T10 + _matrix[ 2 ][ 1 ] * T11 + _matrix[ 2 ][ 3 ] * T13;
601  temp = _matrix[ 3 ][ 0 ];
602  _matrix[ 3 ][ 0 ] = temp * T00 + _matrix[ 3 ][ 1 ] * T01 + _matrix[ 3 ][ 3 ] * T03;
603  _matrix[ 3 ][ 1 ] = temp * T10 + _matrix[ 3 ][ 1 ] * T11 + _matrix[ 3 ][ 3 ] * T13;
604 
605  break;
606  }
607  }
608 }
609 //----------------------------------------------------------------------------
610 template<class Type>
612  const Vector& centerOfRotation,
613  const Vector& axis )
614 {
615  // Normalize the arbitrary axis into a unit vector to be used in the
616  // calculations for the terms of the rotation matrix. Only perform
617  // the rotation if the length of the axis vector is not zero.
618  Vector u( axis );
619  u.Normalize();
620 
621  if( u.MagnitudeSquared() != 0 )
622  {
623  // The following describes the theory used to determine the rotation
624  // matrix for a rotation around an arbitrary axis:
625  //
626  // Definitions:
627  //
628  // The "dual matrix" of a vector u(x,y,z) is S, where
629  // | 0 -z y |
630  // S = | z 0 -x |
631  // |-y x 0 |
632  //
633  // The "outer product" of a vector u with itself (where uT is
634  // the transpose of u) is:
635  // |x| |xx xy xz|
636  // uuT = |y||x y z| = |xy yy yz|
637  // |z| |xz yz zz|
638  //
639  // Suppose we have a unit direction vector, u, then we can derive
640  // a rotation by a given angle about this axis:
641  //
642  // R(a,u) = uuT + (I - uuT) * cos(a) + S * sin(a)
643  //
644  // where I is the identity matrix. This actually produces a 3x3
645  // matrix which we just need to add the 4th column and row to so
646  // that we can use it for affine transformations.
647 
648  // Calculate some constants from uuT
649  const Type xx( Type( u.x * u.x ) );
650  const Type yy( Type( u.y * u.y ) );
651  const Type zz( Type( u.z * u.z ) );
652  const Type xy( Type( u.x * u.y ) );
653  const Type xz( Type( u.x * u.z ) );
654  const Type yz( Type( u.y * u.z ) );
655 
656  // Calculate the sine and cosine of the rotation angle for use
657  // in the calculation of the rotation matrix.
658  const double a( double( angle ) * DEG_TO_RAD );
659  const Type sina( (Type)sin( a ) );
660  const Type cosa( (Type)cos( a ) );
661 
662  // Now calculate M, which is the 3x3 version of the rotation
663  // matrix using the formula for rotation about an arbitrary axis.
664  // GlsMatrix<Type,3> M = UUT + ((I - UUT) * cosa) + (S * sina);
665 
666  // Assign M to the first 3 columns and rows of the final rotation
667  // matrix R.
669 
670  R( 0, 0 ) = xx + ( 1 - xx ) * cosa;
671  R( 1, 0 ) = xy - xy * cosa + u.z * sina;
672  R( 2, 0 ) = xz - xz * cosa - u.y * sina;
673 
674  R( 0, 1 ) = xy - xy * cosa - u.z * sina;
675  R( 1, 1 ) = yy + ( 1 - yy ) * cosa;
676  R( 2, 1 ) = yz - yz * cosa + u.x * sina;
677 
678  R( 0, 2 ) = xz - xz * cosa + u.y * sina;
679  R( 1, 2 ) = yz - yz * cosa - u.x * sina;
680  R( 2, 2 ) = zz + ( 1 - zz ) * cosa;
681 
682  // Multiply the current matrix by the translation, then the rotation,
683  // and then translate back using the inverse.
684  // *this = TInv * R * T * *this;
685  this->Translate( -centerOfRotation.x, -centerOfRotation.y, -centerOfRotation.z );
686  *this = R * *this;
687  this->Translate( centerOfRotation.x, centerOfRotation.y, centerOfRotation.z );
688  }
689 }
690 //----------------------------------------------------------------------------
691 template<class Type>
692 void GlsMatrixAffine<Type>::Scale( Type x, Type y, Type z )
693 {
694  // The scaling matrix, where x, y, and z are on the diagonal.
695  // x 0 0 0
696  // 0 y 0 0
697  // 0 0 z 0
698  // 0 0 0 1
699  // As can be seen most of the matrix is zero
700  // So optimized
701 
702  _matrix[ 0 ][ 0 ] = _matrix[ 0 ][ 0 ] * x;
703  _matrix[ 0 ][ 1 ] = _matrix[ 0 ][ 1 ] * y;
704  _matrix[ 0 ][ 2 ] = _matrix[ 0 ][ 2 ] * z;
705  //_matrix[0][3] = _matrix[0][3];
706 
707  _matrix[ 1 ][ 0 ] = _matrix[ 1 ][ 0 ] * x;
708  _matrix[ 1 ][ 1 ] = _matrix[ 1 ][ 1 ] * y;
709  _matrix[ 1 ][ 2 ] = _matrix[ 1 ][ 2 ] * z;
710  //_matrix[1][3] = _matrix[1][3];
711 
712  _matrix[ 2 ][ 0 ] = _matrix[ 2 ][ 0 ] * x;
713  _matrix[ 2 ][ 1 ] = _matrix[ 2 ][ 1 ] * y;
714  _matrix[ 2 ][ 2 ] = _matrix[ 2 ][ 2 ] * z;
715  //_matrix[2][3] = _matrix[2][3];
716 
717  _matrix[ 3 ][ 0 ] = _matrix[ 3 ][ 0 ] * x;
718  _matrix[ 3 ][ 1 ] = _matrix[ 3 ][ 1 ] * y;
719  _matrix[ 3 ][ 2 ] = _matrix[ 3 ][ 2 ] * z;
720  //_matrix[3][3] = _matrix[3][3];
721 
722  // Row 3 is multiplied by 1, so no need...
723 }
724 //----------------------------------------------------------------------------
725 template<class Type>
726 void GlsMatrixAffine<Type>::Scale( Type x, Type y, Type z, const Vector& anchor )
727 {
728  // First, we must translate the anchor point to the origin,
729  // perform the scaling and then translate back to the anchor
730  // point. This is the transformation matrix we are multiplying by:
731  // (Ax, Ay, Az are the components of anchor)
732  // | x 0 0 Ax-x*Ax |
733  // T = | 0 y 0 Ay-y*Ay |
734  // | 0 0 z Az-z*Az |
735  // | 0 0 0 1 |
736  const Type T00 = x;
737  const Type T11 = y;
738  const Type T22 = z;
739  const Type T03 = anchor.x * ( 1 - x );
740  const Type T13 = anchor.y * ( 1 - y );
741  const Type T23 = anchor.z * ( 1 - z );
742 
743  // Multiply the current matrix by the transformation
744  // *this = T * *this;
745 
746  _matrix[ 0 ][ 0 ] = _matrix[ 0 ][ 0 ] * T00 + _matrix[ 0 ][ 3 ] * T03;
747  _matrix[ 0 ][ 1 ] = _matrix[ 0 ][ 1 ] * T11 + _matrix[ 0 ][ 3 ] * T13;
748  _matrix[ 0 ][ 2 ] = _matrix[ 0 ][ 2 ] * T22 + _matrix[ 0 ][ 3 ] * T23;
749  //_matrix[0][3] = _matrix[0][3];
750 
751  _matrix[ 1 ][ 0 ] = _matrix[ 1 ][ 0 ] * T00 + _matrix[ 1 ][ 3 ] * T03;
752  _matrix[ 1 ][ 1 ] = _matrix[ 1 ][ 1 ] * T11 + _matrix[ 1 ][ 3 ] * T13;
753  _matrix[ 1 ][ 2 ] = _matrix[ 1 ][ 2 ] * T22 + _matrix[ 1 ][ 3 ] * T23;
754  //_matrix[1][3] = _matrix[1][3];
755 
756  _matrix[ 2 ][ 0 ] = _matrix[ 2 ][ 0 ] * T00 + _matrix[ 2 ][ 3 ] * T03;
757  _matrix[ 2 ][ 1 ] = _matrix[ 2 ][ 1 ] * T11 + _matrix[ 2 ][ 3 ] * T13;
758  _matrix[ 2 ][ 2 ] = _matrix[ 2 ][ 2 ] * T22 + _matrix[ 2 ][ 3 ] * T23;
759  //_matrix[2][3] = _matrix[2][3];
760 
761  _matrix[ 3 ][ 0 ] = _matrix[ 3 ][ 0 ] * T00 + _matrix[ 3 ][ 3 ] * T03;
762  _matrix[ 3 ][ 1 ] = _matrix[ 3 ][ 1 ] * T11 + _matrix[ 3 ][ 3 ] * T13;
763  _matrix[ 3 ][ 2 ] = _matrix[ 3 ][ 2 ] * T22 + _matrix[ 3 ][ 3 ] * T23;
764  //_matrix[3][3] = _matrix[3][3];
765 }
766 
767 //----------------------------------------------------------------------------
768 
769 #ifdef MATRIX_TYPE_FLOAT
770 typedef float GlsMatrixElementType;
771 typedef GlsMatrixAffineF GlsMatrixType;
772 # define GLS_glLoadMatrix_TYPE glLoadMatrixf
773 # define GLS_glMultMatrix_TYPE glMultMatrixf
774 #else
775 typedef double GlsMatrixElementType;
776 typedef GlsMatrixAffineD GlsMatrixType;
777 # define GLS_glLoadMatrix_TYPE glLoadMatrixd
778 # define GLS_glMultMatrix_TYPE glMultMatrixd
779 #endif
780 
781 } // namespace disti
782 
783 #endif
Definition: vertex.h:409
#define DISTI_DEPRECATED(msg)
Defines whether this compiler supports the C++14 deprecated attribute.
Definition: gls_cpp_lang_support.h:436
RotationAxis
Definition: vertex.h:73
unsigned char R(void) const
Definition: gls_color.h:208
Definition: gls_matrix.h:61
const double DEG_TO_RAD
Definition: vertex.h:61
float MagnitudeSquared() const
Definition: vertex.h:335
unsigned char B(void) const
Definition: gls_color.h:214
The GlsMatrix class.
void Normalize(void)
Definition: vertex.h:308
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:233
Definition: vertex.h:75
GlsMatrix< Type, 4 > DecomposeRotationMatrix(const GlsMatrix< Type, 4 > &matrix, const Vector &scale)
Definition: gls_matrix_affine.h:306
void Transform(Vector &v) const
Definition: gls_matrix_affine.h:271
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:198
void DecomposeMatrix(const GlsMatrix< Type, 4 > &matrix, Vector &scale, Vector &location, GlsQuaternion< Type > &rotation)
Definition: gls_matrix_affine.h:340
~GlsMatrixAffine()
Definition: gls_matrix_affine.h:384
void Rotate(Type angle, RotationAxis axis)
Definition: gls_matrix_affine.h:390
Vector DecomposeScale(const GlsMatrix< Type, 4 > &m)
Definition: gls_matrix_affine.h:291
Definition: vertex.h:84
Definition: gls_quaternion.h:54
The disti::GlsQuaternion class.
float Magnitude() const
Definition: vertex.h:327
unsigned char A(void) const
Definition: gls_color.h:217
Definition: vertex.h:77
Definition: vertex.h:76
bool IsVeryClose(const GlsMatrix< Type, 4 > &b) const
Definition: gls_matrix_affine.h:113
Definition: bmpimage.h:46
void Scale(Type x, Type y, Type z)
Definition: gls_matrix_affine.h:692
Vector operator*(const Vector &v) const
Definition: gls_matrix_affine.h:244
Definition: gls_matrix_affine.h:60
GlsMatrixAffine()
Definition: gls_matrix_affine.h:361