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
14reproduced, in whole or part, in any form, or by any means of electronic,
15mechanical, or otherwise, without the written permission of DiSTI. Said
16permission may be derived through the purchase of applicable DiSTI product
17licenses which detail the distribution rights of this content and any
18Derivative Works based on this or other copyrighted DiSTI Software.
19
20 NO WARRANTY. THE SOFTWARE IS PROVIDED "AS-IS," WITHOUT WARRANTY OF ANY KIND,
21AND ANY USE OF THIS SOFTWARE PRODUCT IS AT YOUR OWN RISK. TO THE MAXIMUM EXTENT
22PERMITTED BY APPLICABLE LAW, DISTI AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES
23AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
24IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY AND/OR FITNESS FOR A
25PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT, WITH REGARD TO THE SOFTWARE.
26
27 LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW,
28IN NO EVENT SHALL DISTI OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
29INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION,
30DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
31INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR
32INABILITY TO USE THE SOFTWARE, EVEN IF DISTI HAS BEEN ADVISED OF THE POSSIBILITY
33OF SUCH DAMAGES. DISTI'S ENTIRE LIABILITY AND YOUR EXCLUSIVE REMEDY SHALL NOT
34EXCEED FIVE DOLLARS (US$5.00).
35
36 The aforementioned terms and restrictions are governed by the laws of the
37State 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
47namespace 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//----------------------------------------------------------------------------
59template<class Type>
60class GlsMatrixAffine : public GlsMatrix<Type, 4>
61{
62public:
63 using GlsMatrix<Type, 4>::_matrix;
64 DISTI_DEPRECATED( "This identifier is forbidden by the C++ standard. Use BaseClass instead." )
65 typedef GlsMatrix<Type, 4> _BaseClass; ///< Deprecated typedef for the base class.
66 typedef GlsMatrix<Type, 4> BaseClass; ///< Typedef for the base class.
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 //------------------------------------------------------------------------
102 GlsMatrixAffine( const GlsMatrix<Type, 4>& m );
103
104 //------------------------------------------------------------------------
105 /**
106 * Destructor.
107 */
108 //------------------------------------------------------------------------
110
111#ifdef _MSC_VER
112# pragma warning( push )
113# pragma warning( disable : 4458 ) // PRECISION is technically shadowed in the function below, but most compilers need it defined below anyway to compile...
114#endif
115 /// \return True if the supplied matrix is "very close" to this one.
116 /// \param b The matrix to compare.
117 bool IsVeryClose( const GlsMatrix<Type, 4>& b ) const
118 {
119 static const unsigned int SIZE = 4 * 4;
120 static const double PRECISION = 0.00001;
121
122 for( unsigned int i = 0; i < SIZE; ++i )
123 {
124 if( fabs( this->_data[ i ] - b.Data()[ i ] ) > PRECISION )
125 return false;
126 }
127 return true;
128 }
129#ifdef _MSC_VER
130# pragma warning( pop )
131#endif
132
133 //------------------------------------------------------------------------
134 /**
135 * Perform a rotation transformation around a major axis around the origin,
136 * and combine this transformation with the existing matrix data.
137 *
138 * \param angle rotation angle in degrees
139 * \param axis major axis of rotation: X_AXIS, Y_AXIS, Z_AXIS
140 */
141 //------------------------------------------------------------------------
142 void Rotate( Type angle, RotationAxis axis );
143
144 //------------------------------------------------------------------------
145 /**
146 * Perform a rotation transformation around a major axis using a specified
147 * center of rotation, and combine this transformation with the existing
148 * matrix data.
149 *
150 * \param angle rotation angle in degrees
151 * \param centerOfRotation point to rotate around
152 * \param axis major axis of rotation: X_AXIS, Y_AXIS, Z_AXIS
153 */
154 //------------------------------------------------------------------------
155 void Rotate( Type angle, const Vector& centerOfRotation, RotationAxis axis );
156
157 //------------------------------------------------------------------------
158 /**
159 * Perform a rotation transformation around an arbitrary axis using a
160 * specified center of rotation, and combine this transformation with the
161 * existing matrix data.
162 *
163 * \param angle rotation angle in degrees
164 * \param centerOfRotation point to rotate around
165 * \param axis arbitray axis of rotation
166 */
167 //------------------------------------------------------------------------
168 void Rotate( Type angle, const Vector& centerOfRotation, const Vector& axis );
169
170 //------------------------------------------------------------------------
171 /**
172 * Perform a scaling transformation using the origin as the anchor point,
173 * and combine this transformation with the existing matrix data.
174 *
175 * \param x scaling factor in the x direction. 1 = 100% (no scaling change)
176 * \param y scaling factor in the y direction. 1 = 100% (no scaling change)
177 * \param z scaling factor in the z direction. 1 = 100% (no scaling change)
178 */
179 //------------------------------------------------------------------------
180 void Scale( Type x, Type y, Type z );
181
182 //------------------------------------------------------------------------
183 /**
184 * Perform a scaling transformation using an arbitrary anchor point,
185 * and combine this transformation with the existing matrix data.
186 *
187 * \param x scaling factor in the x direction. 1 = 100% (no scaling change)
188 * \param y scaling factor in the y direction. 1 = 100% (no scaling change)
189 * \param z scaling factor in the z direction. 1 = 100% (no scaling change)
190 * \param anchor The anchor point for the scaling
191 */
192 //------------------------------------------------------------------------
193 void Scale( Type x, Type y, Type z, const Vector& anchor );
194
195 //------------------------------------------------------------------------
196 /**
197 * Perform a translation, and combine this transformation with the
198 * existing matrix data.
199 *
200 * \param x translation in the x direction
201 * \param y translation in the y direction
202 * \param z translation in the z direction
203 */
204 //------------------------------------------------------------------------
205 inline void Translate( Type x, Type y, Type z )
206 {
207 // The translation matrix is:
208 // |1 0 0 x|
209 // T = |0 1 0 y|
210 // |0 0 1 z|
211 // |0 0 0 1|
212 // We multiply it on the left: *this = T * *this;
213
214 _matrix[ 0 ][ 0 ] += x * _matrix[ 0 ][ 3 ];
215 _matrix[ 0 ][ 1 ] += y * _matrix[ 0 ][ 3 ];
216 _matrix[ 0 ][ 2 ] += z * _matrix[ 0 ][ 3 ];
217 //_matrix[0][3] = _matrix[0][3];
218 _matrix[ 1 ][ 0 ] += x * _matrix[ 1 ][ 3 ];
219 _matrix[ 1 ][ 1 ] += y * _matrix[ 1 ][ 3 ];
220 _matrix[ 1 ][ 2 ] += z * _matrix[ 1 ][ 3 ];
221 //_matrix[1][3] = _matrix[1][3];
222 _matrix[ 2 ][ 0 ] += x * _matrix[ 2 ][ 3 ];
223 _matrix[ 2 ][ 1 ] += y * _matrix[ 2 ][ 3 ];
224 _matrix[ 2 ][ 2 ] += z * _matrix[ 2 ][ 3 ];
225 //_matrix[2][3] = _matrix[2][3];
226 _matrix[ 3 ][ 0 ] += x * _matrix[ 3 ][ 3 ];
227 _matrix[ 3 ][ 1 ] += y * _matrix[ 3 ][ 3 ];
228 _matrix[ 3 ][ 2 ] += z * _matrix[ 3 ][ 3 ];
229 //_matrix[3][3] = _matrix[3][3];
230 }
231
232 //------------------------------------------------------------------------
233 /**
234 * Perform a translation, and combine this transformation with the
235 * existing matrix data.
236 *
237 * \param v containing the translate values
238 */
239 //------------------------------------------------------------------------
240 inline void Translate( const Vector& v ) { Translate( (Type)v.x, (Type)v.y, (Type)v.z ); }
241
242 // LynxOS does not support 'using'
243 using BaseClass::operator*;
244
245 /// \return A transformed vector using the specified vertex and the data in the matrix, e.g. w = M * v
246 /// \param v The vector to transform.
247 inline Vector operator*( const Vector& v ) const
248 {
249 const GlsMatrix<Type, 4>& M = *this;
250 return Vector(
251 float( ( M( 0, 0 ) * v.x ) + ( M( 0, 1 ) * v.y ) + ( M( 0, 2 ) * v.z ) + M( 0, 3 ) ),
252 float( ( M( 1, 0 ) * v.x ) + ( M( 1, 1 ) * v.y ) + ( M( 1, 2 ) * v.z ) + M( 1, 3 ) ),
253 float( ( M( 2, 0 ) * v.x ) + ( M( 2, 1 ) * v.y ) + ( M( 2, 2 ) * v.z ) + M( 2, 3 ) ) );
254 }
255
256 /// \return A transformed vertex using the specified vertex and the data in the matrix, e.g. w = M * v
257 /// \param v The vertex to transform.
258 inline Vertex operator*( const Vertex& v ) const
259 {
260 const GlsMatrix<Type, 4>& M = *this;
261 return Vertex(
262 float( ( M( 0, 0 ) * v.x ) + ( M( 0, 1 ) * v.y ) + ( M( 0, 2 ) * v.z ) + M( 0, 3 ) ),
263 float( ( M( 1, 0 ) * v.x ) + ( M( 1, 1 ) * v.y ) + ( M( 1, 2 ) * v.z ) + M( 1, 3 ) ),
264 float( ( M( 2, 0 ) * v.x ) + ( M( 2, 1 ) * v.y ) + ( M( 2, 2 ) * v.z ) + M( 2, 3 ) ),
265 v.color.R(),
266 v.color.G(),
267 v.color.B(),
268 v.color.A() );
269 }
270
271 /// Transform the specified vertex using the data in the matrix, where the 4th vector component is assumed to be a 1 (position) i.e. v = M * v
272 /// \param v A modifiable reference to the vector to transform.
273 inline void Transform( Vector& v ) const
274 {
275 // Simple version is:
276 // v = *this * v;
277
278 // Faster version is:
279 float x = float( ( _matrix[ 0 ][ 0 ] * v.x ) + ( _matrix[ 1 ][ 0 ] * v.y ) + ( _matrix[ 2 ][ 0 ] * v.z ) + _matrix[ 3 ][ 0 ] );
280 float y = float( ( _matrix[ 0 ][ 1 ] * v.x ) + ( _matrix[ 1 ][ 1 ] * v.y ) + ( _matrix[ 2 ][ 1 ] * v.z ) + _matrix[ 3 ][ 1 ] );
281 float z = float( ( _matrix[ 0 ][ 2 ] * v.x ) + ( _matrix[ 1 ][ 2 ] * v.y ) + ( _matrix[ 2 ][ 2 ] * v.z ) + _matrix[ 3 ][ 2 ] );
282 v.x = x;
283 v.y = y;
284 v.z = z;
285 }
286};
287
288/** decompose the scale factors from a GlsMatrix
289 * \param[in] m the matrix to decompose
290 * \return scale a vector that contains the x, y, and z scale factors
291 */
292template<class Type>
294{
295 const Vector xAxis = Vector( float( m( 0, 0 ) ), float( m( 1, 0 ) ), float( m( 2, 0 ) ) );
296 const Vector yAxis = Vector( float( m( 0, 1 ) ), float( m( 1, 1 ) ), float( m( 2, 1 ) ) );
297 const Vector zAxis = Vector( float( m( 0, 2 ) ), float( m( 1, 2 ) ), float( m( 2, 2 ) ) );
298 return Vector( xAxis.Magnitude(), yAxis.Magnitude(), zAxis.Magnitude() );
299}
300
301/** decompose the rotation matrix from a GlsMatrix by dividing out the scale factor. If the x,y, or z scale is determined
302 * to be zero, the scale factors not removed from the matrix.
303 * \param[in] matrix the matrix to decompose
304 * \param[in] scale a vector that contains the x, y, and z scale factors
305 * \return the rotation matrix with the scale factors removed
306 */
307template<class Type>
309{
310 GlsMatrix<Type, 4> m( matrix );
311
312 // set the translation to 0
313 m( 0, 3 ) = Type();
314 m( 1, 3 ) = Type();
315 m( 2, 3 ) = Type();
316
317 // only decompose rotation if all scales are non-zero
318 if( 0 != scale.x && 0 != scale.y && 0 != scale.z )
319 {
320 m( 0, 0 ) /= scale.x;
321 m( 1, 0 ) /= scale.x;
322 m( 2, 0 ) /= scale.x;
323 m( 0, 1 ) /= scale.y;
324 m( 1, 1 ) /= scale.y;
325 m( 2, 1 ) /= scale.y;
326 m( 0, 2 ) /= scale.z;
327 m( 1, 2 ) /= scale.z;
328 m( 2, 2 ) /= scale.z;
329 }
330
331 return m;
332}
333
334/** decompose a GlsMatrix into its scaling, translation, and rotation counterparts. If the x,y, or z scale is determined
335 * to be zero, the rotation may not be accurate
336 * \param[in] matrix the matrix to decompose
337 * \param[out] scale a vector that contains the x, y, and z scale factors
338 * \param[out] location a vector that contains the x, y, and z translation
339 * \param[out] rotation a quaternion that contains the rotation
340 */
341template<class Type>
342void DecomposeMatrix( const GlsMatrix<Type, 4>& matrix, Vector& scale, Vector& location, GlsQuaternion<Type>& rotation )
343{
344 scale = DecomposeScale( matrix );
345
346 // decompose location
347 location = Vector( float( matrix( 0, 3 ) ), float( matrix( 1, 3 ) ), float( matrix( 2, 3 ) ) );
348
349 rotation = GlsQuaternion<Type>( DecomposeRotationMatrix( matrix, scale ) );
350}
351
352typedef GlsMatrixAffine<float> GlsMatrixAffineF; ///< Typedef for a matrix of floats.
353typedef GlsMatrixAffine<double> GlsMatrixAffineD; ///< Typedef for a matrix of doubles.
354
355//============================================================================
356//
357// CLASS IMPLEMENTATION
358//
359//============================================================================
360
361//----------------------------------------------------------------------------
362template<class Type>
364{
365}
366//----------------------------------------------------------------------------
367template<class Type>
369 : GlsMatrix<Type, 4>( m )
370{
371}
372//----------------------------------------------------------------------------
373template<class Type>
375 : GlsMatrix<Type, 4>( m )
376{
377}
378//----------------------------------------------------------------------------
379template<class Type>
381 : GlsMatrix<Type, 4>( m )
382{
383}
384//----------------------------------------------------------------------------
385template<class Type>
387{
388}
389
390//----------------------------------------------------------------------------
391template<class Type>
393{
394 // Find the sine and cosine of the angle of rotation to be used
395 // in the rotation transform matrix.
396 const double a( double( angle ) * DEG_TO_RAD );
397 const Type sina( (Type)sin( a ) );
398 const Type cosa( (Type)cos( a ) );
399
400 Type temp;
401
402 switch( axis )
403 {
404 case X_AXIS: {
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 // 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 // The rotation matrix for rotation about the z axis is
456 // |cos(a) sin(a) 0 0|
457 // R = |-sin(a) cos(a) 0 0|
458 // | 0 0 1 0|
459 // | 0 0 0 1|
460
461 // Multiply the current matrix by the rotation transformation
462 // *this = R * *this;
463
464 temp = _matrix[ 0 ][ 0 ];
465 _matrix[ 0 ][ 0 ] = temp * cosa - _matrix[ 0 ][ 1 ] * sina;
466 _matrix[ 0 ][ 1 ] = temp * sina + _matrix[ 0 ][ 1 ] * cosa;
467 temp = _matrix[ 1 ][ 0 ];
468 _matrix[ 1 ][ 0 ] = temp * cosa - _matrix[ 1 ][ 1 ] * sina;
469 _matrix[ 1 ][ 1 ] = temp * sina + _matrix[ 1 ][ 1 ] * cosa;
470 temp = _matrix[ 2 ][ 0 ];
471 _matrix[ 2 ][ 0 ] = temp * cosa - _matrix[ 2 ][ 1 ] * sina;
472 _matrix[ 2 ][ 1 ] = temp * sina + _matrix[ 2 ][ 1 ] * cosa;
473 temp = _matrix[ 3 ][ 0 ];
474 _matrix[ 3 ][ 0 ] = temp * cosa - _matrix[ 3 ][ 1 ] * sina;
475 _matrix[ 3 ][ 1 ] = temp * sina + _matrix[ 3 ][ 1 ] * cosa;
476
477 break;
478 }
479 }
480}
481//----------------------------------------------------------------------------
482template<class Type>
484 const Vector& centerOfRotation,
485 RotationAxis axis )
486{
487 // First, we must translate the center of rotation to the origin,
488 // perform the rotation and then translate back to the center of
489 // rotation.
490
491 // Find the sine and cosine of the angle of rotation to be used
492 // in the rotation transform matrix.
493 const double a( double( angle ) * DEG_TO_RAD );
494 const Type sina( (Type)sin( a ) );
495 const Type cosa( (Type)cos( a ) );
496
497 Type temp;
498
499 switch( axis )
500 {
501 case X_AXIS: {
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 // The rotation matrix for rotation about the y axis is
537 // | cos(a) 0 sin(a) 0|
538 // R = | 0 1 0 0|
539 // |-sin(a) 0 cos(a) 0|
540 // | 0 0 0 1|
541 //
542 // The total transformation T is:
543 // |R00 0 R02 (-R00*x-R02*z)+x |
544 // T = | 0 1 0 y-y |
545 // |R20 0 R22 (-R20*x-R22*z)+z |
546 // | 0 0 0 1 |
547 const Type T00( cosa ), T02( sina ), T20( -sina ), T22( cosa ),
548 T03( centerOfRotation.x - ( sina * centerOfRotation.z + cosa * centerOfRotation.x ) ),
549 // T13( centerOfRotation.y-centerOfRotation.y ),
550 T23( centerOfRotation.z - ( cosa * centerOfRotation.z - sina * centerOfRotation.x ) );
551
552 // Multiply by the transformation matrix
553 // *this = T * *this;
554 temp = _matrix[ 0 ][ 0 ];
555 _matrix[ 0 ][ 0 ] = temp * T00 + _matrix[ 0 ][ 2 ] * T02 + _matrix[ 0 ][ 3 ] * T03;
556 _matrix[ 0 ][ 2 ] = temp * T20 + _matrix[ 0 ][ 2 ] * T22 + _matrix[ 0 ][ 3 ] * T23;
557 temp = _matrix[ 1 ][ 0 ];
558 _matrix[ 1 ][ 0 ] = temp * T00 + _matrix[ 1 ][ 2 ] * T02 + _matrix[ 1 ][ 3 ] * T03;
559 _matrix[ 1 ][ 2 ] = temp * T20 + _matrix[ 1 ][ 2 ] * T22 + _matrix[ 1 ][ 3 ] * T23;
560 temp = _matrix[ 2 ][ 0 ];
561 _matrix[ 2 ][ 0 ] = temp * T00 + _matrix[ 2 ][ 2 ] * T02 + _matrix[ 2 ][ 3 ] * T03;
562 _matrix[ 2 ][ 2 ] = temp * T20 + _matrix[ 2 ][ 2 ] * T22 + _matrix[ 2 ][ 3 ] * T23;
563 temp = _matrix[ 3 ][ 0 ];
564 _matrix[ 3 ][ 0 ] = temp * T00 + _matrix[ 3 ][ 2 ] * T02 + _matrix[ 3 ][ 3 ] * T03;
565 _matrix[ 3 ][ 2 ] = temp * T20 + _matrix[ 3 ][ 2 ] * T22 + _matrix[ 3 ][ 3 ] * T23;
566
567 break;
568 }
569 case Z_AXIS: {
570 // The rotation matrix for rotation about the z axis is
571 // |cos(a) -sin(a) 0 0|
572 // R = |sin(a) cos(a) 0 0|
573 // | 0 0 1 0|
574 // | 0 0 0 1|
575 //
576 // The total transformation T is:
577 // |R00 R01 0 (-R00*x-R01*y)+x |
578 // T = |R10 R11 0 (-R10*x-R11*y)+y |
579 // | 0 0 1 z-z |
580 // | 0 0 0 1 |
581 const Type T00( cosa ), T01( -sina ), T10( sina ), T11( cosa ),
582 T03( centerOfRotation.x - ( cosa * centerOfRotation.x - sina * centerOfRotation.y ) ),
583 T13( centerOfRotation.y - ( sina * centerOfRotation.x + cosa * centerOfRotation.y ) );
584 // T23( centerOfRotation.z-centerOfRotation.z );
585
586 // Multiply by the transformation matrix
587 // *this = T * *this;
588 temp = _matrix[ 0 ][ 0 ];
589 _matrix[ 0 ][ 0 ] = temp * T00 + _matrix[ 0 ][ 1 ] * T01 + _matrix[ 0 ][ 3 ] * T03;
590 _matrix[ 0 ][ 1 ] = temp * T10 + _matrix[ 0 ][ 1 ] * T11 + _matrix[ 0 ][ 3 ] * T13;
591 temp = _matrix[ 1 ][ 0 ];
592 _matrix[ 1 ][ 0 ] = temp * T00 + _matrix[ 1 ][ 1 ] * T01 + _matrix[ 1 ][ 3 ] * T03;
593 _matrix[ 1 ][ 1 ] = temp * T10 + _matrix[ 1 ][ 1 ] * T11 + _matrix[ 1 ][ 3 ] * T13;
594 temp = _matrix[ 2 ][ 0 ];
595 _matrix[ 2 ][ 0 ] = temp * T00 + _matrix[ 2 ][ 1 ] * T01 + _matrix[ 2 ][ 3 ] * T03;
596 _matrix[ 2 ][ 1 ] = temp * T10 + _matrix[ 2 ][ 1 ] * T11 + _matrix[ 2 ][ 3 ] * T13;
597 temp = _matrix[ 3 ][ 0 ];
598 _matrix[ 3 ][ 0 ] = temp * T00 + _matrix[ 3 ][ 1 ] * T01 + _matrix[ 3 ][ 3 ] * T03;
599 _matrix[ 3 ][ 1 ] = temp * T10 + _matrix[ 3 ][ 1 ] * T11 + _matrix[ 3 ][ 3 ] * T13;
600
601 break;
602 }
603 }
604}
605//----------------------------------------------------------------------------
606template<class Type>
608 const Vector& centerOfRotation,
609 const Vector& axis )
610{
611 // Normalize the arbitrary axis into a unit vector to be used in the
612 // calculations for the terms of the rotation matrix. Only perform
613 // the rotation if the length of the axis vector is not zero.
614 Vector u( axis );
615 u.Normalize();
616
617 if( u.MagnitudeSquared() != 0 )
618 {
619 // The following describes the theory used to determine the rotation
620 // matrix for a rotation around an arbitrary axis:
621 //
622 // Definitions:
623 //
624 // The "dual matrix" of a vector u(x,y,z) is S, where
625 // | 0 -z y |
626 // S = | z 0 -x |
627 // |-y x 0 |
628 //
629 // The "outer product" of a vector u with itself (where uT is
630 // the transpose of u) is:
631 // |x| |xx xy xz|
632 // uuT = |y||x y z| = |xy yy yz|
633 // |z| |xz yz zz|
634 //
635 // Suppose we have a unit direction vector, u, then we can derive
636 // a rotation by a given angle about this axis:
637 //
638 // R(a,u) = uuT + (I - uuT) * cos(a) + S * sin(a)
639 //
640 // where I is the identity matrix. This actually produces a 3x3
641 // matrix which we just need to add the 4th column and row to so
642 // that we can use it for affine transformations.
643
644 // Calculate some constants from uuT
645 const Type xx( Type( u.x * u.x ) );
646 const Type yy( Type( u.y * u.y ) );
647 const Type zz( Type( u.z * u.z ) );
648 const Type xy( Type( u.x * u.y ) );
649 const Type xz( Type( u.x * u.z ) );
650 const Type yz( Type( u.y * u.z ) );
651
652 // Calculate the sine and cosine of the rotation angle for use
653 // in the calculation of the rotation matrix.
654 const double a( double( angle ) * DEG_TO_RAD );
655 const Type sina( (Type)sin( a ) );
656 const Type cosa( (Type)cos( a ) );
657
658 // Now calculate M, which is the 3x3 version of the rotation
659 // matrix using the formula for rotation about an arbitrary axis.
660 // GlsMatrix<Type,3> M = UUT + ((I - UUT) * cosa) + (S * sina);
661
662 // Assign M to the first 3 columns and rows of the final rotation
663 // matrix R.
665
666 R( 0, 0 ) = xx + ( 1 - xx ) * cosa;
667 R( 1, 0 ) = xy - xy * cosa + u.z * sina;
668 R( 2, 0 ) = xz - xz * cosa - u.y * sina;
669
670 R( 0, 1 ) = xy - xy * cosa - u.z * sina;
671 R( 1, 1 ) = yy + ( 1 - yy ) * cosa;
672 R( 2, 1 ) = yz - yz * cosa + u.x * sina;
673
674 R( 0, 2 ) = xz - xz * cosa + u.y * sina;
675 R( 1, 2 ) = yz - yz * cosa - u.x * sina;
676 R( 2, 2 ) = zz + ( 1 - zz ) * cosa;
677
678 // Multiply the current matrix by the translation, then the rotation,
679 // and then translate back using the inverse.
680 // *this = TInv * R * T * *this;
681 this->Translate( -centerOfRotation.x, -centerOfRotation.y, -centerOfRotation.z );
682 *this = R * *this;
683 this->Translate( centerOfRotation.x, centerOfRotation.y, centerOfRotation.z );
684 }
685}
686//----------------------------------------------------------------------------
687template<class Type>
688void GlsMatrixAffine<Type>::Scale( Type x, Type y, Type z )
689{
690 // The scaling matrix, where x, y, and z are on the diagonal.
691 // x 0 0 0
692 // 0 y 0 0
693 // 0 0 z 0
694 // 0 0 0 1
695 // As can be seen most of the matrix is zero
696 // So optimized
697
698 _matrix[ 0 ][ 0 ] = _matrix[ 0 ][ 0 ] * x;
699 _matrix[ 0 ][ 1 ] = _matrix[ 0 ][ 1 ] * y;
700 _matrix[ 0 ][ 2 ] = _matrix[ 0 ][ 2 ] * z;
701 //_matrix[0][3] = _matrix[0][3];
702
703 _matrix[ 1 ][ 0 ] = _matrix[ 1 ][ 0 ] * x;
704 _matrix[ 1 ][ 1 ] = _matrix[ 1 ][ 1 ] * y;
705 _matrix[ 1 ][ 2 ] = _matrix[ 1 ][ 2 ] * z;
706 //_matrix[1][3] = _matrix[1][3];
707
708 _matrix[ 2 ][ 0 ] = _matrix[ 2 ][ 0 ] * x;
709 _matrix[ 2 ][ 1 ] = _matrix[ 2 ][ 1 ] * y;
710 _matrix[ 2 ][ 2 ] = _matrix[ 2 ][ 2 ] * z;
711 //_matrix[2][3] = _matrix[2][3];
712
713 _matrix[ 3 ][ 0 ] = _matrix[ 3 ][ 0 ] * x;
714 _matrix[ 3 ][ 1 ] = _matrix[ 3 ][ 1 ] * y;
715 _matrix[ 3 ][ 2 ] = _matrix[ 3 ][ 2 ] * z;
716 //_matrix[3][3] = _matrix[3][3];
717
718 // Row 3 is multiplied by 1, so no need...
719}
720//----------------------------------------------------------------------------
721template<class Type>
722void GlsMatrixAffine<Type>::Scale( Type x, Type y, Type z, const Vector& anchor )
723{
724 // First, we must translate the anchor point to the origin,
725 // perform the scaling and then translate back to the anchor
726 // point. This is the transformation matrix we are multiplying by:
727 // (Ax, Ay, Az are the components of anchor)
728 // | x 0 0 Ax-x*Ax |
729 // T = | 0 y 0 Ay-y*Ay |
730 // | 0 0 z Az-z*Az |
731 // | 0 0 0 1 |
732 const Type T00 = x;
733 const Type T11 = y;
734 const Type T22 = z;
735 const Type T03 = anchor.x * ( 1 - x );
736 const Type T13 = anchor.y * ( 1 - y );
737 const Type T23 = anchor.z * ( 1 - z );
738
739 // Multiply the current matrix by the transformation
740 // *this = T * *this;
741
742 _matrix[ 0 ][ 0 ] = _matrix[ 0 ][ 0 ] * T00 + _matrix[ 0 ][ 3 ] * T03;
743 _matrix[ 0 ][ 1 ] = _matrix[ 0 ][ 1 ] * T11 + _matrix[ 0 ][ 3 ] * T13;
744 _matrix[ 0 ][ 2 ] = _matrix[ 0 ][ 2 ] * T22 + _matrix[ 0 ][ 3 ] * T23;
745 //_matrix[0][3] = _matrix[0][3];
746
747 _matrix[ 1 ][ 0 ] = _matrix[ 1 ][ 0 ] * T00 + _matrix[ 1 ][ 3 ] * T03;
748 _matrix[ 1 ][ 1 ] = _matrix[ 1 ][ 1 ] * T11 + _matrix[ 1 ][ 3 ] * T13;
749 _matrix[ 1 ][ 2 ] = _matrix[ 1 ][ 2 ] * T22 + _matrix[ 1 ][ 3 ] * T23;
750 //_matrix[1][3] = _matrix[1][3];
751
752 _matrix[ 2 ][ 0 ] = _matrix[ 2 ][ 0 ] * T00 + _matrix[ 2 ][ 3 ] * T03;
753 _matrix[ 2 ][ 1 ] = _matrix[ 2 ][ 1 ] * T11 + _matrix[ 2 ][ 3 ] * T13;
754 _matrix[ 2 ][ 2 ] = _matrix[ 2 ][ 2 ] * T22 + _matrix[ 2 ][ 3 ] * T23;
755 //_matrix[2][3] = _matrix[2][3];
756
757 _matrix[ 3 ][ 0 ] = _matrix[ 3 ][ 0 ] * T00 + _matrix[ 3 ][ 3 ] * T03;
758 _matrix[ 3 ][ 1 ] = _matrix[ 3 ][ 1 ] * T11 + _matrix[ 3 ][ 3 ] * T13;
759 _matrix[ 3 ][ 2 ] = _matrix[ 3 ][ 2 ] * T22 + _matrix[ 3 ][ 3 ] * T23;
760 //_matrix[3][3] = _matrix[3][3];
761}
762
763/// Typedef for a generic (float or double) matrix element.
764#ifdef MATRIX_TYPE_FLOAT
765typedef float GlsMatrixElementType;
766#else
767typedef double GlsMatrixElementType;
768#endif
769
770/// Typedef for a generic (float or double elements) matrix.
771#ifdef MATRIX_TYPE_FLOAT
773#else
775#endif
776
777/// Macro to call the appropriate glLoadMatrix call whether we are using floats or doubles.
778#ifdef MATRIX_TYPE_FLOAT
779# define GLS_glLoadMatrix_TYPE glLoadMatrixf
780#else
781# define GLS_glLoadMatrix_TYPE glLoadMatrixd
782#endif
783
784/// Macro to call the appropriate glMultMatrix call whether we are using floats or doubles.
785#ifdef MATRIX_TYPE_FLOAT
786# define GLS_glMultMatrix_TYPE glMultMatrixf
787#else
788# define GLS_glMultMatrix_TYPE glMultMatrixd
789#endif
790
791} // namespace disti
792
793#endif
unsigned char G() const
Definition: gls_color.h:214
unsigned char R() const
Definition: gls_color.h:211
unsigned char B() const
Definition: gls_color.h:217
unsigned char A() const
Definition: gls_color.h:220
Definition: gls_matrix_affine.h:61
void Rotate(Type angle, RotationAxis axis)
Definition: gls_matrix_affine.h:392
void Scale(Type x, Type y, Type z)
Definition: gls_matrix_affine.h:688
void Rotate(Type angle, const Vector &centerOfRotation, RotationAxis axis)
Definition: gls_matrix_affine.h:483
void Scale(Type x, Type y, Type z, const Vector &anchor)
Definition: gls_matrix_affine.h:722
GlsMatrixAffine()
Definition: gls_matrix_affine.h:363
void Rotate(Type angle, const Vector &centerOfRotation, const Vector &axis)
Definition: gls_matrix_affine.h:607
void Translate(const Vector &v)
Definition: gls_matrix_affine.h:240
Vertex operator*(const Vertex &v) const
Definition: gls_matrix_affine.h:258
Vector operator*(const Vector &v) const
Definition: gls_matrix_affine.h:247
void Transform(Vector &v) const
Definition: gls_matrix_affine.h:273
~GlsMatrixAffine()
Definition: gls_matrix_affine.h:386
void Translate(Type x, Type y, Type z)
Definition: gls_matrix_affine.h:205
bool IsVeryClose(const GlsMatrix< Type, 4 > &b) const
Definition: gls_matrix_affine.h:117
Definition: gls_matrix.h:62
Type * Data()
Definition: gls_matrix.h:128
static const double PRECISION
Definition: gls_matrix.h:368
Type * _matrix[DIM]
Definition: gls_matrix.h:389
Type _data[DIM *DIM]
Definition: gls_matrix.h:377
Definition: gls_quaternion.h:57
Definition: vertex.h:85
float MagnitudeSquared() const
Definition: vertex.h:338
float y
The Y component.
Definition: vertex.h:88
float x
The X component.
Definition: vertex.h:87
float Magnitude() const
Definition: vertex.h:330
void Normalize()
Definition: vertex.h:311
float z
The Z component.
Definition: vertex.h:89
Definition: vertex.h:420
GlsColor color
The RGBA color component.
Definition: vertex.h:422
#define DISTI_DEPRECATED(msg)
Defines whether this compiler supports the C++14 deprecated attribute.
Definition: gls_cpp_lang_support.h:457
The GlsMatrix class.
The disti::GlsQuaternion class.
Force inclusion of the DirectShow library.
Definition: bmpimage.h:47
GlsMatrix< Type, 4 > DecomposeRotationMatrix(const GlsMatrix< Type, 4 > &matrix, const Vector &scale)
Definition: gls_matrix_affine.h:308
GlsMatrixAffine< double > GlsMatrixAffineD
Typedef for a matrix of doubles.
Definition: gls_matrix_affine.h:353
Vector DecomposeScale(const GlsMatrix< Type, 4 > &m)
Definition: gls_matrix_affine.h:293
RotationAxis
Definition: vertex.h:74
@ Z_AXIS
Definition: vertex.h:77
@ X_AXIS
Definition: vertex.h:75
@ Y_AXIS
Definition: vertex.h:76
const double DEG_TO_RAD
Definition: vertex.h:61
VertexNoColor Vector
Definition: gls_font_base.h:69
void DecomposeMatrix(const GlsMatrix< Type, 4 > &matrix, Vector &scale, Vector &location, GlsQuaternion< Type > &rotation)
Definition: gls_matrix_affine.h:342
GlsMatrixAffine< float > GlsMatrixAffineF
Typedef for a matrix of floats.
Definition: gls_matrix_affine.h:352
GlsMatrixAffineD GlsMatrixType
Typedef for a generic (float or double elements) matrix.
Definition: gls_matrix_affine.h:774
double GlsMatrixElementType
Typedef for a generic (float or double) matrix element.
Definition: gls_matrix_affine.h:767
The disti::Vertex class. A class for manipulating 3D vertices.