SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLMat3.h
Go to the documentation of this file.
1 /**
2  * \file math/SLMat3.h
3  * \brief 3 x 3 Matrix for linear 3D transformations
4  * \date July 2014
5  * \authors Marcus Hudritsch
6  * \copyright http://opensource.org/licenses/GPL-3.0
7  * \remarks Please use clangformat to format the code. See more code style on
8  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
9 */
10 
11 #ifndef SLMAT3_H
12 #define SLMAT3_H
13 
14 #include <SLMath.h>
15 #include <Utils.h>
16 #include <SLVec3.h>
17 #include <iostream>
18 #include <assert.h>
19 
20 using namespace Utils;
21 
22 //-----------------------------------------------------------------------------
23 //! 3x3 matrix template class
24 /*!
25 Implements a 3 by 3 matrix template. 9 floats were used instead of the normal
26 [3][3] array. The order is columnwise as in OpenGL
27 
28 | 0 3 6 |
29 | 1 4 7 |
30 | 2 5 8 |
31 
32 \n type definitions for 3x3 matrice:
33 \n Use SLMat3f for a specific float type 3x3 matrix
34 \n Use SLMat3d for a specific double type 3x3 matrix
35 */
36 // clang-format off
37 template<class T>
38 class SLMat3
39 {
40  public:
41  T _m[9];
42 
43  // Overloaded constructors
44  SLMat3 (); //!< Sets identity matrix
45  SLMat3 (const SLMat3& A); //!< Sets mat by other SLMat3
46  SLMat3 (const T M0, const T M3, const T M6,
47  const T M1, const T M4, const T M7,
48  const T M2, const T M5, const T M8); //!< Sets matrix by components
49  SLMat3 (const T angleDEG,
50  const T axis_x,
51  const T axis_y,
52  const T axis_z); //!< Sets rotate matrix from axis & angle
53  SLMat3 (const T angleDEG,
54  const SLVec3<T> axis); //!< Sets rotate matrix
55  SLMat3 (const T scale_xyz); //!< Sets uniform scaling matrix
56  SLMat3 (const T angleXRAD,
57  const T angleYRAD,
58  const T angleZRAD); //!< Sets rotation matrix from Euler angles in radians
59 
60  // Setters
61  void setMatrix (const SLMat3& A);
62  void setMatrix (const SLMat3* A);
63  void setMatrix (const T* M);
64  void setMatrix (T M0, T M3, T M6,
65  T M1, T M4, T M7,
66  T M2, T M5, T M8);
67  void m (int i, T val) {assert(i>=0 && i<9); _m[i] = val;}
68 
69  // Getters
70  const T* m () const {return _m;}
71  T m (int i) const {assert(i>=0 && i<9); return _m[i];}
72 
73 
74  // Overloaded operators
75  SLMat3<T>& operator= (const SLMat3& A);
76  SLMat3<T>& operator*= (const SLMat3& A);
77  SLMat3<T>& operator= (const T* a);
78  SLMat3<T> operator+ (const SLMat3& A) const;
79  SLMat3<T> operator- (const SLMat3& A) const;
80  SLMat3<T> operator* (const SLMat3& A) const;
81  SLVec3<T> operator* (const SLVec3<T>& v) const;
82  SLMat3<T> operator* (T a) const; //!< scalar multiplication
83  SLMat3<T>& operator*= (T a); //!< scalar multiplication
84  SLMat3<T> operator/ (T a) const; //!< scalar division
85  SLMat3<T>& operator/= (T a); //!< scalar division
86  operator const T*() const {return _m;}
87  operator T* (){return _m;}
88  T& operator ()(SLint row, SLint col) {return _m[3*col+row];}
89  const T& operator ()(SLint row, SLint col)const {return _m[3*col+row];}
90 
91  //! Sets the rotation components
92  void rotation (const T angleDEG,
93  const SLVec3<T>& axis);
94  void rotation (const T angleDEG,
95  const T axisx, const T axisy, const T axisz);
96  void rotation (const T zAngleRAD, const T yAngleRAD, const T xAngleRAD);
97 
98  //! Sets the scaling components
99  void scale (const T sx, const T sy, const T sz);
100  void scale (const SLVec3<T>& s);
101  void scale (const T s);
102 
103  // Misc. methods
104  void identity ();
105  void transpose ();
107  void invert ();
109  T trace () const;
110  T det () const;
111 
112  void toAngleAxis (T& angleDEG, SLVec3<T>& axis) const;
113  void toEulerAnglesXYZ (T& xRotRAD, T& yRotRAD, T& zRotRAD);
114  void toEulerAnglesZYX (T& zRotRAD, T& yRotRAD, T& xRotRAD);
115  void fromEulerAnglesXYZ(const T angleXRAD,
116  const T angleYRAD,
117  const T angleZRAD);
118  void fromEulerAnglesZYX(const T angleZ1RAD,
119  const T angleY2RAD,
120  const T angleX3RAD);
121  void fromEulerAnglesZXZ(const T angleZ1RAD,
122  const T angleX2RAD,
123  const T angleZ2RAD);
124  void print (const SLchar* str) const;
125 
126  static void swap (T& a, T& b) {T t; t=a; a=b; b=t;}
127 };
128 
129 //-----------------------------------------------------------------------------
130 // constructors
131 //-----------------------------------------------------------------------------
132 template<class T>
134 {
135  identity();
136 }
137 //-----------------------------------------------------------------------------
138 template<class T>
140 {
141  setMatrix(A);
142 }
143 //-----------------------------------------------------------------------------
144 template<class T>
145 SLMat3<T>::SLMat3(T M0, T M3, T M6,
146  T M1, T M4, T M7,
147  T M2, T M5, T M8)
148 {
149  _m[0]=M0; _m[3]=M3; _m[6]=M6;
150  _m[1]=M1; _m[4]=M4; _m[7]=M7;
151  _m[2]=M2; _m[5]=M5; _m[8]=M8;
152 }
153 //-----------------------------------------------------------------------------
154 template<class T>
155 SLMat3<T>::SLMat3(const T angleDEG, const T axisx, const T axisy, const T axisz)
156 {
157  rotation(angleDEG, axisx, axisy, axisz);
158 }
159 //-----------------------------------------------------------------------------
160 template<class T>
161 SLMat3<T>::SLMat3(const T angleDEG, const SLVec3<T> axis)
162 {
163  rotation(angleDEG, axis);
164 }
165 //-----------------------------------------------------------------------------
166 template<class T>
167 SLMat3<T>::SLMat3(const T scale_xyz)
168 {
169  scale(scale_xyz);
170 }
171 //-----------------------------------------------------------------------------
172 template<class T>
173 SLMat3<T>::SLMat3(const T angleXRAD,
174  const T angleYRAD,
175  const T angleZRAD)
176 {
177  fromEulerAnglesXYZ(angleXRAD,
178  angleYRAD,
179  angleZRAD);
180 }
181 //-----------------------------------------------------------------------------
182 // matrix-matrix and matrix-vector operators
183 //-----------------------------------------------------------------------------
184 template<class T>
186 {
187  _m[0]=A._m[0]; _m[3]=A._m[3]; _m[6]=A._m[6];
188  _m[1]=A._m[1]; _m[4]=A._m[4]; _m[7]=A._m[7];
189  _m[2]=A._m[2]; _m[5]=A._m[5]; _m[8]=A._m[8];
190  return(*this);
191 }
192 //-----------------------------------------------------------------------------
193 template<class T>
195 {
196  for (int i=0; i<9; ++i) _m[i] = a[i];
197 }
198 //-----------------------------------------------------------------------------
199 // matrix component wise addition
200 template<class T>
202 {
203  SLMat3<T> sum(_m[0]+A._m[0], _m[3]+A._m[3], _m[6]+A._m[6],
204  _m[1]+A._m[1], _m[4]+A._m[4], _m[7]+A._m[7],
205  _m[2]+A._m[2], _m[5]+A._m[5], _m[8]+A._m[8]);
206  return(sum);
207 }
208 //-----------------------------------------------------------------------------
209 // matrix component wise subtraction
210 template<class T>
212 {
213  SLMat3<T> sub(_m[0]-A._m[0], _m[3]-A._m[3], _m[6]-A._m[6],
214  _m[1]-A._m[1], _m[4]-A._m[4], _m[7]-A._m[7],
215  _m[2]-A._m[2], _m[5]-A._m[5], _m[8]-A._m[8]);
216  return(sub);
217 }
218 //-----------------------------------------------------------------------------
219 // matrix multiplication
220 template<class T>
222 {
223  SLMat3<T> NewM(_m[0]*A._m[0] + _m[3]*A._m[1] + _m[6]*A._m[2], // ROW 1
224  _m[0]*A._m[3] + _m[3]*A._m[4] + _m[6]*A._m[5],
225  _m[0]*A._m[6] + _m[3]*A._m[7] + _m[6]*A._m[8],
226  _m[1]*A._m[0] + _m[4]*A._m[1] + _m[7]*A._m[2], // ROW 2
227  _m[1]*A._m[3] + _m[4]*A._m[4] + _m[7]*A._m[5],
228  _m[1]*A._m[6] + _m[4]*A._m[7] + _m[7]*A._m[8],
229  _m[2]*A._m[0] + _m[5]*A._m[1] + _m[8]*A._m[2], // ROW 3
230  _m[2]*A._m[3] + _m[5]*A._m[4] + _m[8]*A._m[5],
231  _m[2]*A._m[6] + _m[5]*A._m[7] + _m[8]*A._m[8]);
232  return(NewM);
233 }
234 //-----------------------------------------------------------------------------
235 // matrix multiplication
236 template<class T>
238 {
239  setMatrix(_m[0]*A._m[0] + _m[3]*A._m[1] + _m[6]*A._m[2], // ROW 1
240  _m[0]*A._m[3] + _m[3]*A._m[4] + _m[6]*A._m[5],
241  _m[0]*A._m[6] + _m[3]*A._m[7] + _m[6]*A._m[8],
242  _m[1]*A._m[0] + _m[4]*A._m[1] + _m[7]*A._m[2], // ROW 2
243  _m[1]*A._m[3] + _m[4]*A._m[4] + _m[7]*A._m[5],
244  _m[1]*A._m[6] + _m[4]*A._m[7] + _m[7]*A._m[8],
245  _m[2]*A._m[0] + _m[5]*A._m[1] + _m[8]*A._m[2], // ROW 3
246  _m[2]*A._m[3] + _m[5]*A._m[4] + _m[8]*A._m[5],
247  _m[2]*A._m[6] + _m[5]*A._m[7] + _m[8]*A._m[8]);
248  return *this;
249 }
250 //-----------------------------------------------------------------------------
251 template<class T>
253 {
254  SLVec3<T> NewV;
255  NewV.x = _m[0]*v.x + _m[3]*v.y + _m[6]*v.z;
256  NewV.y = _m[1]*v.x + _m[4]*v.y + _m[7]*v.z;
257  NewV.z = _m[2]*v.x + _m[5]*v.y + _m[8]*v.z;
258  return(NewV);
259 }
260 //-----------------------------------------------------------------------------
261 template<class T>
263 {
264  SLMat3<T> NewM(_m[0] * a, _m[3] * a, _m[6] * a,
265  _m[1] * a, _m[4] * a, _m[7] * a,
266  _m[2] * a, _m[5] * a, _m[8] * a);
267  return NewM;
268 }
269 //-----------------------------------------------------------------------------
270 // scalar multiplication
271 template<class T>
273 {
274  for (int i=0; i<9; ++i) _m[i] *= a;
275  return *this;
276 }
277 //-----------------------------------------------------------------------------
278 // scalar division
279 template<class T>
281 {
282  SLMat3<T> NewM(_m[0] / a, _m[3] / a, _m[6] / a,
283  _m[1] / a, _m[4] / a, _m[7] / a,
284  _m[2] / a, _m[5] / a, _m[8] / a);
285  return NewM;
286 }
287 //-----------------------------------------------------------------------------
288 // scalar division
289 template<class T>
291 {
292  for (int i=0; i<9; ++i) _m[i] /= a;
293  return *this;
294 }
295 //-----------------------------------------------------------------------------
296 // Setters
297 //-----------------------------------------------------------------------------
298 template<class T>
300 {
301  for (int i=0; i<9; ++i) _m[i] = A._m[i];
302 }
303 //-----------------------------------------------------------------------------
304 template<class T>
306 {
307  for (int i=0; i<9; ++i) _m[i] = A->_m[i];
308 }
309 //-----------------------------------------------------------------------------
310 template<class T>
311 void SLMat3<T>::setMatrix(const T* M)
312 {
313  for (int i=0; i<9; ++i) _m[i] = M[i];
314 }
315 //-----------------------------------------------------------------------------
316 template<class T>
317 void SLMat3<T>::setMatrix (T M0, T M3, T M6,
318  T M1, T M4, T M7,
319  T M2, T M5, T M8)
320 {
321  _m[0]=M0; _m[3]=M3; _m[6]=M6;
322  _m[1]=M1; _m[4]=M4; _m[7]=M7;
323  _m[2]=M2; _m[5]=M5; _m[8]=M8;
324 }
325 //-----------------------------------------------------------------------------
326 // Standard Matrix Operations
327 //-----------------------------------------------------------------------------
328 template<class T>
330 {
331  _m[0]=_m[4]=_m[8]=1;
332  _m[1]=_m[2]=_m[3]=_m[5]=_m[6]=_m[7]=0;
333 }
334 //-----------------------------------------------------------------------------
335 template<class T>
336 //! Transposes the matrix
338 {
339  swap(_m[1],_m[3]);
340  swap(_m[2],_m[6]);
341  swap(_m[5],_m[7]);
342 }
343 //-----------------------------------------------------------------------------
344 //! Returns the transposed of the matrix and leaves the itself unchanged
345 template<class T>
347 {
348  SLMat3<T> t(_m[0],_m[1],_m[2],
349  _m[3],_m[4],_m[5],
350  _m[6],_m[7],_m[8]);
351  return t;
352 }
353 //-----------------------------------------------------------------------------
354 //! Inverts the matrix
355 template<class T>
357 {
358  setMatrix(inverted());
359 }
360 //-----------------------------------------------------------------------------
361 //! Returns the inverse of the matrix and leaves itself unchanged
362 template<class T>
364 {
365  // Compute determinant as early as possible using these cofactors.
366  T d = det();
367 
368  if (fabs(d) < FLT_EPSILON)
369  {
370  SLMATH_LOG("3x3-Matrix is singular. Inversion impossible.");
371  exit(0);
372  }
373 
374  SLMat3<T> i;
375  i._m[0] = _m[4]*_m[8] - _m[7]*_m[5];
376  i._m[1] = _m[7]*_m[2] - _m[1]*_m[8];
377  i._m[2] = _m[1]*_m[5] - _m[4]*_m[2];
378  i._m[3] = _m[6]*_m[5] - _m[3]*_m[8];
379  i._m[4] = _m[0]*_m[8] - _m[6]*_m[2];
380  i._m[5] = _m[3]*_m[2] - _m[0]*_m[5];
381  i._m[6] = _m[3]*_m[7] - _m[6]*_m[4];
382  i._m[7] = _m[6]*_m[1] - _m[0]*_m[7];
383  i._m[8] = _m[0]*_m[4] - _m[3]*_m[1];
384 
385  i /= d;
386  return i;
387 }
388 //-----------------------------------------------------------------------------
389 // Standard Matrix Transformations
390 //-----------------------------------------------------------------------------
391 template<class T>
392 void SLMat3<T>::rotation(const T angleDEG, const SLVec3<T>& axis)
393 {
394  rotation(angleDEG, axis.x, axis.y, axis.z);
395 }
396 //-----------------------------------------------------------------------------
397 template<class T>
398 void SLMat3<T>::rotation(const T angleDEG,
399  const T axisx, const T axisy, const T axisz)
400 {
401  T angleRAD = (T)angleDEG * DEG2RAD;
402  T ca = (T)cos(angleRAD);
403  T sa = (T)sin(angleRAD);
404 
405  if (axisx==1 && axisy==0 && axisz==0) // about x-axis
406  { _m[0]=1; _m[3]=0; _m[6]=0;
407  _m[1]=0; _m[4]=ca; _m[7]=-sa;
408  _m[2]=0; _m[5]=sa; _m[8]=ca;
409  }
410  else if (axisx==0 && axisy==1 && axisz==0) // about y-axis
411  { _m[0]=ca; _m[3]=0; _m[6]=sa;
412  _m[1]=0; _m[4]=1; _m[7]=0;
413  _m[2]=-sa; _m[5]=0; _m[8]=ca;
414  }
415  else if (axisx==0 && axisy==0 && axisz==1) // about z-axis
416  { _m[0]=ca; _m[3]=-sa; _m[6]=0;
417  _m[1]=sa; _m[4]=ca; _m[7]=0;
418  _m[2]=0; _m[5]=0; _m[8]=1;
419  } // arbitrary axis
420  else
421  {
422  T l = axisx*axisx + axisy*axisy + axisz*axisz; // length squared
423  T x, y, z;
424  x=axisx, y=axisy, z=axisz;
425  if ((l > T(1.0001) || l < T(0.9999)) && l!=0)
426  { l=T(1.0)/sqrt(l);
427  x*=l; y*=l; z*=l;
428  }
429  T xy=x*y, yz=y*z, xz=x*z, xx=x*x, yy=y*y, zz=z*z;
430  _m[0]=xx + ca*(1-xx); _m[3]=xy - xy*ca - z*sa; _m[6]=xz - xz*ca + y*sa;
431  _m[1]=xy - xy*ca + z*sa; _m[4]=yy + ca*(1-yy); _m[7]=yz - yz*ca - x*sa;
432  _m[2]=xz - xz*ca - y*sa; _m[5]=yz - yz*ca + x*sa; _m[8]=zz + ca*(1-zz);
433  }
434 }
435 //-----------------------------------------------------------------------------
436 /*!
437 Sets the matrix as a rotation matrix from the 3 euler angles in radians around
438 the z-axis, y-axis & x-axis.
439 See Van Verth: Essential Math for Games, chapter 5: Orientation Representation
440 */
441 template<class T>
442 void SLMat3<T>::rotation(const T zAngleRAD, const T yAngleRAD, const T xAngleRAD)
443 {
444  T Cx = (T)cos(xAngleRAD); T Sx = (T)sin(xAngleRAD);
445  T Cy = (T)cos(yAngleRAD); T Sy = (T)sin(yAngleRAD);
446  T Cz = (T)cos(zAngleRAD); T Sz = (T)sin(zAngleRAD);
447 
448  _m[0] = (Cy * Cz);
449  _m[3] = -(Cy * Sz);
450  _m[6] = Sy;
451 
452  _m[1] = (Sx * Sy * Cz) + (Cx * Sz);
453  _m[4] = -(Sx * Sy * Sz) + (Cx * Cz);
454  _m[7] = -(Sx * Cy);
455 
456  _m[2] = -(Cx * Sy * Cz) + (Sx * Sz);
457  _m[5] = (Cx * Sy * Sz) + (Sx * Cz);
458  _m[8] = (Cx * Cy);
459 }
460 //-----------------------------------------------------------------------------
461 template<class T>
462 void SLMat3<T>::scale(T sx, T sy, T sz)
463 {
464  _m[0]=sx; _m[3]=0; _m[6]=0;
465  _m[1]=0; _m[4]=sy; _m[7]=0;
466  _m[2]=0; _m[5]=0; _m[8]=sz;
467 }
468 //-----------------------------------------------------------------------------
469 template<class T>
471 {
472  _m[0]=s.x; _m[3]=0; _m[6]=0;
473  _m[1]=0; _m[4]=s.y; _m[7]=0;
474  _m[2]=0; _m[5]=0; _m[8]=s.z;
475 }
476 //-----------------------------------------------------------------------------
477 template<class T>
478 void SLMat3<T>::scale(const T s)
479 {
480  _m[0]=s; _m[3]=0; _m[6]=0;
481  _m[1]=0; _m[4]=s; _m[7]=0;
482  _m[2]=0; _m[5]=0; _m[8]=s;
483 }
484 //-----------------------------------------------------------------------------
485 template<class T>
486 inline T SLMat3<T>::trace() const
487 {
488  return _m[0] + _m[4] + _m[8];
489 }
490 //-----------------------------------------------------------------------------
491 //! det returns the determinant
492 template<class T>
493 inline T SLMat3<T>::det() const
494 {
495  return _m[0]*(_m[4]*_m[8] - _m[7]*_m[5]) -
496  _m[3]*(_m[1]*_m[8] - _m[7]*_m[2]) +
497  _m[6]*(_m[1]*_m[5] - _m[4]*_m[2]);
498 }
499 //-----------------------------------------------------------------------------
500 //! Conversion to axis and angle in radians
501 /*!
502 The matrix must be a rotation matrix for this functions to be valid. The last
503 function uses Gram-Schmidt orthonormalization applied to the columns of the
504 rotation matrix. The angle must be in radians, not degrees.
505 */
506 template <typename T>
507 void SLMat3<T>::toAngleAxis(T& angleDEG, SLVec3<T>& axis) const
508 {
509  // Let (x,y,z) be the unit-length axis and let A be an angle of rotation.
510  // The rotation matrix is R = I + sin(A)*P + (1-cos(A))*P^2 where
511  // I is the identity and
512  //
513  // +- -+
514  // | 0 -z +y |
515  // P = | +z 0 -x |
516  // | -y +x 0 |
517  // +- -+
518  //
519  // If A > 0, R represents a counterclockwise rotation about the axis in
520  // the sense of looking from the tip of the axis vector towards the
521  // origin. Some algebra will show that
522  //
523  // cos(A) = (trace(R)-1)/2 and R - R^t = 2*sin(A)*P
524  //
525  // In the event that A = pi, R-R^t = 0 which prevents us from extracting
526  // the axis through P. Instead note that R = I+2*P^2 when A = pi, so
527  // P^2 = (R-I)/2. The diagonal entries of P^2 are x^2-1, y^2-1, and
528  // z^2-1. We can solve these for axis (x,y,z). Because the angle is pi,
529  // it does not matter which sign you choose on the square roots.
530 
531  T tr = trace();
532  T cs = ((T)0.5) * (tr - (T)1);
533  T angleRAD = acos(cs); // in [0,PI]
534 
535  if (angleRAD > (T)0)
536  {
537  if (angleRAD < PI)
538  {
539  axis.x = _m[5] - _m[7];
540  axis.y = _m[6] - _m[2];
541  axis.z = _m[1] - _m[3];
542  axis.normalize();
543  }
544  else
545  {
546  // angle is PI
547  T halfInverse;
548  if (_m[0] >= _m[4])
549  {
550  // r00 >= r11
551  if (_m[0] >= _m[8])
552  {
553  // r00 is maximum diagonal term
554  axis.x = ((T)0.5)*sqrt((T)1 + _m[0] - _m[4] - _m[8]);
555  halfInverse = ((T)0.5)/axis.x;
556  axis.y = halfInverse*_m[3];
557  axis.z = halfInverse*_m[6];
558  }
559  else
560  {
561  // r22 is maximum diagonal term
562  axis.z = ((T)0.5)*sqrt((T)1 + _m[8] - _m[0] - _m[4]);
563  halfInverse = ((T)0.5)/axis.z;
564  axis.x = halfInverse*_m[6];
565  axis.y = halfInverse*_m[7];
566  }
567  }
568  else
569  {
570  // r11 > r00
571  if (_m[4] >= _m[8])
572  {
573  // r11 is maximum diagonal term
574  axis.y = ((T)0.5)*sqrt((T)1 + _m[4] - _m[0] - _m[8]);
575  halfInverse = ((T)0.5)/axis.y;
576  axis.x = halfInverse*_m[3];
577  axis.z = halfInverse*_m[7];
578  }
579  else
580  {
581  // r22 is maximum diagonal term
582  axis.z = ((T)0.5)*sqrt((T)1 + _m[8] - _m[0] - _m[4]);
583  halfInverse = ((T)0.5)/axis.z;
584  axis.x = halfInverse*_m[6];
585  axis.y = halfInverse*_m[7];
586  }
587  }
588  }
589  }
590  else
591  {
592  // The angle is 0 and the matrix is the identity. Any axis will
593  // work, so just use the x-axis.
594  axis.x = (T)1;
595  axis.y = (T)0;
596  axis.z = (T)0;
597  }
598  angleDEG = angleRAD * RAD2DEG;
599 }
600 
601 //-----------------------------------------------------------------------------
602 /*!
603 Gets one set of possible x-y-z euler angles that will generate this matrix
604 Source: Essential Mathematics for Games and Interactive Applications
605 A Programmer's Guide 2nd edition by James M. Van Verth and Lars M. Bishop
606 */
607 template<class T>
608 void SLMat3<T>::toEulerAnglesXYZ(T& xRotRAD, T& yRotRAD, T& zRotRAD)
609 {
610  T Cx, Sx;
611  T Cy, Sy;
612  T Cz, Sz;
613 
614  Sy = _m[6];
615  Cy = (T)sqrt(1.0 - Sy*Sy);
616 
617  // normal case
618  if (Utils::abs(Cy) > FLT_EPSILON)
619  {
620  T factor = (T)1.0 / Cy;
621  Sx = -_m[7]*factor;
622  Cx = _m[8]*factor;
623  Sz = -_m[3]*factor;
624  Cz = _m[0]*factor;
625  }
626  else // x and z axes aligned
627  {
628  Sz = 0.0f;
629  Cz = 1.0f;
630  Sx = _m[5];
631  Cx = _m[4];
632  }
633 
634  zRotRAD = atan2f(Sz, Cz);
635  yRotRAD = atan2f(Sy, Cy);
636  xRotRAD = atan2f(Sx, Cx);
637 }
638 
639 /*!
640 Gets one set of possible z-y-x euler angles that will generate this matrix
641 Source: Essential Mathematics for Games and Interactive Applications
642 A Programmer's Guide 2nd edition by James M. Van Verth and Lars M. Bishop
643 */
644 template<class T>
645 void SLMat3<T>::toEulerAnglesZYX(T& zRotRAD, T& yRotRAD, T& xRotRAD)
646 {
647  T Cx, Sx;
648  T Cy, Sy;
649  T Cz, Sz;
650 
651  Sy = -_m[2];
652  Cy = (T)sqrt(1.0 - Sy*Sy);
653 
654  // normal case
655  if (Utils::abs(Cy) > FLT_EPSILON)
656  {
657  T factor = (T)1.0 / Cy;
658  Sx = _m[5]*factor;
659  Cx = _m[8]*factor;
660  Sz = _m[1]*factor;
661  Cz = _m[0]*factor;
662  }
663  else // x and z axes aligned
664  {
665  Sz = 0.0f;
666  Cz = 1.0f;
667  Sx = _m[3];
668  Cx = _m[6];
669  }
670 
671  zRotRAD = atan2f(Sz, Cz);
672  yRotRAD = atan2f(Sy, Cy);
673  xRotRAD = atan2f(Sx, Cx);
674 }
675 
676 //-----------------------------------------------------------------------------
677 /*!
678 Sets the linear 3x3 sub-matrix as a rotation matrix from the 3 euler angles
679 in radians around the z-axis, y-axis & x-axis := Rx * Ry * Rz
680 See: http://en.wikipedia.org/wiki/Euler_angles
681 */
682 template<class T>
683 void SLMat3<T>::fromEulerAnglesXYZ(const T angleX1RAD,
684  const T angleY2RAD,
685  const T angleZ3RAD)
686 {
687  T s1 = sin(angleX1RAD), c1 = cos(angleX1RAD);
688  T s2 = sin(angleY2RAD), c2 = cos(angleY2RAD);
689  T s3 = sin(angleZ3RAD), c3 = cos(angleZ3RAD);
690 
691  _m[0]=(T) (c2*c3); _m[3]=(T)-(c2*s3); _m[6] =(T) s2;
692  _m[1]=(T) (s1*s2*c3) + (c1*s3); _m[4]=(T)-(s1*s2*s3) + (c1*c3); _m[7] =(T)-(c2*s1);
693  _m[2]=(T)-(c1*s2*c3) + (s1*s3); _m[5]=(T) (c1*s2*s3) + (s1*c3); _m[8] =(T) (c1*c2);
694 }
695 //-----------------------------------------------------------------------------
696 /*!
697 Sets the linear 3x3 sub-matrix as a rotation matrix from the 3 euler angles
698 in radians around the x-axis, y-axis & z-axis := Rz * Ry * Rx
699 See: http://en.wikipedia.org/wiki/Euler_angles
700 */
701 template<class T>
702 void SLMat3<T>::fromEulerAnglesZYX(const T angleZ1RAD,
703  const T angleY2RAD,
704  const T angleX3RAD)
705 {
706  T s1 = sin(angleZ1RAD), c1 = cos(angleZ1RAD);
707  T s2 = sin(angleY2RAD), c2 = cos(angleY2RAD);
708  T s3 = sin(angleX3RAD), c3 = cos(angleX3RAD);
709 
710  _m[0]=(T) (c1*c2); _m[3]=(T) (c1*s2*s3) - (c3*s1); _m[6] =(T) (s1*s3) + (c1*c3*s2);
711  _m[1]=(T) (c2*s1); _m[4]=(T) (c1*c3) + (s1*s2*s3); _m[7] =(T) (c3*s1*s2) - (c1*s3);
712  _m[2]=(T)-s2; _m[5]=(T) (c2*s3); _m[8] =(T) (c2*c3);
713 }
714 //-----------------------------------------------------------------------------
715 /*!
716 Sets the linear 3x3 sub-matrix as a rotation matrix from the 3 euler angles
717 in radians around the z-axis, x-axis & z-axis:= Z1*X2*Z3
718 See: http://en.wikipedia.org/wiki/Euler_angles
719 */
720 template<class T>
721 void SLMat3<T>::fromEulerAnglesZXZ(const T angleZ1RAD,
722  const T angleX2RAD,
723  const T angleZ3RAD)
724 {
725  T s1 = sin(angleZ1RAD), c1 = cos(angleZ1RAD);
726  T s2 = sin(angleX2RAD), c2 = cos(angleX2RAD);
727  T s3 = sin(angleZ3RAD), c3 = cos(angleZ3RAD);
728 
729  _m[0]=(T)( c1*c3 - s1*c2*s3); _m[3]=(T)( s1*c3 + c1*c2*s3); _m[6] =(T)( s2*s3);
730  _m[1]=(T)(-c1*s3 - s1*c2*c3); _m[4]=(T)( c1*c2*c3 - s1*s3); _m[7] =(T)( s2*c3);
731  _m[2]=(T)( s1*s2); _m[5]=(T)(-c1*s2); _m[8] =(T)( c2);
732 }
733 
734 //-----------------------------------------------------------------------------
735 // Handy matrix printing routine.
736 //-----------------------------------------------------------------------------
737 template<class T>
738 void SLMat3<T>::print(const SLchar* str) const
739 {
740  if (str) SLMATH_LOG("%s",str);
741  SLMATH_LOG("% 3.3f % 3.3f % 3.3f", _m[0],_m[3],_m[6]);
742  SLMATH_LOG("% 3.3f % 3.3f % 3.3f", _m[1],_m[4],_m[7]);
743  SLMATH_LOG("% 3.3f % 3.3f % 3.3f", _m[2],_m[5],_m[8]);
744 }
745 //-----------------------------------------------------------------------------
748 //-----------------------------------------------------------------------------
749 #endif
char SLchar
Definition: SL.h:162
int SLint
Definition: SL.h:170
SLMat3< SLdouble > SLMat3d
Definition: SLMat3.h:747
SLMat3< SLfloat > SLMat3f
Definition: SLMat3.h:746
#define SLMATH_LOG(...)
Definition: SLMath.h:70
SLScene * s
Definition: SLScene.h:31
3x3 matrix template class
Definition: SLMat3.h:39
SLMat3()
Sets identity matrix.
Definition: SLMat3.h:133
SLMat3< T > operator/(T a) const
scalar division
Definition: SLMat3.h:280
void toEulerAnglesZYX(T &zRotRAD, T &yRotRAD, T &xRotRAD)
Definition: SLMat3.h:645
SLMat3(const SLMat3 &A)
Sets mat by other SLMat3.
Definition: SLMat3.h:139
void scale(const SLVec3< T > &s)
Definition: SLMat3.h:470
void rotation(const T angleDEG, const SLVec3< T > &axis)
Sets the rotation components
Definition: SLMat3.h:392
T trace() const
Definition: SLMat3.h:486
void transpose()
Transposes the matrix.
Definition: SLMat3.h:337
void rotation(const T zAngleRAD, const T yAngleRAD, const T xAngleRAD)
Definition: SLMat3.h:442
void rotation(const T angleDEG, const T axisx, const T axisy, const T axisz)
Definition: SLMat3.h:398
void m(int i, T val)
Definition: SLMat3.h:67
SLMat3(const T angleXRAD, const T angleYRAD, const T angleZRAD)
Sets rotation matrix from Euler angles in radians.
Definition: SLMat3.h:173
T det() const
det returns the determinant
Definition: SLMat3.h:493
const T * m() const
Definition: SLMat3.h:70
SLMat3< T > transposed() const
Returns the transposed of the matrix and leaves the itself unchanged.
Definition: SLMat3.h:346
SLMat3(const T scale_xyz)
Sets uniform scaling matrix.
Definition: SLMat3.h:167
void setMatrix(const SLMat3 &A)
Definition: SLMat3.h:299
SLMat3< T > operator+(const SLMat3 &A) const
Definition: SLMat3.h:201
void scale(const T sx, const T sy, const T sz)
Sets the scaling components.
Definition: SLMat3.h:462
SLMat3< T > operator-(const SLMat3 &A) const
Definition: SLMat3.h:211
void fromEulerAnglesZYX(const T angleZ1RAD, const T angleY2RAD, const T angleX3RAD)
Definition: SLMat3.h:702
SLMat3< T > & operator=(const SLMat3 &A)
Definition: SLMat3.h:185
SLMat3(const T angleDEG, const SLVec3< T > axis)
Sets rotate matrix.
Definition: SLMat3.h:161
void toAngleAxis(T &angleDEG, SLVec3< T > &axis) const
Conversion to axis and angle in radians.
Definition: SLMat3.h:507
void print(const SLchar *str) const
Definition: SLMat3.h:738
void setMatrix(const T *M)
Definition: SLMat3.h:311
void setMatrix(T M0, T M3, T M6, T M1, T M4, T M7, T M2, T M5, T M8)
Definition: SLMat3.h:317
void scale(const T s)
Definition: SLMat3.h:478
void identity()
Definition: SLMat3.h:329
SLMat3< T > & operator*=(const SLMat3 &A)
Definition: SLMat3.h:237
SLMat3< T > operator*(const SLMat3 &A) const
Definition: SLMat3.h:221
SLMat3(const T angleDEG, const T axis_x, const T axis_y, const T axis_z)
Sets rotate matrix from axis & angle.
Definition: SLMat3.h:155
void fromEulerAnglesXYZ(const T angleXRAD, const T angleYRAD, const T angleZRAD)
Definition: SLMat3.h:683
SLMat3< T > inverted()
Returns the inverse of the matrix and leaves itself unchanged.
Definition: SLMat3.h:363
void invert()
Inverts the matrix.
Definition: SLMat3.h:356
SLMat3< T > & operator/=(T a)
scalar division
Definition: SLMat3.h:290
SLMat3(const T M0, const T M3, const T M6, const T M1, const T M4, const T M7, const T M2, const T M5, const T M8)
Sets matrix by components.
Definition: SLMat3.h:145
void fromEulerAnglesZXZ(const T angleZ1RAD, const T angleX2RAD, const T angleZ2RAD)
Definition: SLMat3.h:721
static void swap(T &a, T &b)
Definition: SLMat3.h:126
T _m[9]
Definition: SLMat3.h:41
void setMatrix(const SLMat3 *A)
Definition: SLMat3.h:305
void toEulerAnglesXYZ(T &xRotRAD, T &yRotRAD, T &zRotRAD)
Definition: SLMat3.h:608
T m(int i) const
Definition: SLMat3.h:71
The SLScene class represents the top level instance holding the scene structure.
Definition: SLScene.h:47
3D vector template class for standard 3D vector algebra.
Definition: SLVec3.h:40
T y
Definition: SLVec3.h:43
T x
Definition: SLVec3.h:43
SLVec3 & normalize()
Definition: SLVec3.h:124
T z
Definition: SLVec3.h:43
Utils provides utilities for string & file handling, logging and math functions.
Definition: Averaged.h:22
static const float DEG2RAD
Definition: Utils.h:239
T abs(T a)
Definition: Utils.h:249
static const float RAD2DEG
Definition: Utils.h:238
static const float PI
Definition: Utils.h:237