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