SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLMat4.h
Go to the documentation of this file.
1 /**
2  * \file math/SLMat4.h
3  * \brief 4 x 4 Matrix for affine 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 SLMAT4_H
12 #define SLMAT4_H
13 
14 #include <SLMath.h>
15 #include <stack>
16 #include <Utils.h>
17 #include <SLMat3.h>
18 #include <SLVec3.h>
19 #include <SLVec4.h>
20 #include <cassert>
21 #include <Shoemake/Decompose.h>
22 #include <Shoemake/EulerAngles.h>
23 
24 //-----------------------------------------------------------------------------
25 //! 4x4 matrix template class
26 /*!
27 Implements a 4 by 4 matrix template class. An array of 16 floats or double is
28 used instead of a 2D array [4][4] to be compliant with OpenGL.
29 The index layout is as follows:
30 <PRE>
31  | 0 4 8 12 |
32  | 1 5 9 13 |
33  M = | 2 6 10 14 |
34  | 3 7 11 15 |
35 
36 </PRE>
37 Vectors are interpreted as column vectors when applying matrix multiplications.
38 This means a vector is as a single column, 4-row matrix. The result is that the
39 transformations implemented by the matrices happens right-to-left e.g. if
40 vector V is to be transformed by M1 then M2 then M3, the calculation would
41 be M3 * M2 * M1 * V. The order that matrices are concatenated is vital
42 since matrix multiplication is not commutative, i.e. you can get a different
43 result if you concatenate in the wrong order.
44 The use of column vectors and right-to-left ordering is the standard in most
45 mathematical texts, and is the same as used in OpenGL. It is, however, the
46 opposite of Direct3D, which has inexplicably chosen to differ from the
47 accepted standard and uses row vectors and left-to-right matrix multiplication.
48 */
49 // clang-format off
50 template<class T>
51 class SLMat4
52 {
53  public:
54  // Constructors
55  SLMat4 (); //!< Sets identity matrix
56  SLMat4 (const SLMat4& A); //!< Sets mat by other SLMat4
57  SLMat4 (const SLMat3f& A); //!< Sets mat by other SLMat3
58  SLMat4 (const T* M); //!< Sets mat by array
59  SLMat4 (T M0, T M4, T M8, T M12,
60  T M1, T M5, T M9, T M13,
61  T M2, T M6, T M10, T M14,
62  T M3, T M7, T M11, T M15);
63  SLMat4 (T tx,
64  T ty,
65  T tz); //!< Sets translate matrix
66  explicit SLMat4 (T degAng,
67  T axis_x,
68  T axis_y,
69  T axis_z); //!< Sets rotation matrix
70  explicit SLMat4 (T scale_xyz); //!< Sets scaling matrix
71  explicit SLMat4 (const SLVec3<T>& translationVec); //!< Sets translate matrix
72  SLMat4 (const SLVec3<T>& fromUnitVec,
73  const SLVec3<T>& toUnitVec); //!< Sets rotation matrix
75  const SLMat3<T>& rotation,
76  const SLVec3<T>& scale); //!< Set matrix by translation, rotation & scale
77 
78  // Setters
79  void setMatrix (const SLMat4& A); //!< Set matrix by other 4x4 matrix
80  void setMatrix (const SLMat3f& A); //!< Set matrix by other 3x3 matrix
81  void setMatrix (const SLMat4* A); //!< Set matrix by other matrix pointer
82  void setMatrix (const T* M); //!< Set matrix by float[16] array
83  void setMatrix (T M0, T M4, T M8 , T M12,
84  T M1, T M5, T M9 , T M13,
85  T M2, T M6, T M10, T M14,
86  T M3, T M7, T M11, T M15); //!< Set matrix by components
88  const SLMat3<T>& rotation,
89  const SLVec3<T>& scale); //!< Set matrix by translation, rotation & scale
90  void setMatrix (const int16_t i, const SLfloat value) { assert(i >= 0 && i < 16); _m[i] = value; }
91  void setRotation (const SLMat3<T>& rotation); //!< Set 3x3 submatrix describing the rotational part
92  void setTranslation (const SLVec3<T>& translation); //!< Set vector as submatrix describing the translational part
93  void m (int i, T val) {assert(i>=0 && i<16); _m[i] = val;}
94 
95  // Getters
96  const T* m () const {return _m;}
97  T m (int i) const {assert(i>=0 && i<16); return _m[i];}
98  SLMat3<T> mat3 () const {SLMat3<T> m3;
99  m3.setMatrix(_m[0], _m[4], _m[ 8],
100  _m[1], _m[5], _m[ 9],
101  _m[2], _m[6], _m[10]);
102  return m3;}
103  // Operators
104  SLMat4<T>& operator= (const SLMat4& A); //!< assignment operator
105  SLMat4<T> operator* (const SLMat4& A) const; //!< matrix-matrix multiplication
106  SLMat4<T>& operator*= (const SLMat4& A); //!< matrix-matrix multiplication
107  SLMat4<T> operator+ (const SLMat4& A) const; //!< matrix-matrix addition
108  SLVec3<T> operator* (const SLVec3<T>& v) const;//!< SLVec3 mult w. persp div
109  SLVec4<T> operator* (const SLVec4<T>& v) const;//!< SLVec4 mult
110  SLMat4<T> operator* (T a) const; //!< scalar mult
111  SLMat4<T>& operator*= (T a); //!< scalar mult
112  SLMat4<T> operator/ (T a) const; //!< scalar division
113  SLMat4<T>& operator/= (T a); //!< scalar division
114  T& operator ()(int row, int col) {return _m[4*col+row];}
115  const T& operator ()(int row, int col)const {return _m[4*col+row];}
116 
117  SLbool isEqual (const SLMat4& A, SLfloat epsilon = 0.01f);
118  void multiply (const SLMat4& A);
121  void add (const SLMat4& A);
122  void translate (T tx, T ty, T tz=0);
123  void translate (const SLVec2<T>& t);
124  void translate (const SLVec3<T>& t);
125  void rotate (T degAng,
126  T axisx, T axisy, T axisz);
127  void rotate (T degAng,
128  const SLVec3<T>& axis);
129  void rotate (const SLVec3<T>& fromUnitVec,
130  const SLVec3<T>& toUnitVec);
131  void scale (T sxyz);
132  void scale (T sx, T sy, T sz);
133  void scale (const SLVec3<T>& sxyz);
134 
135  //! Defines a view frustum projection matrix equivalent to glFrustum
136  void frustum (T l, T r, T b, T t, T n, T f);
137 
138  //! Defines a perspective projection matrix with a field of view angle
139  void perspective (T fov, T aspect, T n, T f);
140 
141  //! Defines a projection matrix for a calibrated camera (from intrinsics matrix)
142  //! Attention: The principle point has to be centered
143  void perspectiveCenteredPP(T w, T h, T fx, T fy, T cx, T cy, T n, T f);
144 
145  //! Defines a orthographic projection matrix with a field of view angle
146  void ortho (T l, T r, T b, T t, T n, T f);
147 
148  //! Defines the viewport matrix
149  void viewport (T x, T y, T ww, T wh, T n=0.0f, T f=1.0f);
150 
151  //! Defines the a view matrix as the corresponding gluLookAt function
152  void lookAt (T EyeX, T EyeY, T EyeZ,
153  T AtX=0, T AtY=0, T AtZ=0,
154  T UpX=0, T UpY=0, T UpZ=0);
155 
156  //! Defines the a view matrix as the corresponding gluLookAt function
157  void lookAt (const SLVec3<T>& Eye,
158  const SLVec3<T>& At=SLVec3<T>::ZERO,
159  const SLVec3<T>& Up=SLVec3<T>::ZERO);
160 
161  //! Reads out of the matrix the look at parameters
162  void lookAt (SLVec3<T>* eye,
163  SLVec3<T>* at,
164  SLVec3<T>* up,
165  SLVec3<T>* right) const;
166 
167  //! Defines the a model matrix for light positioning
168  void lightAt (T PosX, T PosY, T PosZ,
169  T AtX=0, T AtY=0, T AtZ=0,
170  T UpX=0, T UpY=0, T UpZ=0);
171 
172  //! Defines the a model matrix for light positioning
173  void lightAt (const SLVec3<T>& pos,
174  const SLVec3<T>& At=SLVec3<T>::ZERO,
175  const SLVec3<T>& Up=SLVec3<T>::ZERO);
176  void posAtUp (T PosX, T PosY, T PosZ,
177  T dirAtX=0, T dirAtY=0, T dirAtZ=0,
178  T dirUpX=0, T dirUpY=0, T dirUpZ=0);
179  void posAtUp (const SLVec3<T>& pos,
180  const SLVec3<T>& dirAt=SLVec3<T>::ZERO,
181  const SLVec3<T>& dirUp=SLVec3<T>::ZERO);
182 
183  // Returns the axis and translation vectors
184  SLVec3<T> translation () const {return SLVec3<T>(_m[12], _m[13], _m[14]);}
185  SLVec3<T> axisX () const {return SLVec3<T>(_m[ 0], _m[ 1], _m[ 2]);}
186  SLVec3<T> axisY () const {return SLVec3<T>(_m[ 4], _m[ 5], _m[ 6]);}
187  SLVec3<T> axisZ () const {return SLVec3<T>(_m[ 8], _m[ 9], _m[10]);}
188 
189  //! Sets the translation with or without overwriting the linear submatrix
190  void translation (T tx, T ty, T tz,
191  SLbool keepLinear=true);
192  void translation (const SLVec3<T>& t,
193  SLbool keepLinear=true);
194 
195  //! Sets the rotation with or without overwriting the translation
196  void rotation (T degAng,
197  const SLVec3<T>& axis,
198  SLbool keepTranslation=true);
199  void rotation (T degAng,
200  T axisx, T axisy, T axisz,
201  SLbool keepTranslation=true);
202  void rotation (const SLVec3<T>& fromUnitVec,
203  const SLVec3<T>& toUnitVec);
204 
205  //! Sets the scaling with or without overwriting the translation
206  void scaling (T sxyz, SLbool keepTrans=true);
207  void scaling (const SLVec3<T>& sxyz, SLbool keepTrans=true);
208  void scaling (T sx, T sy, T sz, SLbool keepTranslation=true);
209 
210  // Set matrix from euler angles or get euler angles from matrix
211  void fromEulerAnglesZXZ(double angle1RAD,
212  double angle2RAD,
213  double angle3RAD,
214  bool keepTranslation=true);
215  void fromEulerAnglesXYZ(double angle1RAD,
216  double angle2RAD,
217  double angle3RAD,
218  bool keepTranslation=true);
219 
220  // Get euler angles from matrix
221  void toEulerAnglesZYX(T& zRotRAD, T& yRotRAD, T& xRotRAD);
222  void toEulerAnglesXYZ(T& xRotRAD, T& yRotRAD, T& zRotRAD);
223  // (transfer order define in EulerAngles.h from Kent Shoemake)
225 
226  // Misc. methods
227  void identity ();
228  void transpose ();
230  void invert ();
231  SLMat4<T> inverted () const;
233  T trace () const;
234 
235  // Composing & decomposing
236  void compose (SLVec3f trans,
237  SLVec3f rotEulerRAD,
238  SLVec3f scale);
239  void decompose (SLVec3f &trans,
240  SLVec4f &rotQuat,
241  SLVec3f &scale);
242  void decompose (SLVec3f &trans,
243  SLMat3f &rotMat,
244  SLVec3f &scale);
245  void decompose (SLVec3f &trans,
246  SLVec3f &rotEulerRAD,
247  SLVec3f &scale);
248 
249  void print (const SLchar* str=nullptr) const;
250  SLstring toString () const;
251 
252  static void swap (T& a, T& b) {T t; t=a;a=b;b=t;}
253 
254  private:
255  T _m[16]; //!< The 16 elements of the matrix
256 };
257 
258 //-----------------------------------------------------------------------------
259 // Constructors
260 //-----------------------------------------------------------------------------
261 template<class T>
263 { identity();
264 }
265 //-----------------------------------------------------------------------------
266 template<class T>
268 { setMatrix(A);
269 }
270 //-----------------------------------------------------------------------------
271 template<class T>
273 { setMatrix(A);
274 }
275 //-----------------------------------------------------------------------------
276 template<class T>
277 SLMat4<T>::SLMat4(T M0, T M4, T M8, T M12,
278  T M1, T M5, T M9, T M13,
279  T M2, T M6, T M10, T M14,
280  T M3, T M7, T M11, T M15)
281 {
282  setMatrix(M0, M4, M8, M12,
283  M1, M5, M9, M13,
284  M2, M6, M10,M14,
285  M3, M7, M11,M15);
286 }
287 //-----------------------------------------------------------------------------
288 template<class T>
289 SLMat4<T>::SLMat4(const T* M)
290 {
291  setMatrix(M);
292 }
293 //-----------------------------------------------------------------------------
294 template<class T>
295 SLMat4<T>::SLMat4(const T tx, const T ty, const T tz)
296 {
297  translation(tx, ty, tz, false);
298 }
299 //-----------------------------------------------------------------------------
300 template<class T>
301 SLMat4<T>::SLMat4(const SLVec3<T>& translationVec)
302 {
303  translation(translationVec.x, translationVec.y, translationVec.z, false);
304 }
305 //-----------------------------------------------------------------------------
306 template<class T>
307 SLMat4<T>::SLMat4(const T degAng, const T ax, const T ay, const T az)
308 {
309  rotation(degAng, ax, ay, az, false);
310 }
311 //-----------------------------------------------------------------------------
312 template<class T>
313 SLMat4<T>::SLMat4(const T scale_xyz)
314 {
315  scaling(scale_xyz);
316 }
317 //-----------------------------------------------------------------------------
318 template<class T>
319 SLMat4<T>::SLMat4(const SLVec3<T>& fromUnitVec, const SLVec3<T>& toUnitVec)
320 {
321  rotation(fromUnitVec, toUnitVec);
322 }
323 //-----------------------------------------------------------------------------
324 template<class T>
325 SLMat4<T>::SLMat4(const SLVec3<T>& translation,
326  const SLMat3<T>& rotation,
327  const SLVec3<T>& scale)
328 {
329  setMatrix(translation, rotation, scale);
330 }
331 //-----------------------------------------------------------------------------
332 // Setters
333 //-----------------------------------------------------------------------------
334 template<class T>
336 {
337  for (int i=0; i<16; ++i) _m[i] = A._m[i];
338 }
339 //-----------------------------------------------------------------------------
340 template<class T>
342 {
343  _m[0]=A._m[0]; _m[4]=A._m[3]; _m[ 8]=A._m[6]; _m[12]=0;
344  _m[1]=A._m[1]; _m[5]=A._m[4]; _m[ 9]=A._m[7]; _m[13]=0;
345  _m[2]=A._m[2]; _m[6]=A._m[5]; _m[10]=A._m[8]; _m[14]=0;
346  _m[3]=0; _m[7]=0; _m[11]=0; _m[15]=1;
347 }
348 //-----------------------------------------------------------------------------
349 template<class T>
351 {
352  for (int i=0; i<16; ++i) _m[i] = A->_m[i];
353 }
354 //-----------------------------------------------------------------------------
355 template<class T>
356 void SLMat4<T>::setMatrix(const T* M)
357 {
358  for (int i=0; i<16; ++i) _m[i] = M[i];
359 }
360 //-----------------------------------------------------------------------------
361 template<class T>
362 void SLMat4<T>::setMatrix(T M0, T M4, T M8 , T M12,
363  T M1, T M5, T M9 , T M13,
364  T M2, T M6, T M10, T M14,
365  T M3, T M7, T M11, T M15)
366 {
367  _m[0]=M0; _m[4]=M4; _m[ 8]=M8; _m[12]=M12;
368  _m[1]=M1; _m[5]=M5; _m[ 9]=M9; _m[13]=M13;
369  _m[2]=M2; _m[6]=M6; _m[10]=M10; _m[14]=M14;
370  _m[3]=M3; _m[7]=M7; _m[11]=M11; _m[15]=M15;
371 }
372 //-----------------------------------------------------------------------------
373 template<class T>
374 void SLMat4<T>::setMatrix(const SLVec3<T>& translation,
375  const SLMat3<T>& rotation,
376  const SLVec3<T>& scale)
377 {
378  setMatrix(scale.x * rotation[0], scale.y * rotation[3], scale.z * rotation[6], translation.x,
379  scale.x * rotation[1], scale.y * rotation[4], scale.z * rotation[7], translation.y,
380  scale.x * rotation[2], scale.y * rotation[5], scale.z * rotation[8], translation.z,
381  0 , 0 , 0 , 1);
382 }
383 //-----------------------------------------------------------------------------
384 template<class T>
385 void SLMat4<T>::setRotation (const SLMat3<T>& rotation) //!< Set 3x3 submatrix describing the rotational part
386 {
387  _m[0]=rotation[0]; _m[4]=rotation[3]; _m[8]=rotation[6];
388  _m[1]=rotation[1]; _m[5]=rotation[4]; _m[9]=rotation[7];
389  _m[2]=rotation[2]; _m[6]=rotation[5]; _m[10]=rotation[8];
390 }
391 //-----------------------------------------------------------------------------
392 template<class T>
393 void SLMat4<T>::setTranslation (const SLVec3<T>& translation) //!< Set vector as submatrix describing the translational part
394 {
395  _m[12]=translation.x;
396  _m[13]=translation.y;
397  _m[14]=translation.z;
398 }
399 //-----------------------------------------------------------------------------
400 // Operators
401 //-----------------------------------------------------------------------------
402 /*!
403 Matrix assignment with instance
404 */
405 template<class T>
407 {
408  _m[0]=A._m[0]; _m[4]=A._m[4]; _m[ 8]=A._m[ 8]; _m[12]=A._m[12];
409  _m[1]=A._m[1]; _m[5]=A._m[5]; _m[ 9]=A._m[ 9]; _m[13]=A._m[13];
410  _m[2]=A._m[2]; _m[6]=A._m[6]; _m[10]=A._m[10]; _m[14]=A._m[14];
411  _m[3]=A._m[3]; _m[7]=A._m[7]; _m[11]=A._m[11]; _m[15]=A._m[15];
412  return *this;
413 }
414 //-----------------------------------------------------------------------------
415 /*!
416 Matrix - matrix multiplication
417 */
418 template<class T>
420 {
421  SLMat4<T> newM((const T*)this);
422  newM.multiply(A);
423  return newM;
424 }
425 //-----------------------------------------------------------------------------
426 /*
427 !Matrix - matrix multiplication
428 */
429 template<class T>
431 {
432  multiply(A);
433  return *this;
434 }
435 //-----------------------------------------------------------------------------
436 /*
437 !Matrix - matrix multiplication
438 */
439 template<class T>
441 {
442  SLMat4<T> newM((const T*)this);
443  newM.add(A);
444  return newM;
445 }
446 
447 //-----------------------------------------------------------------------------
448 /*!
449 Matrix - 3D vector multiplication with perspective division
450 */
451 template<class T>
453 {
454  T W = 1 / (_m[3]*v.x + _m[7]*v.y + _m[11]*v.z + _m[15]);
455  return SLVec3<T>((_m[0]*v.x + _m[4]*v.y + _m[ 8]*v.z + _m[12]) * W,
456  (_m[1]*v.x + _m[5]*v.y + _m[ 9]*v.z + _m[13]) * W,
457  (_m[2]*v.x + _m[6]*v.y + _m[10]*v.z + _m[14]) * W);
458 }
459 //-----------------------------------------------------------------------------
460 /*!
461 Matrix - 4D vector multiplication
462 */
463 template<class T>
465 {
466  return SLVec4<T>(_m[0]*v.x + _m[4]*v.y + _m[ 8]*v.z + _m[12]*v.w,
467  _m[1]*v.x + _m[5]*v.y + _m[ 9]*v.z + _m[13]*v.w,
468  _m[2]*v.x + _m[6]*v.y + _m[10]*v.z + _m[14]*v.w,
469  _m[3]*v.x + _m[7]*v.y + _m[11]*v.z + _m[15]*v.w);
470 }
471 //-----------------------------------------------------------------------------
472 /*!
473 Scalar multiplication.
474 */
475 template<class T>
477 {
478  return SLMat4<T>(_m[ 0]*a, _m[ 1]*a, _m[ 2]*a, _m[ 3]*a,
479  _m[ 4]*a, _m[ 5]*a, _m[ 6]*a, _m[ 7]*a,
480  _m[ 8]*a, _m[ 9]*a, _m[10]*a, _m[11]*a,
481  _m[12]*a, _m[13]*a, _m[14]*a, _m[15]*a);
482 }
483 //-----------------------------------------------------------------------------
484 /*!
485 Scalar multiplication.
486 */
487 template<class T>
489 {
490  for (auto & i : _m) i *= a;
491  return *this;
492 }
493 //-----------------------------------------------------------------------------
494 /*!
495 Scalar division.
496 */
497 template<class T>
499 {
500  T invA = 1 / a;
501  SLMat4<T> newM(_m[ 0]*invA, _m[ 1]*invA, _m[ 2]*invA, _m[ 3]*invA,
502  _m[ 4]*invA, _m[ 5]*invA, _m[ 6]*invA, _m[ 7]*invA,
503  _m[ 8]*invA, _m[ 9]*invA, _m[10]*invA, _m[11]*invA,
504  _m[12]*invA, _m[13]*invA, _m[14]*invA, _m[15]*invA);
505  return newM;
506 }
507 //-----------------------------------------------------------------------------
508 /*!
509 Scalar division.
510 */
511 template<class T>
513 {
514  T invA = 1 / a;
515  for (auto & i : _m) i *= invA;
516  return *this;
517 }
518 //-----------------------------------------------------------------------------
519 //! Returns true if one element of the matrix differs more than epsilon
520 template<class T>
522 {
523  for (SLuint i = 0; i < 16; ++i)
524  {
525  if (std::abs(_m[i] - A._m[i]) > epsilon)
526  return false;
527  }
528  return true;
529 }
530 //-----------------------------------------------------------------------------
531 /*!
532 Multiplies the matrix with a another matrix. Corresponds to the OpenGL function
533 glMultMatrix*.
534 */
535 template<class T>
537 {
538  setMatrix(_m[0]*A._m[ 0] + _m[4]*A._m[ 1] + _m[8] *A._m[ 2] + _m[12]*A._m[ 3], //row 1
539  _m[0]*A._m[ 4] + _m[4]*A._m[ 5] + _m[8] *A._m[ 6] + _m[12]*A._m[ 7],
540  _m[0]*A._m[ 8] + _m[4]*A._m[ 9] + _m[8] *A._m[10] + _m[12]*A._m[11],
541  _m[0]*A._m[12] + _m[4]*A._m[13] + _m[8] *A._m[14] + _m[12]*A._m[15],
542  _m[1]*A._m[ 0] + _m[5]*A._m[ 1] + _m[9] *A._m[ 2] + _m[13]*A._m[ 3], //row 2
543  _m[1]*A._m[ 4] + _m[5]*A._m[ 5] + _m[9] *A._m[ 6] + _m[13]*A._m[ 7],
544  _m[1]*A._m[ 8] + _m[5]*A._m[ 9] + _m[9] *A._m[10] + _m[13]*A._m[11],
545  _m[1]*A._m[12] + _m[5]*A._m[13] + _m[9] *A._m[14] + _m[13]*A._m[15],
546  _m[2]*A._m[ 0] + _m[6]*A._m[ 1] + _m[10]*A._m[ 2] + _m[14]*A._m[ 3], //row 3
547  _m[2]*A._m[ 4] + _m[6]*A._m[ 5] + _m[10]*A._m[ 6] + _m[14]*A._m[ 7],
548  _m[2]*A._m[ 8] + _m[6]*A._m[ 9] + _m[10]*A._m[10] + _m[14]*A._m[11],
549  _m[2]*A._m[12] + _m[6]*A._m[13] + _m[10]*A._m[14] + _m[14]*A._m[15],
550  _m[3]*A._m[ 0] + _m[7]*A._m[ 1] + _m[11]*A._m[ 2] + _m[15]*A._m[ 3], //row 4
551  _m[3]*A._m[ 4] + _m[7]*A._m[ 5] + _m[11]*A._m[ 6] + _m[15]*A._m[ 7],
552  _m[3]*A._m[ 8] + _m[7]*A._m[ 9] + _m[11]*A._m[10] + _m[15]*A._m[11],
553  _m[3]*A._m[12] + _m[7]*A._m[13] + _m[11]*A._m[14] + _m[15]*A._m[15]);
554 
555  // | 0 4 8 12 | | 0 4 8 12 |
556  // | 1 5 9 13 | | 1 5 9 13 |
557  // M = | 2 6 10 14 | x | 2 6 10 14 |
558  // | 3 7 11 15 | | 3 7 11 15 |
559 }
560 
561 //-----------------------------------------------------------------------------
562 /*!
563 Adds the matrix to an other matrix A.
564 */
565 template<class T>
566 void SLMat4<T>::add(const SLMat4& A)
567 {
568  for (SLint i = 0; i < 16; ++i)
569  _m[i] = _m[i] + A._m[i];
570 }
571 //-----------------------------------------------------------------------------
572 /*!
573 Matrix - 3D vector multiplication with perspective division
574 */
575 template<class T>
577 {
578  T W = 1 / (_m[3]*v.x + _m[7]*v.y + _m[11]*v.z + _m[15]);
579  return SLVec3<T>((_m[0]*v.x + _m[4]*v.y + _m[ 8]*v.z + _m[12]) * W,
580  (_m[1]*v.x + _m[5]*v.y + _m[ 9]*v.z + _m[13]) * W,
581  (_m[2]*v.x + _m[6]*v.y + _m[10]*v.z + _m[14]) * W);
582 }
583 //-----------------------------------------------------------------------------
584 /*!
585 Matrix - 4D vector multiplication
586 */
587 template<class T>
589 {
590  return SLVec4<T>(_m[0]*v.x + _m[4]*v.y + _m[ 8]*v.z + _m[12]*v.w,
591  _m[1]*v.x + _m[5]*v.y + _m[ 9]*v.z + _m[13]*v.w,
592  _m[2]*v.x + _m[6]*v.y + _m[10]*v.z + _m[14]*v.w,
593  _m[3]*v.x + _m[7]*v.y + _m[11]*v.z + _m[15]*v.w);
594 }
595 //-----------------------------------------------------------------------------
596 /*!
597 Multiplies the matrix with a translation matrix.
598 Corresponds to the OpenGL function glTranslate*.
599 */
600 template <class T>
601 void SLMat4<T>::translate(const T tx, const T ty, const T tz)
602 {
603  SLMat4<T> trans(tx, ty, tz);
604  multiply(trans);
605 }
606 //-----------------------------------------------------------------------------
607 /*!
608 Multiplies the matrix with a translation matrix.
609 Corresponds to the OpenGL function glTranslate*.
610 */
611 template<class T>
613 {
614  SLMat4<T> trans(t.x, t.y, 0);
615  multiply(trans);
616 }
617 //-----------------------------------------------------------------------------
618 /*!
619 Multiplies the matrix with a translation matrix.
620 Corresponds to the OpenGL function glTranslate*.
621 */
622 template<class T>
624 {
625  SLMat4<T> trans(t.x, t.y, t.z);
626  multiply(trans);
627 }
628 //-----------------------------------------------------------------------------
629 /*!
630 Multiplies the matrix with a rotation matrix.
631 Corresponds to the OpenGL function glRotate*.
632 */
633 template<class T>
634 void SLMat4<T>::rotate(const T degAng, const SLVec3<T>& axis)
635 {
636  SLMat4<T> R(degAng, axis.x, axis.y, axis.z);
637  multiply(R);
638 }
639 //-----------------------------------------------------------------------------
640 /*!
641 Multiplies the matrix with a rotation matrix created with a rotation between
642 two vectors.
643 */
644 template<class T>
645 void SLMat4<T>::rotate(const SLVec3<T>& fromUnitVec, const SLVec3<T>& toUnitVec)
646 {
647  SLMat4<T> R(fromUnitVec, toUnitVec);
648  multiply(R);
649 }
650 //-----------------------------------------------------------------------------
651 /*!
652 Multiplies the matrix with a rotation matrix.
653 Corresponds to the OpenGL function glRotate*.
654 */
655 template<class T>
656 void SLMat4<T>::rotate(const T degAng, const T axisx, const T axisy, const T axisz)
657 {
658  SLMat4<T> R(degAng, axisx, axisy, axisz);
659  multiply(R);
660 }
661 //-----------------------------------------------------------------------------
662 /*!
663 Multiplies the matrix with a scaling matrix.
664 Corresponds to the OpenGL function glScale*.
665 */
666 template<class T>
667 void SLMat4<T>::scale(const T s)
668 { SLMat4<T> S(s, 0, 0, 0,
669  0, s, 0, 0,
670  0, 0, s, 0,
671  0, 0, 0, 1);
672  multiply(S);
673 }
674 //-----------------------------------------------------------------------------
675 /*!
676 Multiplies the matrix with a scaling matrix.
677 Corresponds to the OpenGL function glScale*.
678 */
679 template<class T>
680 void SLMat4<T>::scale(const T sx, const T sy, const T sz)
681 {
682  SLMat4<T> S(sx, 0, 0, 0,
683  0,sy, 0, 0,
684  0, 0,sz, 0,
685  0, 0, 0, 1);
686  multiply(S);
687 }
688 //-----------------------------------------------------------------------------
689 /*!
690 Multiplies the matrix with a scaling matrix.
691 Corresponds to the OpenGL function glScale*.
692 */
693 template<class T>
695 {
696  SLMat4<T> S(s.x, 0, 0, 0,
697  0,s.y, 0, 0,
698  0, 0,s.z, 0,
699  0, 0, 0, 1);
700  multiply(S);
701 }
702 //-----------------------------------------------------------------------------
703 //! Defines the view matrix with an eye position, a look at point and an up vector.
704 /*!
705 This method is equivalent to the OpenGL function gluLookAt.
706 */
707 template<class T>
708 void SLMat4<T>::lookAt( const T EyeX, const T EyeY, const T EyeZ,
709  const T AtX, const T AtY, const T AtZ,
710  const T UpX, const T UpY, const T UpZ)
711 {
712  lookAt(SLVec3<T>(EyeX,EyeY,EyeZ),
713  SLVec3<T>( AtX, AtY, AtZ),
714  SLVec3<T>( UpX, UpY, UpZ));
715 }
716 //-----------------------------------------------------------------------------
717 //! Defines the view matrix with an eye position, a look at point and an up vector.
718 /*!
719 This method is equivalent to the OpenGL function gluLookAt.
720 @param Eye Vector to the position of the eye (view point).
721 @param At Vector to the target point.
722 @param Up Vector that points from the viewpoint upwards. If Up is a zero vector
723 a default up vector is calculated with a default look-right vector (VZ) that
724 lies in the x-z plane.
725 */
726 template<class T>
727 void SLMat4<T>::lookAt(const SLVec3<T>& Eye,
728  const SLVec3<T>& At,
729  const SLVec3<T>& Up)
730 {
731  SLVec3<T> VX, VY, VZ, VT;
732  SLMat3<T> xz(0.0, 0.0, 1.0, // matrix that transforms YZ into a
733  0.0, 0.0, 0.0, // vector that is perpendicular to YZ and
734  -1.0, 0.0, 0.0); // lies in the x-z plane
735 
736  VZ = Eye-At;
737  VZ.normalize();
738 
739  if (Up==SLVec3<T>::ZERO || Up==VZ)
740  { VX.set(xz*VZ);
741  VX.normalize();
742  } else
743  { VX.cross(Up, VZ);
744  VX.normalize();
745  }
746  VY.cross(VZ, VX); VY.normalize();
747  VT = -Eye;
748 
749  setMatrix(VX.x, VX.y, VX.z, VX*VT,
750  VY.x, VY.y, VY.z, VY*VT,
751  VZ.x, VZ.y, VZ.z, VZ*VT,
752  0.0, 0.0, 0.0, 1.0);
753 }
754 //-----------------------------------------------------------------------------
755 /*!
756 This method retrieves the eye position the look at, up & right vector out of
757 the view matrix. Attention: The look-at is normalized vector, not a point.
758 */
759 template<class T>
761  SLVec3<T>* at,
762  SLVec3<T>* up,
763  SLVec3<T>* ri) const
764 {
765  SLMat4<T> invRot(_m); // get the current view matrix
766  invRot.translation(0,0,0); // remove the translation
767  invRot.transpose(); // transpose it to get inverse rot.
768  eye->set(invRot.multVec(-translation())); // setMatrix eye
769  ri->set( _m[0], _m[4], _m[8]); // normalized look right vector
770  up->set( _m[1], _m[5], _m[9]); // normalized look up vector
771  at->set(-_m[2],-_m[6],-_m[10]); // normalized look at vector
772 }
773 //-----------------------------------------------------------------------------
774 /*!
775 Defines the a model matrix for positioning a light at pos and shining at At
776 */
777 template<class T>
778 void SLMat4<T>::lightAt(const T PosX, const T PosY, const T PosZ,
779  const T AtX, const T AtY, const T AtZ,
780  const T UpX, const T UpY, const T UpZ)
781 {
782  lightAt(SLVec3<T>(PosX,PosY,PosZ),
783  SLVec3<T>( AtX, AtY, AtZ),
784  SLVec3<T>( UpX, UpY, UpZ));
785 }
786 //-----------------------------------------------------------------------------
787 //! Defines the a model matrix for positioning a light source.
788 /*!
789 Utility method for defining the transformation matrix for a spot light. There
790 is no equivalent function for this purpose in OpenGL.
791 /param pos Vector to the position of the light source.
792 /param At Vector to a target point where a spot light shines to.
793 */
794 template<class T>
796  const SLVec3<T>& At,
797  const SLVec3<T>& Up)
798 {
799  SLVec3<T> VX, VY, VZ;
800  SLMat3<T> xz(0.0, 0.0, 1.0, // matrix that transforms VZ into a
801  0.0, 0.0, 0.0, // vector that is perpendicular to YZ and
802  -1.0, 0.0, 0.0); // lies in the x-z plane
803 
804  VZ = pos-At; VZ.normalize();
805 
806  if (Up==SLVec3<T>::ZERO)
807  { VX = xz*VZ; VX.normalize();
808  VY = VZ^VX; VY.normalize();
809  } else
810  { VX = Up^VZ; VX.normalize();
811  VY = VZ^VX; VY.normalize();
812  }
813 
814  setMatrix(VX.x, VY.x, VZ.x, pos.x,
815  VX.y, VY.y, VZ.y, pos.y,
816  VX.z, VY.z, VZ.z, pos.z,
817  0.0, 0.0, 0.0, 1.0);
818 }
819 //-----------------------------------------------------------------------------
820 //! Same as lightAt
821 template<class T>
822 void SLMat4<T>::posAtUp(const T PosX, const T PosY, const T PosZ,
823  const T dirAtX, const T dirAtY, const T dirAtZ,
824  const T dirUpX, const T dirUpY, const T dirUpZ)
825 {
826  lightAt(SLVec3<T>( PosX, PosY, PosZ),
827  SLVec3<T>(dirAtX, dirAtY, dirAtZ),
828  SLVec3<T>(dirUpX, dirUpY, dirUpZ));
829 }
830 
831 //-----------------------------------------------------------------------------
832 //! Same as lightAt
833 template<class T>
835  const SLVec3<T>& dirAt,
836  const SLVec3<T>& dirUp)
837 {
838  lightAt(pos, dirAt, dirUp);
839 }
840 
841 //---------------------------------------------------------------------------
842 //! Defines a view frustum projection matrix equivalent to OpenGL's glFrustum
843 /*!
844 The view frustum is the truncated view pyramid of a central projection that
845 is defined with the folowing parameters:
846 @param l Distance from the center of projection (COP) to the left border on
847 the near clipping plane.
848 @param r Distance from the COP to the right border on the near clipping plane.
849 @param b Distance from the COP to the bottom border on the near clipping plane.
850 @param t Distance from the COP to the top border on the near clipping plane.
851 @param n Distance from the eye to near clipping plane of the view frustum.
852 @param f Distance from the eye to far clipping plane of the view frustum.
853 */
854 template<class T>
855 void SLMat4<T>::frustum(const T l, const T r, const T b, const T t,
856  const T n, const T f)
857 {
858  _m[0]=2*n/(r-l); _m[4]=0; _m[8] = (r+l)/(r-l); _m[12]=0;
859  _m[1]=0; _m[5]=2*n/(t-b); _m[9] = (t+b)/(t-b); _m[13]=0;
860  _m[2]=0; _m[6]=0; _m[10]=-(f+n)/(f-n); _m[14]=-2*f*n/(f-n);
861  _m[3]=0; _m[7]=0; _m[11]=-1; _m[15]=0;
862 }
863 //---------------------------------------------------------------------------
864 //! Defines a view frustum projection matrix for a perspective projection
865 /*!
866 This method is equivalent to the OpenGL function gluPerspective except that
867 instead of the window aspect the window width and height have to be passed.
868 @param fov Vertical field of view angle (zoom angle)
869 @param aspect aspect ratio of of the viewport = width / height
870 @param n Distance from the eye to near clipping plane of the view frustum.
871 @param f Distance from the eye to far clipping plane of the view frustum.
872 */
873 template<class T>
874 void SLMat4<T>::perspective(const T fov, const T aspect,
875  const T n, const T f)
876 {
877  T t = (T)tan(fov * DEG2RAD * 0.5)*n;
878  T b = -t;
879  T r = t*aspect;
880  T l = -r;
881  frustum(l,r,b,t,n,f);
882 }
883 //---------------------------------------------------------------------------
884 //! Defines a projection matrix for a calibrated camera, the principle point has to be centered (from intrinsics matrix)
885 /*! This should give an exact result.
886 http://kgeorge.github.io/2014/03/08/calculating-opengl-perspective-matrix-from-opencv-intrinsic-matrix
887 (see also https://stackoverflow.com/questions/22064084/how-to-create-perspective-projection-matrix-given-focal-points-and-camera-princ
888 but the other solutions did not work as well)
889 */
890 template<class T>
891 void SLMat4<T>::perspectiveCenteredPP(const T w, const T h, const T fx, const T fy,
892  const T cx, const T cy, const T n, const T f)
893 {
894  _m[0]=fx/cx; _m[4]=0; _m[8] = 0; _m[12]=0;
895  _m[1]=0; _m[5]=fy/cy; _m[9] = 0; _m[13]=0;
896  _m[2]=0; _m[6]=0; _m[10]=-(f+n)/(f-n); _m[14]=(-2*f*n)/(f-n);
897  _m[3]=0; _m[7]=0; _m[11]=-1; _m[15]=0;
898 }
899 //---------------------------------------------------------------------------
900 //! Defines a ortographic projection matrix equivalent to OpenGL's glOrtho
901 /*!
902 @param l Distance from the center of projection (COP) to the left border on
903 the near clipping plane.
904 @param r Distance from the COP to the right border on the near clipping plane.
905 @param b Distance from the COP to the bottom border on the near clipping plane.
906 @param t Distance from the COP to the top border on the near clipping plane.
907 @param n Distance from the eye to near clipping plane of the view frustum.
908 @param f Distance from the eye to far clipping plane of the view frustum.
909 */
910 template<class T>
911 void SLMat4<T>::ortho(const T l, const T r, const T b, const T t,
912  const T n, const T f)
913 {
914  _m[0]=2/(r-l); _m[4]=0; _m[8]=0; _m[12]=-(r+l)/(r-l);
915  _m[1]=0; _m[5]=2/(t-b); _m[9]=0; _m[13]=-(t+b)/(t-b);
916  _m[2]=0; _m[6]=0; _m[10]=-2/(f-n); _m[14]=-(f+n)/(f-n);
917  _m[3]=0; _m[7]=0; _m[11]=0; _m[15]=1;
918 }
919 //---------------------------------------------------------------------------
920 //! Defines a viewport matrix as it will be produced by glViewport
921 /*!
922 @param x left window coord. in px.
923 @param y top window coord. in px.
924 @param ww window width in px.
925 @param wh window height in px.
926 @param n near depth range (default 0)
927 @param f far depth range (default 1)
928 */
929 template<class T>
930 void SLMat4<T>::viewport(const T x, const T y, const T ww, const T wh,
931  const T n, const T f)
932 {
933  T ww2 = ww*0.5f;
934  T wh2 = wh*0.5f;
935 
936  // negate the first wh2 because windows has topdown window coords
937  _m[0]=ww2; _m[4]=0; _m[8] =0; _m[12]=x+ww2;
938  _m[1]=0; _m[5]=-wh2; _m[9] =0; _m[13]=y+wh2;
939  _m[2]=0; _m[6]=0; _m[10]=(f-n)*0.5f; _m[14]=(f+n)*0.5f;
940  _m[3]=0; _m[7]=0; _m[11]=0; _m[15]=1;
941 }
942 //-----------------------------------------------------------------------------
943 /*!
944 Sets the translation components. By default the linear 3x3 submatrix containing
945 rotations and scaling is reset to identity.
946 */
947 template<class T>
948 void SLMat4<T>::translation(const SLVec3<T>& t, const SLbool keepLinear)
949 {
950  translation(t.x, t.y, t.z, keepLinear);
951 }
952 //-----------------------------------------------------------------------------
953 /*!
954 Sets the translation components. By default the linear 3x3 submatrix containing
955 rotations and scaling is reset to identity.
956 */
957 template<class T>
958 void SLMat4<T>::translation(const T tx, const T ty, const T tz,
959  const SLbool keepLinear)
960 {
961  _m[12]=tx;
962  _m[13]=ty;
963  _m[14]=tz;
964 
965  if (!keepLinear)
966  { _m[0]=1; _m[4]=0; _m[8]=0;
967  _m[1]=0; _m[5]=1; _m[9]=0;
968  _m[2]=0; _m[6]=0; _m[10]=1;
969  _m[3]=0; _m[7]=0; _m[11]=0; _m[15]=1;
970  }
971 }
972 //-----------------------------------------------------------------------------
973 /*!
974 Sets the linear 3x3 submatrix as a rotation matrix with a rotation of degAng
975 degrees around an axis. By default the translation components are set to 0.
976 */
977 template<class T>
978 void SLMat4<T>::rotation(const T degAng, const SLVec3<T>& axis,
979  const SLbool keepTrans)
980 {
981  rotation(degAng, axis.x, axis.y, axis.z, keepTrans);
982 }
983 //-----------------------------------------------------------------------------
984 /*!
985 Sets the linear 3x3 submatrix as a rotation matrix with a rotation of degAng
986 degrees around an axis. By default the translation components are set to 0.
987 */
988 template<class T>
989 void SLMat4<T>::rotation(const T degAng,
990  const T axisx, const T axisy, const T axisz,
991  const SLbool keepTrans)
992 {
993  T RadAng = (T)degAng * DEG2RAD;
994  T ca=(T)cos(RadAng), sa=(T)sin(RadAng);
995  if (axisx==1 && axisy==0 && axisz==0) // about x-axis
996  { _m[0]=1; _m[4]=0; _m[8]=0;
997  _m[1]=0; _m[5]=ca; _m[9]=-sa;
998  _m[2]=0; _m[6]=sa; _m[10]=ca;
999  } else
1000  if (axisx==0 && axisy==1 && axisz==0) // about y-axis
1001  { _m[0]=ca; _m[4]=0; _m[8]=sa;
1002  _m[1]=0; _m[5]=1; _m[9]=0;
1003  _m[2]=-sa; _m[6]=0; _m[10]=ca;
1004  } else
1005  if (axisx==0 && axisy==0 && axisz==1) // about z-axis
1006  { _m[0]=ca; _m[4]=-sa; _m[8]=0;
1007  _m[1]=sa; _m[5]=ca; _m[9]=0;
1008  _m[2]=0; _m[6]=0; _m[10]=1;
1009  } else // arbitrary axis
1010  { T l = axisx*axisx + axisy*axisy + axisz*axisz; // length squared
1011  T x, y, z;
1012  x=axisx, y=axisy, z=axisz;
1013  if ((l > T(1.0001) || l < T(0.9999)) && l!=0)
1014  { l=T(1.0)/sqrt(l);
1015  x*=l; y*=l; z*=l;
1016  }
1017  T xy=x*y, yz=y*z, xz=x*z, xx=x*x, yy=y*y, zz=z*z;
1018  _m[0]=xx + ca*(1-xx); _m[4]=xy - xy*ca - z*sa; _m[8] =xz - xz*ca + y*sa;
1019  _m[1]=xy - xy*ca + z*sa; _m[5]=yy + ca*(1-yy); _m[9] =yz - yz*ca - x*sa;
1020  _m[2]=xz - xz*ca - y*sa; _m[6]=yz - yz*ca + x*sa; _m[10]=zz + ca*(1-zz);
1021  }
1022  _m[3]=_m[7]=_m[11]=0; _m[15]=1;
1023 
1024  if (!keepTrans)
1025  _m[12] = _m[13] = _m[14] = 0;
1026 }
1027 //-----------------------------------------------------------------------------
1028 /*!
1029 Defines a rotation matrix that rotates the vector from to the vector to.
1030 Code and explanation comes from the paper "Efficiently build
1031 a matrix to ratate one vector to another" from Thomas Mueller and John Hughes in
1032 the Journal of Graphic Tools, volume 4.
1033 */
1034 template<class T>
1035 void SLMat4<T>::rotation(const SLVec3<T>&from, const SLVec3<T> &to)
1036 {
1037  // Creates a rotation matrix that will rotate the Vector 'from' into
1038  // the Vector 'to'. The resulting matrix is stored in 'this' Matrix.
1039  // For this method to work correctly, vector 'from' and vector 'to'
1040  // must both be unit length vectors.
1041 
1042  T cosAngle = from.dot(to);
1043 
1044  if (fabs(cosAngle-1.0) <= FLT_EPSILON) // cosAngle = 1.0
1045  {
1046  // Special case where 'from' is equal to 'to'. In other words,
1047  // the angle between Vector 'from' and Vector 'to' is zero
1048  // degrees. In this case the identity matrix is returned in
1049  // Matrix 'result'.
1050 
1051  identity();
1052  }
1053  else if (fabs(cosAngle+1.0) <= FLT_EPSILON) // cosAngle = -1.0
1054  {
1055  // Special case where 'from' is directly opposite to 'to'. In
1056  // other words, the angle between Vector 'from' and Vector 'to'
1057  // is 180 degrees. In this case, the following matrix is used:
1058  //
1059  // Let:
1060  // F = from
1061  // S = vector perpendicular to F
1062  // U = S X F
1063  //
1064  // We want to rotate from (F, U, S) to (-F, U, -S)
1065  //
1066  // | -FxFx+UxUx-SxSx -FxFy+UxUy-SxSy -FxFz+UxUz-SxSz 0 |
1067  // | -FxFy+UxUy-SxSy -FyFy+UyUy-SySy -FyFz+UyUz-SySz 0 |
1068  // | -FxFz+UxUz-SxSz -FyFz+UyUz-SySz -FzFz+UzUz-SzSz 0 |
1069  // | 0 0 0 1 |
1070 
1071  SLVec3<T> side(0.f, from.z, -from.y);
1072 
1073  if (fabs(side.dot(side)) <= FLT_EPSILON)
1074  { side.x = -from.z;
1075  side.y = 0.f;
1076  side.z = from.x;
1077  }
1078 
1079  side.normalize();
1080 
1081  SLVec3<T> up;
1082  up.cross(side, from);
1083  up.normalize();
1084 
1085  _m[ 0] = -(from.x * from.x) + (up.x * up.x) - (side.x * side.x);
1086  _m[ 4] = -(from.x * from.y) + (up.x * up.y) - (side.x * side.y);
1087  _m[ 8] = -(from.x * from.z) + (up.x * up.z) - (side.x * side.z);
1088  _m[12] = 0.f;
1089  _m[ 1] = -(from.x * from.y) + (up.x * up.y) - (side.x * side.y);
1090  _m[ 5] = -(from.y * from.y) + (up.y * up.y) - (side.y * side.y);
1091  _m[ 9] = -(from.y * from.z) + (up.y * up.z) - (side.y * side.z);
1092  _m[13] = 0.f;
1093  _m[ 2] = -(from.x * from.z) + (up.x * up.z) - (side.x * side.z);
1094  _m[ 6] = -(from.y * from.z) + (up.y * up.z) - (side.y * side.z);
1095  _m[10] = -(from.z * from.z) + (up.z * up.z) - (side.z * side.z);
1096  _m[14] = 0.f;
1097  _m[ 3] = 0.f;
1098  _m[ 7] = 0.f;
1099  _m[11] = 0.f;
1100  _m[15] = 1.f;
1101  }
1102  else
1103  {
1104  // This is the most common case. Creates the rotation matrix:
1105  //
1106  // | E + HVx^2 HVxVy - Vz HVxVz + Vy 0 |
1107  // R(from, to) = | HVxVy + Vz E + HVy^2 HVyVz - Vx 0 |
1108  // | HVxVz - Vy HVyVz + Vx E + HVz^2 0 |
1109  // | 0 0 0 1 |
1110  //
1111  // where,
1112  // V = from X to
1113  // E = from.dot(to)
1114  // H = (1 - E) / V.dot(V)
1115 
1116  SLVec3<T> v;
1117  v.cross(from, to);
1118  v.normalize();
1119 
1120  T h = (1.f - cosAngle) / v.dot(v);
1121 
1122  _m[ 0] = cosAngle + h * v.x * v.x;
1123  _m[ 4] = h * v.x * v.y - v.z;
1124  _m[ 8] = h * v.x * v.z + v.y;
1125  _m[12] = 0.f;
1126  _m[ 1] = h * v.x * v.y + v.z;
1127  _m[ 5] = cosAngle + h * v.y * v.y;
1128  _m[ 9] = h * v.y * v.z - v.x;
1129  _m[13] = 0.f;
1130  _m[ 2] = h * v.x * v.z - v.y;
1131  _m[ 6] = h * v.y * v.z + v.x;
1132  _m[10] = cosAngle + h * v.z * v.z;
1133  _m[14] = 0.f;
1134  _m[ 3] = 0.f;
1135  _m[ 7] = 0.f;
1136  _m[11] = 0.f;
1137  _m[15] = 1.f;
1138  }
1139 }
1140 //-----------------------------------------------------------------------------
1141 /*!
1142 Sets the linear 3x3 submatrix as a scaling matrix with the scaling vector s.
1143 By default the translation components are set to 0.
1144 */
1145 template<class T>
1146 void SLMat4<T>::scaling(const T sxyz,
1147  const SLbool keepTrans)
1148 {
1149  scaling(sxyz, sxyz, sxyz);
1150 }
1151 //-----------------------------------------------------------------------------
1152 /*!
1153 Sets the linear 3x3 submatrix as a scaling matrix with the scaling vector s.
1154 By default the translation components are set to 0.
1155 */
1156 template<class T>
1157 void SLMat4<T>::scaling(const SLVec3<T>& scale,
1158  const SLbool keepTrans)
1159 {
1160  scaling(scale.x, scale.y, scale.z);
1161 }
1162 //-----------------------------------------------------------------------------
1163 /*!
1164 Sets the linear 3x3 submatrix as a scaling matrix with the scaling f_actors
1165 sx, sy and sz. By default the translation components are set to 0.
1166 */
1167 template<class T>
1168 void SLMat4<T>::scaling(const T sx, const T sy, const T sz,
1169  const SLbool keepTrans)
1170 {
1171  _m[0]=sx; _m[4]=0; _m[8]=0;
1172  _m[1]=0; _m[5]=sy; _m[9]=0;
1173  _m[2]=0; _m[6]=0; _m[10]=sz;
1174  _m[3]=0; _m[7]=0; _m[11]=0; _m[15]=1;
1175 
1176  if (!keepTrans)
1177  _m[12] = _m[13] = _m[14] = 0;
1178 }
1179 //-----------------------------------------------------------------------------
1180 /*!
1181 Sets the linear 3x3 submatrix as a rotation matrix from the 3 euler angles
1182 in radians around the z-axis, x-axis & z-axis.
1183 By default the translation components are set to 0.
1184 See: http://en.wikipedia.org/wiki/Euler_angles
1185 */
1186 template<class T>
1187 void SLMat4<T>::fromEulerAnglesZXZ(const double angle1RAD,
1188  const double angle2RAD,
1189  const double angle3RAD,
1190  const SLbool keepTrans)
1191 {
1192  double s1 = sin(angle1RAD), c1 = cos(angle1RAD);
1193  double s2 = sin(angle2RAD), c2 = cos(angle2RAD);
1194  double s3 = sin(angle3RAD), c3 = cos(angle3RAD);
1195 
1196  _m[0]=(T)( c1*c3 - s1*c2*s3); _m[4]=(T)( s1*c3 + c1*c2*s3); _m[8] =(T)( s2*s3);
1197  _m[1]=(T)(-c1*s3 - s1*c2*c3); _m[5]=(T)( c1*c2*c3 - s1*s3); _m[9] =(T)( s2*c3);
1198  _m[2]=(T)( s1*s2); _m[6]=(T)(-c1*s2); _m[10]=(T)( c2);
1199 
1200  _m[3]=_m[7]=_m[11]=0; _m[15]=1;
1201 
1202  if (!keepTrans)
1203  { _m[12] = _m[13] = _m[14] = 0;
1204  }
1205 }
1206 //-----------------------------------------------------------------------------
1207 /*!
1208 Sets the linear 3x3 submatrix as a rotation matrix from the 3 euler angles
1209 in radians around the z-axis, y-axis & x-axis.
1210 By default the translation components are set to 0.
1211 See: http://en.wikipedia.org/wiki/Euler_angles
1212 */
1213 template<class T>
1214 void SLMat4<T>::fromEulerAnglesXYZ(const double angle1RAD,
1215  const double angle2RAD,
1216  const double angle3RAD,
1217  const SLbool keepTrans)
1218 {
1219  double s1 = sin(angle1RAD), c1 = cos(angle1RAD);
1220  double s2 = sin(angle2RAD), c2 = cos(angle2RAD);
1221  double s3 = sin(angle3RAD), c3 = cos(angle3RAD);
1222 
1223  _m[0]=(T) (c2*c3); _m[4]=(T)-(c2*s3); _m[8] =(T) s2;
1224  _m[1]=(T) (s1*s2*c3) + (c1*s3); _m[5]=(T)-(s1*s2*s3) + (c1*c3); _m[9] =(T)-(s1*c2);
1225  _m[2]=(T)-(c1*s2*c3) + (s1*s3); _m[6]=(T) (c1*s2*s3) + (s1*c3); _m[10]=(T) (c1*c2);
1226 
1227  _m[3]=_m[7]=_m[11]=0; _m[15]=1;
1228 
1229  if (!keepTrans)
1230  { _m[12] = _m[13] = _m[14] = 0;
1231  }
1232 }
1233 //-----------------------------------------------------------------------------
1234 /*!
1235 Gets one set of possible z-y-x euler angles that will generate this matrix
1236 Assumes that upper 3x3 is a rotation matrix
1237 Source: Essential Mathematics for Games and Interactive Applications
1238 A Programmer's Guide 2nd edition by James M. Van Verth and Lars M. Bishop
1239 */
1240 template<class T>
1241 void SLMat4<T>::toEulerAnglesZYX(T& zRotRAD, T& yRotRAD, T& xRotRAD)
1242 {
1243  T Cx, Sx;
1244  T Cy, Sy;
1245  T Cz, Sz;
1246 
1247  Sy = -_m[2];
1248  Cy = (T)sqrt(1.0 - Sy*Sy);
1249 
1250  // normal case
1251  if (Utils::abs(Cy) > FLT_EPSILON)
1252  {
1253  T factor = (T)(1.0 / Cy);
1254  Sx = _m[ 6]*factor;
1255  Cx = _m[10]*factor;
1256  Sz = _m[ 1]*factor;
1257  Cz = _m[ 0]*factor;
1258  }
1259  else // x and z axes aligned
1260  {
1261  Sz = 0.0;
1262  Cz = 1.0;
1263  Sx = _m[4];
1264  Cx = _m[8];
1265  }
1266 
1267  zRotRAD = atan2f(Sz, Cz);
1268  yRotRAD = atan2f(Sy, Cy);
1269  xRotRAD = atan2f(Sx, Cx);
1270 }
1271 /*!
1272 Gets one set of possible x-y-z euler angles that will generate this matrix
1273 Assumes that upper 3x3 is a rotation matrix
1274 Source: Essential Mathematics for Games and Interactive Applications
1275 A Programmer's Guide 2nd edition by James M. Van Verth and Lars M. Bishop
1276 */
1277 template<class T>
1278 void SLMat4<T>::toEulerAnglesXYZ(T& xRotRAD, T& yRotRAD, T& zRotRAD)
1279 {
1280  T Cx, Sx;
1281  T Cy, Sy;
1282  T Cz, Sz;
1283 
1284  Sy = _m[8];
1285  Cy = (T)sqrt(1.0 - Sy*Sy);
1286 
1287  // normal case
1288  if (Utils::abs(Cy) > FLT_EPSILON)
1289  {
1290  T factor = (T)(1.0 / Cy);
1291  Sx = -_m[ 9]*factor;
1292  Cx = _m[10]*factor;
1293  Sz = -_m[ 4]*factor;
1294  Cz = _m[ 0]*factor;
1295  }
1296  else // x and z axes aligned
1297  {
1298  Sz = 0.0;
1299  Cz = 1.0;
1300  Sx = _m[6];
1301  Cx = _m[5];
1302  }
1303 
1304  zRotRAD = atan2f(Sz, Cz);
1305  yRotRAD = atan2f(Sy, Cy);
1306  xRotRAD = atan2f(Sx, Cx);
1307 }
1308 
1309 template<class T>
1311 {
1312  HMatrix A;
1313  A[0][0]=_m[0]; A[0][1]=_m[4]; A[0][2]=_m[ 8]; A[0][3]=_m[12];
1314  A[1][0]=_m[1]; A[1][1]=_m[5]; A[1][2]=_m[ 9]; A[1][3]=_m[13];
1315  A[2][0]=_m[2]; A[2][1]=_m[6]; A[2][2]=_m[10]; A[2][3]=_m[14];
1316  A[3][0]=_m[3]; A[3][1]=_m[7]; A[3][2]=_m[11]; A[3][3]=_m[15];
1317 
1318  EulerAngles eulerAngles = Eul_FromHMatrix(A, order);
1319 
1320  SLVec3<T> angles;
1321  angles.x = eulerAngles.x;
1322  angles.y = eulerAngles.y;
1323  angles.z = eulerAngles.z;
1324  return angles;
1325 }
1326 //-----------------------------------------------------------------------------
1327 
1328 //-----------------------------------------------------------------------------
1329 // Misc. methods
1330 //-----------------------------------------------------------------------------
1331 //! Sets the identity matrix
1332 template<class T>
1334 {
1335  _m[0]=_m[5]=_m[10]=_m[15]=1;
1336  _m[1]=_m[2]=_m[3]=_m[4]=_m[6]=_m[7]=_m[8]=_m[9]=_m[11]=_m[12]=_m[13]=_m[14]=0;
1337 }
1338 //-----------------------------------------------------------------------------
1339 //! Sets the transposed matrix by swaping around the main diagonal
1340 template<class T>
1342 {
1343  swap(_m[1], _m[ 4]);
1344  swap(_m[2], _m[ 8]);
1345  swap(_m[6], _m[ 9]);
1346  swap(_m[3], _m[12]);
1347  swap(_m[7], _m[13]);
1348  swap(_m[11],_m[14]);
1349 }
1350 //-----------------------------------------------------------------------------
1351 //! Returns the transposed of the matrix and leaves the itself unchanged
1352 template<class T>
1354 {
1355  SLMat4<T> t( _m[0], _m[1], _m[2], _m[3],
1356  _m[4], _m[5], _m[6], _m[7],
1357  _m[8], _m[9],_m[10],_m[11],
1358  _m[12],_m[13],_m[14],_m[15]);
1359  return t;
1360 }
1361 //-----------------------------------------------------------------------------
1362 //! Inverts the matrix
1363 template<class T>
1365 {
1366  setMatrix(inverted());
1367 }
1368 //-----------------------------------------------------------------------------
1369 //! Computes the inverse of a 4x4 non-singular matrix.
1370 template<class T>
1372 {
1373  SLMat4<T> i;
1374 
1375  // Code from Mesa-2.2\src\glu\project.c
1376  T det, d12, d13, d23, d24, d34, d41;
1377 
1378  // Inverse = adjoint / det. (See linear algebra texts.)
1379  // pre-compute 2x2 dets for last two rows when computing
1380  // cof_actors of first two rows.
1381  d12 = ( _m[2]*_m[ 7] - _m[ 3]*_m[ 6]);
1382  d13 = ( _m[2]*_m[11] - _m[ 3]*_m[10]);
1383  d23 = ( _m[6]*_m[11] - _m[ 7]*_m[10]);
1384  d24 = ( _m[6]*_m[15] - _m[ 7]*_m[14]);
1385  d34 = (_m[10]*_m[15] - _m[11]*_m[14]);
1386  d41 = (_m[14]*_m[ 3] - _m[15]*_m[ 2]);
1387 
1388  i._m[0] = (_m[5]*d34 - _m[9]*d24 + _m[13]*d23);
1389  i._m[1] = -(_m[1]*d34 + _m[9]*d41 + _m[13]*d13);
1390  i._m[2] = (_m[1]*d24 + _m[5]*d41 + _m[13]*d12);
1391  i._m[3] = -(_m[1]*d23 - _m[5]*d13 + _m[ 9]*d12);
1392 
1393  // Compute determinant as early as possible using these cof_actors.
1394  det = _m[0]*i._m[0] + _m[4]*i._m[1] + _m[8]*i._m[2] + _m[12]*i._m[3];
1395 
1396  // Run singularity test.
1397  if (fabs(det) < FLT_EPSILON)
1398  {
1399  SL_LOG("4x4-Matrix is singular. Inversion impossible.");
1400  exit(-1);
1401  }
1402  else
1403  {
1404  T invDet = 1 / det;
1405  // Compute rest of inverse.
1406  i._m[0] *= invDet;
1407  i._m[1] *= invDet;
1408  i._m[2] *= invDet;
1409  i._m[3] *= invDet;
1410 
1411  i._m[4] = -(_m[4]*d34 - _m[8]*d24 + _m[12]*d23)*invDet;
1412  i._m[5] = (_m[0]*d34 + _m[8]*d41 + _m[12]*d13)*invDet;
1413  i._m[6] = -(_m[0]*d24 + _m[4]*d41 + _m[12]*d12)*invDet;
1414  i._m[7] = (_m[0]*d23 - _m[4]*d13 + _m[8]*d12)*invDet;
1415 
1416  // Pre-compute 2x2 dets for first two rows when computing
1417  // cofactors of last two rows.
1418  d12 = _m[ 0]*_m[ 5] - _m[ 1]*_m[ 4];
1419  d13 = _m[ 0]*_m[ 9] - _m[ 1]*_m[ 8];
1420  d23 = _m[ 4]*_m[ 9] - _m[ 5]*_m[ 8];
1421  d24 = _m[ 4]*_m[13] - _m[ 5]*_m[12];
1422  d34 = _m[ 8]*_m[13] - _m[ 9]*_m[12];
1423  d41 = _m[12]*_m[ 1] - _m[13]*_m[ 0];
1424 
1425  i._m[ 8] = (_m[7]*d34 - _m[11]*d24 + _m[15]*d23)*invDet;
1426  i._m[ 9] = -(_m[3]*d34 + _m[11]*d41 + _m[15]*d13)*invDet;
1427  i._m[10] = (_m[3]*d24 + _m[ 7]*d41 + _m[15]*d12)*invDet;
1428  i._m[11] = -(_m[3]*d23 - _m[ 7]*d13 + _m[11]*d12)*invDet;
1429  i._m[12] = -(_m[6]*d34 - _m[10]*d24 + _m[14]*d23)*invDet;
1430  i._m[13] = (_m[2]*d34 + _m[10]*d41 + _m[14]*d13)*invDet;
1431  i._m[14] = -(_m[2]*d24 + _m[ 6]*d41 + _m[14]*d12)*invDet;
1432  i._m[15] = (_m[2]*d23 - _m[ 6]*d13 + _m[10]*d12)*invDet;
1433  }
1434  return i;
1435 }
1436 //-----------------------------------------------------------------------------
1437 /*! Computes the inverse transposed matrix of the upper left 3x3 matrix for
1438 the transformation of vertex normals.
1439 */
1440 template<class T>
1442 {
1443  SLMat3<T> i(_m[0], _m[4], _m[8],
1444  _m[1], _m[5], _m[9],
1445  _m[2], _m[6], _m[10]);
1446  i.invert();
1447  i.transpose();
1448  return i;
1449 }
1450 //-----------------------------------------------------------------------------
1451 /*!
1452 Returns the trace of the matrix that is the sum of the diagonal components.
1453 */
1454 template<class T>
1455 inline T SLMat4<T>::trace() const
1456 {
1457  return _m[0] + _m[5] + _m[10] + _m[15];
1458 }
1459 
1460 
1461 
1462 //-----------------------------------------------------------------------------
1463 /*!
1464 Composes the matrix from a translation vector, a rotation Euler angle vector
1465 and the scaling factors.
1466 */
1467 template<class T>
1468 void SLMat4<T>::compose(const SLVec3f trans,
1469  const SLVec3f rotEulerRAD,
1470  const SLVec3f scaleFactors)
1471 {
1472  fromEulerAnglesXYZ(rotEulerRAD.x, rotEulerRAD.y, rotEulerRAD.z);
1473  scale(scaleFactors);
1474  translate(trans);
1475 }
1476 //-----------------------------------------------------------------------------
1477 /*!
1478 Decomposes the matrix into a translation vector, a rotation quaternion and the
1479 scaling factors using polar decomposition introduced by Ken Shoemake.
1480 See the paper in lib-SLExternal/Shoemake/polar-decomp.pdf
1481 */
1482 template<class T>
1483 void SLMat4<T>::decompose(SLVec3f &trans, SLVec4f &rotQuat, SLVec3f &scale)
1484 {
1485  // Input matrix A
1486  HMatrix A;
1487  A[0][0]=_m[0]; A[0][1]=_m[4]; A[0][2]=_m[ 8]; A[0][3]=_m[12];
1488  A[1][0]=_m[1]; A[1][1]=_m[5]; A[1][2]=_m[ 9]; A[1][3]=_m[13];
1489  A[2][0]=_m[2]; A[2][1]=_m[6]; A[2][2]=_m[10]; A[2][3]=_m[14];
1490  A[3][0]=_m[3]; A[3][1]=_m[7]; A[3][2]=_m[11]; A[3][3]=_m[15];
1491 
1492  AffineParts parts;
1493  decomp_affine(A, &parts);
1494 
1495  trans.set(parts.t.x, parts.t.y, parts.t.z);
1496  scale.set(parts.k.x, parts.k.y, parts.k.z);
1497  rotQuat.set(parts.q.x, parts.q.y, parts.q.z, parts.q.w);
1498 }
1499 //-----------------------------------------------------------------------------
1500 /*!
1501 Decomposes the matrix into a translation vector, a 3x3 rotation matrix and the
1502 scaling factors using polar decomposition introduced by Ken Shoemake.
1503 See the paper in lib-SLExternal/Shoemake/polar-decomp.pdf
1504 */
1505 template<class T>
1506 void SLMat4<T>::decompose(SLVec3f &trans, SLMat3f &rotMat, SLVec3f &scale)
1507 {
1508  SLVec4f rotQuat;
1509  decompose(trans, rotQuat, scale);
1510 
1511  // Convert quaternion to 3x3 matrix
1512  SLfloat qx = rotQuat.x;
1513  SLfloat qy = rotQuat.y;
1514  SLfloat qz = rotQuat.z;
1515  SLfloat qw = rotQuat.w;
1516 
1517  SLfloat x2 = qx * 2.0f;
1518  SLfloat y2 = qy * 2.0f;
1519  SLfloat z2 = qz * 2.0f;
1520 
1521  SLfloat wx2 = qw * x2; SLfloat wy2 = qw * y2; SLfloat wz2 = qw * z2;
1522  SLfloat xx2 = qx * x2; SLfloat xy2 = qx * y2; SLfloat xz2 = qx * z2;
1523  SLfloat yy2 = qy * y2; SLfloat yz2 = qy * z2; SLfloat zz2 = qz * z2;
1524 
1525  rotMat.setMatrix(1.0f-(yy2 + zz2), xy2 - wz2 , xz2 + wy2,
1526  xy2 + wz2 , 1.0f-(xx2 + zz2), yz2 - wx2,
1527  xz2 - wy2 , yz2 + wx2 , 1.0f-(xx2 + yy2));
1528 }
1529 //-----------------------------------------------------------------------------
1530 /*!
1531 Decomposes the matrix into a translation vector, a rotation Euler angle vector
1532 and the scaling factors using polar decomposition introduced by Ken Shoemake.
1533 See the paper in lib-SLExternal/Shoemake/polar-decomp.pdf
1534 */
1535 template<class T>
1536 void SLMat4<T>::decompose(SLVec3f &trans, SLVec3f &rotEulerRAD, SLVec3f &scale)
1537 {
1538  SLMat3f rotMat;
1539  decompose(trans, rotMat, scale);
1540 
1541  SLfloat rotAngleXRAD, rotAngleYRAD, rotAngleZRAD;
1542  rotMat.toEulerAnglesXYZ(rotAngleXRAD, rotAngleYRAD, rotAngleZRAD);
1543 
1544  rotEulerRAD.set(rotAngleXRAD, rotAngleYRAD, rotAngleZRAD);
1545 }
1546 
1547 
1548 
1549 //-----------------------------------------------------------------------------
1550 /*!
1551 Prints out the matrix row by row.
1552 */
1553 template<class T>
1554 void SLMat4<T>::print(const SLchar* str) const
1555 {
1556  if (str) SL_LOG("%s",str);
1557  SL_LOG("% 3.2f % 3.2f % 3.2f % 3.2f", _m[0],_m[4],_m[ 8],_m[12]);
1558  SL_LOG("% 3.2f % 3.2f % 3.2f % 3.2f", _m[1],_m[5],_m[ 9],_m[13]);
1559  SL_LOG("% 3.2f % 3.2f % 3.2f % 3.2f", _m[2],_m[6],_m[10],_m[14]);
1560  SL_LOG("% 3.2f % 3.2f % 3.2f % 3.2f", _m[3],_m[7],_m[11],_m[15]);
1561 }
1562 //-----------------------------------------------------------------------------
1563 /*!
1564 Prints out the matrix row by row.
1565 */
1566 template<class T>
1568 {
1569  SLchar cstr[500];
1570  snprintf(cstr,
1571  sizeof(cstr),
1572  "% 3.3f % 3.3f % 3.3f % 3.3f\n% 3.3f % 3.3f % 3.3f % 3.3f\n% 3.3f % 3.3f % 3.3f % 3.3f\n% 3.3f % 3.3f % 3.3f % 3.3f",
1573  _m[0],_m[4],_m[ 8],_m[12],
1574  _m[1],_m[5],_m[ 9],_m[13],
1575  _m[2],_m[6],_m[10],_m[14],
1576  _m[3],_m[7],_m[11],_m[15]);
1577  SLstring cppstr = cstr;
1578  return cppstr;
1579 }
1580 //-----------------------------------------------------------------------------
1582 #ifdef SL_HAS_DOUBLE
1583 typedef SLMat4<SLdouble> SLMat4d;
1584 #endif
1585 typedef vector<SLMat4f> SLVMat4f;
1586 typedef std::stack<SLMat4f> SLSMat4f;
1587 //-----------------------------------------------------------------------------
1588 #endif
float SLfloat
Definition: SL.h:173
#define SL_LOG(...)
Definition: SL.h:233
unsigned int SLuint
Definition: SL.h:171
char SLchar
Definition: SL.h:162
bool SLbool
Definition: SL.h:175
string SLstring
Definition: SL.h:158
int SLint
Definition: SL.h:170
std::stack< SLMat4f > SLSMat4f
Definition: SLMat4.h:1586
SLMat4< SLfloat > SLMat4f
Definition: SLMat4.h:1581
vector< SLMat4f > SLVMat4f
Definition: SLMat4.h:1585
void transpose()
Transposes the matrix.
Definition: SLMat3.h:337
void setMatrix(const SLMat3 &A)
Definition: SLMat3.h:299
void invert()
Inverts the matrix.
Definition: SLMat3.h:356
T _m[9]
Definition: SLMat3.h:41
void toEulerAnglesXYZ(T &xRotRAD, T &yRotRAD, T &zRotRAD)
Definition: SLMat3.h:608
4x4 matrix template class
Definition: SLMat4.h:52
void scale(T sxyz)
Definition: SLMat4.h:667
SLbool isEqual(const SLMat4 &A, SLfloat epsilon=0.01f)
Returns true if one element of the matrix differs more than epsilon.
Definition: SLMat4.h:521
void print(const SLchar *str=nullptr) const
Definition: SLMat4.h:1554
void setMatrix(const SLMat3f &A)
Set matrix by other 3x3 matrix.
Definition: SLMat4.h:341
void scale(const SLVec3< T > &sxyz)
Definition: SLMat4.h:694
SLMat4< T > operator/(T a) const
scalar division
Definition: SLMat4.h:498
void transpose()
Sets the transposed matrix by swaping around the main diagonal.
Definition: SLMat4.h:1341
SLMat4< T > operator*(const SLMat4 &A) const
matrix-matrix multiplication
Definition: SLMat4.h:419
SLVec3< T > translation() const
Definition: SLMat4.h:184
void lookAt(SLVec3< T > *eye, SLVec3< T > *at, SLVec3< T > *up, SLVec3< T > *right) const
Reads out of the matrix the look at parameters.
Definition: SLMat4.h:760
void lookAt(T EyeX, T EyeY, T EyeZ, T AtX=0, T AtY=0, T AtZ=0, T UpX=0, T UpY=0, T UpZ=0)
Defines the a view matrix as the corresponding gluLookAt function.
Definition: SLMat4.h:708
void posAtUp(T PosX, T PosY, T PosZ, T dirAtX=0, T dirAtY=0, T dirAtZ=0, T dirUpX=0, T dirUpY=0, T dirUpZ=0)
Same as lightAt.
Definition: SLMat4.h:822
SLMat4(T tx, T ty, T tz)
Sets translate matrix.
Definition: SLMat4.h:295
void translate(const SLVec2< T > &t)
Definition: SLMat4.h:612
SLMat3< T > mat3() const
Definition: SLMat4.h:98
void setTranslation(const SLVec3< T > &translation)
Set vector as submatrix describing the translational part.
Definition: SLMat4.h:393
void setRotation(const SLMat3< T > &rotation)
Set 3x3 submatrix describing the rotational part.
Definition: SLMat4.h:385
void toEulerAnglesZYX(T &zRotRAD, T &yRotRAD, T &xRotRAD)
Definition: SLMat4.h:1241
SLMat4< T > operator+(const SLMat4 &A) const
matrix-matrix addition
Definition: SLMat4.h:440
void perspectiveCenteredPP(T w, T h, T fx, T fy, T cx, T cy, T n, T f)
Defines a projection matrix for a calibrated camera, the principle point has to be centered (from int...
Definition: SLMat4.h:891
SLMat4< T > & operator/=(T a)
scalar division
Definition: SLMat4.h:512
SLMat4(T scale_xyz)
Sets scaling matrix.
Definition: SLMat4.h:313
void setMatrix(const SLMat4 &A)
Set matrix by other 4x4 matrix.
Definition: SLMat4.h:335
SLVec3< T > axisX() const
Definition: SLMat4.h:185
void add(const SLMat4 &A)
Definition: SLMat4.h:566
void translation(T tx, T ty, T tz, SLbool keepLinear=true)
Sets the translation with or without overwriting the linear submatrix.
Definition: SLMat4.h:958
void setMatrix(const SLVec3< T > &translation, const SLMat3< T > &rotation, const SLVec3< T > &scale)
Set matrix by translation, rotation & scale.
Definition: SLMat4.h:374
void scaling(const SLVec3< T > &sxyz, SLbool keepTrans=true)
Definition: SLMat4.h:1157
SLMat4< T > & operator=(const SLMat4 &A)
assignment operator
Definition: SLMat4.h:406
T _m[16]
The 16 elements of the matrix.
Definition: SLMat4.h:255
SLVec3< T > toEulerAngles(int order)
Definition: SLMat4.h:1310
void scaling(T sx, T sy, T sz, SLbool keepTranslation=true)
Definition: SLMat4.h:1168
T m(int i) const
Definition: SLMat4.h:97
SLMat4< T > & operator*=(const SLMat4 &A)
matrix-matrix multiplication
Definition: SLMat4.h:430
SLMat4< T > transposed()
Returns the transposed of the matrix and leaves the itself unchanged.
Definition: SLMat4.h:1353
void setMatrix(T M0, T M4, T M8, T M12, T M1, T M5, T M9, T M13, T M2, T M6, T M10, T M14, T M3, T M7, T M11, T M15)
Set matrix by components.
Definition: SLMat4.h:362
SLVec4< T > multVec(SLVec4< T > v) const
Definition: SLMat4.h:588
void ortho(T l, T r, T b, T t, T n, T f)
Defines a orthographic projection matrix with a field of view angle.
Definition: SLMat4.h:911
SLMat4(const SLVec3< T > &translationVec)
Sets translate matrix.
Definition: SLMat4.h:301
void rotation(T degAng, const SLVec3< T > &axis, SLbool keepTranslation=true)
Sets the rotation with or without overwriting the translation.
Definition: SLMat4.h:978
SLVec3< T > axisY() const
Definition: SLMat4.h:186
void translation(const SLVec3< T > &t, SLbool keepLinear=true)
Definition: SLMat4.h:948
void invert()
Inverts the matrix.
Definition: SLMat4.h:1364
void decompose(SLVec3f &trans, SLMat3f &rotMat, SLVec3f &scale)
Definition: SLMat4.h:1506
void decompose(SLVec3f &trans, SLVec4f &rotQuat, SLVec3f &scale)
Definition: SLMat4.h:1483
SLMat4(const SLVec3< T > &fromUnitVec, const SLVec3< T > &toUnitVec)
Sets rotation matrix.
Definition: SLMat4.h:319
void m(int i, T val)
Definition: SLMat4.h:93
void rotation(T degAng, T axisx, T axisy, T axisz, SLbool keepTranslation=true)
Definition: SLMat4.h:989
void rotate(T degAng, T axisx, T axisy, T axisz)
Definition: SLMat4.h:656
void compose(SLVec3f trans, SLVec3f rotEulerRAD, SLVec3f scale)
Definition: SLMat4.h:1468
void lookAt(const SLVec3< T > &Eye, const SLVec3< T > &At=SLVec3< T >::ZERO, const SLVec3< T > &Up=SLVec3< T >::ZERO)
Defines the a view matrix as the corresponding gluLookAt function.
Definition: SLMat4.h:727
void rotate(T degAng, const SLVec3< T > &axis)
Definition: SLMat4.h:634
SLMat4()
Sets identity matrix.
Definition: SLMat4.h:262
void setMatrix(const SLMat4 *A)
Set matrix by other matrix pointer.
Definition: SLMat4.h:350
const T * m() const
Definition: SLMat4.h:96
void multiply(const SLMat4 &A)
Definition: SLMat4.h:536
void scale(T sx, T sy, T sz)
Definition: SLMat4.h:680
SLstring toString() const
Definition: SLMat4.h:1567
void lightAt(const SLVec3< T > &pos, const SLVec3< T > &At=SLVec3< T >::ZERO, const SLVec3< T > &Up=SLVec3< T >::ZERO)
Defines the a model matrix for light positioning.
Definition: SLMat4.h:795
void fromEulerAnglesXYZ(double angle1RAD, double angle2RAD, double angle3RAD, bool keepTranslation=true)
Definition: SLMat4.h:1214
void fromEulerAnglesZXZ(double angle1RAD, double angle2RAD, double angle3RAD, bool keepTranslation=true)
Definition: SLMat4.h:1187
SLVec3< T > multVec(SLVec3< T > v) const
Definition: SLMat4.h:576
SLMat4(const SLMat4 &A)
Sets mat by other SLMat4.
Definition: SLMat4.h:267
SLMat4< T > inverted() const
Computes the inverse of a 4x4 non-singular matrix.
Definition: SLMat4.h:1371
SLVec3< T > axisZ() const
Definition: SLMat4.h:187
void perspective(T fov, T aspect, T n, T f)
Defines a perspective projection matrix with a field of view angle.
Definition: SLMat4.h:874
void identity()
Sets the identity matrix.
Definition: SLMat4.h:1333
void rotation(const SLVec3< T > &fromUnitVec, const SLVec3< T > &toUnitVec)
Definition: SLMat4.h:1035
static void swap(T &a, T &b)
Definition: SLMat4.h:252
SLMat4(T M0, T M4, T M8, T M12, T M1, T M5, T M9, T M13, T M2, T M6, T M10, T M14, T M3, T M7, T M11, T M15)
Definition: SLMat4.h:277
T trace() const
Definition: SLMat4.h:1455
SLMat4(const SLMat3f &A)
Sets mat by other SLMat3.
Definition: SLMat4.h:272
void posAtUp(const SLVec3< T > &pos, const SLVec3< T > &dirAt=SLVec3< T >::ZERO, const SLVec3< T > &dirUp=SLVec3< T >::ZERO)
Same as lightAt.
Definition: SLMat4.h:834
SLMat4(const T *M)
Sets mat by array.
Definition: SLMat4.h:289
SLMat4(T degAng, T axis_x, T axis_y, T axis_z)
Sets rotation matrix.
Definition: SLMat4.h:307
void setMatrix(const int16_t i, const SLfloat value)
Definition: SLMat4.h:90
void translate(const SLVec3< T > &t)
Definition: SLMat4.h:623
void frustum(T l, T r, T b, T t, T n, T f)
Defines a view frustum projection matrix equivalent to glFrustum.
Definition: SLMat4.h:855
SLMat4(const SLVec3< T > &translation, const SLMat3< T > &rotation, const SLVec3< T > &scale)
Set matrix by translation, rotation & scale.
Definition: SLMat4.h:325
void scaling(T sxyz, SLbool keepTrans=true)
Sets the scaling with or without overwriting the translation.
Definition: SLMat4.h:1146
void decompose(SLVec3f &trans, SLVec3f &rotEulerRAD, SLVec3f &scale)
Definition: SLMat4.h:1536
void rotate(const SLVec3< T > &fromUnitVec, const SLVec3< T > &toUnitVec)
Definition: SLMat4.h:645
void lightAt(T PosX, T PosY, T PosZ, T AtX=0, T AtY=0, T AtZ=0, T UpX=0, T UpY=0, T UpZ=0)
Defines the a model matrix for light positioning.
Definition: SLMat4.h:778
SLMat3< T > inverseTransposed()
Definition: SLMat4.h:1441
void setMatrix(const T *M)
Set matrix by float[16] array.
Definition: SLMat4.h:356
void toEulerAnglesXYZ(T &xRotRAD, T &yRotRAD, T &zRotRAD)
Definition: SLMat4.h:1278
T & operator()(int row, int col)
Definition: SLMat4.h:114
void translate(T tx, T ty, T tz=0)
Definition: SLMat4.h:601
void viewport(T x, T y, T ww, T wh, T n=0.0f, T f=1.0f)
Defines the viewport matrix.
Definition: SLMat4.h:930
The SLScene class represents the top level instance holding the scene structure.
Definition: SLScene.h:47
2D vector template class for standard 2D vector algebra.
Definition: SLVec2.h:27
T y
Definition: SLVec2.h:30
T x
Definition: SLVec2.h:30
3D vector template class for standard 3D vector algebra.
Definition: SLVec3.h:40
T y
Definition: SLVec3.h:43
void cross(const SLVec3 &a, const SLVec3 &b)
Definition: SLVec3.h:118
T x
Definition: SLVec3.h:43
SLVec3 & normalize()
Definition: SLVec3.h:124
void set(const T X, const T Y, const T Z)
Definition: SLVec3.h:59
T dot(const SLVec3 &v) const
Definition: SLVec3.h:117
T z
Definition: SLVec3.h:43
4D vector template class for standard 4D vector algebra.
Definition: SLVec4.h:29
T w
Definition: SLVec4.h:32
T z
Definition: SLVec4.h:32
void set(const T X, const T Y, const T Z, const T W=1)
Definition: SLVec4.h:49
T y
Definition: SLVec4.h:32
T x
Definition: SLVec4.h:32
static const float DEG2RAD
Definition: Utils.h:239
T abs(T a)
Definition: Utils.h:249