| 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:
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 //------------------------------------------------------------------------
73 GlsMatrixAffine();
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 //------------------------------------------------------------------------
109 ~GlsMatrixAffine();
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 */
292 template<class Type>
293 Vector DecomposeScale( const GlsMatrix<Type, 4>& m )
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 */
307 template<class Type>
308 GlsMatrix<Type, 4> DecomposeRotationMatrix( const GlsMatrix<Type, 4>& matrix, const Vector& scale )
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 */
341 template<class Type>
342 void 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
352 typedef GlsMatrixAffine<float> GlsMatrixAffineF; ///< Typedef for a matrix of floats.
353 typedef GlsMatrixAffine<double> GlsMatrixAffineD; ///< Typedef for a matrix of doubles.
354
355//============================================================================
356//
357// CLASS IMPLEMENTATION
358//
359//============================================================================
360
361//----------------------------------------------------------------------------
362 template<class Type>
363 GlsMatrixAffine<Type>::GlsMatrixAffine()
364{
365}
366//----------------------------------------------------------------------------
367 template<class Type>
368 GlsMatrixAffine<Type>::GlsMatrixAffine( const Type m[ 4 ][ 4 ] )
369 : GlsMatrix<Type, 4>( m )
370{
371}
372//----------------------------------------------------------------------------
373 template<class Type>
374 GlsMatrixAffine<Type>::GlsMatrixAffine( const Type* m )
375 : GlsMatrix<Type, 4>( m )
376{
377}
378//----------------------------------------------------------------------------
379 template<class Type>
380 GlsMatrixAffine<Type>::GlsMatrixAffine( const GlsMatrix<Type, 4>& m )
381 : GlsMatrix<Type, 4>( m )
382{
383}
384//----------------------------------------------------------------------------
385 template<class Type>
386 GlsMatrixAffine<Type>::~GlsMatrixAffine()
387{
388}
389
390//----------------------------------------------------------------------------
391 template<class Type>
392 void GlsMatrixAffine<Type>::Rotate( Type angle, RotationAxis axis )
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//----------------------------------------------------------------------------
482 template<class Type>
483 void GlsMatrixAffine<Type>::Rotate( Type angle,
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//----------------------------------------------------------------------------
606 template<class Type>
607 void GlsMatrixAffine<Type>::Rotate( Type angle,
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.
664 GlsMatrix<Type, 4> 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//----------------------------------------------------------------------------
687 template<class Type>
688 void 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//----------------------------------------------------------------------------
721 template<class Type>
722 void 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
765 typedef float GlsMatrixElementType;
766#else
767 typedef double GlsMatrixElementType;
768#endif
769
770/// Typedef for a generic (float or double elements) matrix.
771#ifdef MATRIX_TYPE_FLOAT
772 typedef GlsMatrixAffineF GlsMatrixType;
773#else
774 typedef GlsMatrixAffineD GlsMatrixType;
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
disti::GlsColor::G
unsigned char G() const
Definition: gls_color.h:214
disti::GlsColor::R
unsigned char R() const
Definition: gls_color.h:211
disti::GlsColor::B
unsigned char B() const
Definition: gls_color.h:217
disti::GlsColor::A
unsigned char A() const
Definition: gls_color.h:220
disti::GlsMatrixAffine
Definition: gls_matrix_affine.h:61
disti::GlsMatrixAffine::Rotate
void Rotate(Type angle, RotationAxis axis)
Definition: gls_matrix_affine.h:392
disti::GlsMatrixAffine::Scale
void Scale(Type x, Type y, Type z)
Definition: gls_matrix_affine.h:688
disti::GlsMatrixAffine::Rotate
void Rotate(Type angle, const Vector &centerOfRotation, RotationAxis axis)
Definition: gls_matrix_affine.h:483
disti::GlsMatrixAffine::Scale
void Scale(Type x, Type y, Type z, const Vector &anchor)
Definition: gls_matrix_affine.h:722
disti::GlsMatrixAffine::GlsMatrixAffine
GlsMatrixAffine()
Definition: gls_matrix_affine.h:363
disti::GlsMatrixAffine::Rotate
void Rotate(Type angle, const Vector &centerOfRotation, const Vector &axis)
Definition: gls_matrix_affine.h:607
disti::GlsMatrixAffine::Translate
void Translate(const Vector &v)
Definition: gls_matrix_affine.h:240
disti::GlsMatrixAffine::operator*
Vertex operator*(const Vertex &v) const
Definition: gls_matrix_affine.h:258
disti::GlsMatrixAffine::operator*
Vector operator*(const Vector &v) const
Definition: gls_matrix_affine.h:247
disti::GlsMatrixAffine::Transform
void Transform(Vector &v) const
Definition: gls_matrix_affine.h:273
disti::GlsMatrixAffine::~GlsMatrixAffine
~GlsMatrixAffine()
Definition: gls_matrix_affine.h:386
disti::GlsMatrixAffine::Translate
void Translate(Type x, Type y, Type z)
Definition: gls_matrix_affine.h:205
disti::GlsMatrixAffine::IsVeryClose
bool IsVeryClose(const GlsMatrix< Type, 4 > &b) const
Definition: gls_matrix_affine.h:117
disti::GlsMatrix
Definition: gls_matrix.h:62
disti::GlsMatrix::Data
Type * Data()
Definition: gls_matrix.h:128
disti::GlsMatrix< Type, 4 >::PRECISION
static const double PRECISION
Definition: gls_matrix.h:368
disti::GlsMatrix< Type, 4 >::_matrix
Type * _matrix[DIM]
Definition: gls_matrix.h:389
disti::GlsMatrix< Type, 4 >::_data
Type _data[DIM *DIM]
Definition: gls_matrix.h:377
disti::GlsQuaternion
Definition: gls_quaternion.h:57
disti::VertexNoColor
Definition: vertex.h:85
disti::VertexNoColor::MagnitudeSquared
float MagnitudeSquared() const
Definition: vertex.h:338
disti::VertexNoColor::y
float y
The Y component.
Definition: vertex.h:88
disti::VertexNoColor::x
float x
The X component.
Definition: vertex.h:87
disti::VertexNoColor::Magnitude
float Magnitude() const
Definition: vertex.h:330
disti::VertexNoColor::Normalize
void Normalize()
Definition: vertex.h:311
disti::VertexNoColor::z
float z
The Z component.
Definition: vertex.h:89
disti::Vertex
Definition: vertex.h:420
disti::Vertex::color
GlsColor color
The RGBA color component.
Definition: vertex.h:422
DISTI_DEPRECATED
#define DISTI_DEPRECATED(msg)
Defines whether this compiler supports the C++14 deprecated attribute.
Definition: gls_cpp_lang_support.h:488
gls_matrix.h
The GlsMatrix class.
gls_quaternion.h
The disti::GlsQuaternion class.
disti
Definition: bmpimage.h:47
disti::DecomposeRotationMatrix
GlsMatrix< Type, 4 > DecomposeRotationMatrix(const GlsMatrix< Type, 4 > &matrix, const Vector &scale)
Definition: gls_matrix_affine.h:308
disti::GlsMatrixAffineD
GlsMatrixAffine< double > GlsMatrixAffineD
Typedef for a matrix of doubles.
Definition: gls_matrix_affine.h:353
disti::DecomposeScale
Vector DecomposeScale(const GlsMatrix< Type, 4 > &m)
Definition: gls_matrix_affine.h:293
disti::RotationAxis
RotationAxis
Definition: vertex.h:74
disti::Z_AXIS
@ Z_AXIS
Definition: vertex.h:77
disti::X_AXIS
@ X_AXIS
Definition: vertex.h:75
disti::Y_AXIS
@ Y_AXIS
Definition: vertex.h:76
disti::DEG_TO_RAD
const double DEG_TO_RAD
Definition: vertex.h:61
disti::Vector
VertexNoColor Vector
Definition: gls_font_base.h:69
disti::DecomposeMatrix
void DecomposeMatrix(const GlsMatrix< Type, 4 > &matrix, Vector &scale, Vector &location, GlsQuaternion< Type > &rotation)
Definition: gls_matrix_affine.h:342
disti::GlsMatrixAffineF
GlsMatrixAffine< float > GlsMatrixAffineF
Typedef for a matrix of floats.
Definition: gls_matrix_affine.h:352
disti::GlsMatrixType
GlsMatrixAffineD GlsMatrixType
Typedef for a generic (float or double elements) matrix.
Definition: gls_matrix_affine.h:774
disti::GlsMatrixElementType
double GlsMatrixElementType
Typedef for a generic (float or double) matrix element.
Definition: gls_matrix_affine.h:767
vertex.h
The disti::Vertex class. A class for manipulating 3D vertices.