Irrlicht 3D Engine
matrix4.h
Go to the documentation of this file.
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
4 
5 #ifndef __IRR_MATRIX_H_INCLUDED__
6 #define __IRR_MATRIX_H_INCLUDED__
7 
8 #include "irrMath.h"
9 #include "vector3d.h"
10 #include "vector2d.h"
11 #include "plane3d.h"
12 #include "aabbox3d.h"
13 #include "rect.h"
14 #include "irrString.h"
15 
16 // enable this to keep track of changes to the matrix
17 // and make simpler identity check for seldomly changing matrices
18 // otherwise identity check will always compare the elements
19 //#define USE_MATRIX_TEST
20 
21 // this is only for debugging purposes
22 //#define USE_MATRIX_TEST_DEBUG
23 
24 #if defined( USE_MATRIX_TEST_DEBUG )
25 
26 struct MatrixTest
27 {
28  MatrixTest () : ID(0), Calls(0) {}
29  char buf[256];
30  int Calls;
31  int ID;
32 };
33 static MatrixTest MTest;
34 
35 #endif
36 
37 namespace irr
38 {
39 namespace core
40 {
41 
43 
44  template <class T>
45  class CMatrix4
46  {
47  public:
48 
51  {
58  };
59 
61 
62  CMatrix4( eConstructor constructor = EM4CONST_IDENTITY );
64 
66  CMatrix4(const CMatrix4<T>& other, eConstructor constructor = EM4CONST_COPY);
67 
69  T& operator()(const s32 row, const s32 col)
70  {
71 #if defined ( USE_MATRIX_TEST )
72  definitelyIdentityMatrix=false;
73 #endif
74  return M[ row * 4 + col ];
75  }
76 
78  const T& operator()(const s32 row, const s32 col) const { return M[row * 4 + col]; }
79 
81  T& operator[](u32 index)
82  {
83 #if defined ( USE_MATRIX_TEST )
84  definitelyIdentityMatrix=false;
85 #endif
86  return M[index];
87  }
88 
90  const T& operator[](u32 index) const { return M[index]; }
91 
93  inline CMatrix4<T>& operator=(const CMatrix4<T> &other);
94 
96  inline CMatrix4<T>& operator=(const T& scalar);
97 
99  const T* pointer() const { return M; }
100  T* pointer()
101  {
102 #if defined ( USE_MATRIX_TEST )
103  definitelyIdentityMatrix=false;
104 #endif
105  return M;
106  }
107 
109  bool operator==(const CMatrix4<T> &other) const;
110 
112  bool operator!=(const CMatrix4<T> &other) const;
113 
115  CMatrix4<T> operator+(const CMatrix4<T>& other) const;
116 
118  CMatrix4<T>& operator+=(const CMatrix4<T>& other);
119 
121  CMatrix4<T> operator-(const CMatrix4<T>& other) const;
122 
124  CMatrix4<T>& operator-=(const CMatrix4<T>& other);
125 
127 
128  inline CMatrix4<T>& setbyproduct(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
129 
131 
133  CMatrix4<T>& setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
134 
136 
137  CMatrix4<T> operator*(const CMatrix4<T>& other) const;
138 
140 
141  CMatrix4<T>& operator*=(const CMatrix4<T>& other);
142 
144  CMatrix4<T> operator*(const T& scalar) const;
145 
147  CMatrix4<T>& operator*=(const T& scalar);
148 
150  inline CMatrix4<T>& makeIdentity();
151 
153  inline bool isIdentity() const;
154 
156  inline bool isOrthogonal() const;
157 
159  bool isIdentity_integer_base () const;
160 
162  CMatrix4<T>& setTranslation( const vector3d<T>& translation );
163 
165  vector3d<T> getTranslation() const;
166 
168  CMatrix4<T>& setInverseTranslation( const vector3d<T>& translation );
169 
171  inline CMatrix4<T>& setRotationRadians( const vector3d<T>& rotation );
172 
174  CMatrix4<T>& setRotationDegrees( const vector3d<T>& rotation );
175 
177 
179 
181 
182  inline CMatrix4<T>& setInverseRotationRadians( const vector3d<T>& rotation );
183 
185 
186  inline CMatrix4<T>& setInverseRotationDegrees( const vector3d<T>& rotation );
187 
189 
190  inline CMatrix4<T>& setRotationAxisRadians(const T& angle, const vector3d<T>& axis);
191 
193  CMatrix4<T>& setScale( const vector3d<T>& scale );
194 
196  CMatrix4<T>& setScale( const T scale ) { return setScale(core::vector3d<T>(scale,scale,scale)); }
197 
199  core::vector3d<T> getScale() const;
200 
202  void inverseTranslateVect( vector3df& vect ) const;
203 
205  void inverseRotateVect( vector3df& vect ) const;
206 
208  void rotateVect( vector3df& vect ) const;
209 
211  void rotateVect(core::vector3df& out, const core::vector3df& in) const;
212 
214  void rotateVect(T *out,const core::vector3df &in) const;
215 
217  void transformVect( vector3df& vect) const;
218 
220  void transformVect( vector3df& out, const vector3df& in ) const;
221 
223  void transformVect(T *out,const core::vector3df &in) const;
224 
226  void transformVec3(T *out, const T * in) const;
227 
229  void translateVect( vector3df& vect ) const;
230 
232  void transformPlane( core::plane3d<f32> &plane) const;
233 
235  void transformPlane( const core::plane3d<f32> &in, core::plane3d<f32> &out) const;
236 
238 
240  void transformBox(core::aabbox3d<f32>& box) const;
241 
243 
245  void transformBoxEx(core::aabbox3d<f32>& box) const;
246 
248  void multiplyWith1x4Matrix(T* matrix) const;
249 
251 
252  bool makeInverse();
253 
254 
256 
257  bool getInversePrimitive ( CMatrix4<T>& out ) const;
258 
260 
262  bool getInverse(CMatrix4<T>& out) const;
263 
265  CMatrix4<T>& buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
266 
268  CMatrix4<T>& buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
269 
271  CMatrix4<T>& buildProjectionMatrixPerspectiveFovInfinityLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon=0);
272 
274  CMatrix4<T>& buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
275 
277  CMatrix4<T>& buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
278 
280  CMatrix4<T>& buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
281 
283  CMatrix4<T>& buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
284 
287  const vector3df& position,
288  const vector3df& target,
289  const vector3df& upVector);
290 
293  const vector3df& position,
294  const vector3df& target,
295  const vector3df& upVector);
296 
298 
302  CMatrix4<T>& buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point=1.0f);
303 
305 
306  CMatrix4<T>& buildNDCToDCMatrix( const core::rect<s32>& area, f32 zScale);
307 
309 
311  CMatrix4<T> interpolate(const core::CMatrix4<T>& b, f32 time) const;
312 
314  CMatrix4<T> getTransposed() const;
315 
317  inline void getTransposed( CMatrix4<T>& dest ) const;
318 
320 
324 
326 
329  void setRotationCenter(const core::vector3df& center, const core::vector3df& translate);
330 
332 
338  void buildAxisAlignedBillboard(const core::vector3df& camPos,
339  const core::vector3df& center,
340  const core::vector3df& translation,
341  const core::vector3df& axis,
342  const core::vector3df& from);
343 
344  /*
345  construct 2D Texture transformations
346  rotate about center, scale, and transform.
347  */
350  const core::vector2df &rotatecenter,
351  const core::vector2df &translate,
352  const core::vector2df &scale);
353 
355 
360 
362 
367 
369 
374 
376 
380  CMatrix4<T>& setTextureScale( f32 sx, f32 sy );
381 
383 
388 
390  CMatrix4<T>& setM(const T* data);
391 
393  void setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix);
394 
396  bool getDefinitelyIdentityMatrix() const;
397 
399  bool equals(const core::CMatrix4<T>& other, const T tolerance=(T)ROUNDING_ERROR_f64) const;
400 
401  private:
403  T M[16];
404 #if defined ( USE_MATRIX_TEST )
405  mutable u32 definitelyIdentityMatrix;
407 #endif
408 #if defined ( USE_MATRIX_TEST_DEBUG )
409  u32 id;
410  mutable u32 calls;
411 #endif
412 
413  };
414 
415  // Default constructor
416  template <class T>
417  inline CMatrix4<T>::CMatrix4( eConstructor constructor )
418 #if defined ( USE_MATRIX_TEST )
419  : definitelyIdentityMatrix(BIT_UNTESTED)
420 #endif
421 #if defined ( USE_MATRIX_TEST_DEBUG )
422  ,id ( MTest.ID++), calls ( 0 )
423 #endif
424  {
425  switch ( constructor )
426  {
427  case EM4CONST_NOTHING:
428  case EM4CONST_COPY:
429  break;
430  case EM4CONST_IDENTITY:
431  case EM4CONST_INVERSE:
432  default:
433  makeIdentity();
434  break;
435  }
436  }
437 
438  // Copy constructor
439  template <class T>
440  inline CMatrix4<T>::CMatrix4( const CMatrix4<T>& other, eConstructor constructor)
441 #if defined ( USE_MATRIX_TEST )
442  : definitelyIdentityMatrix(BIT_UNTESTED)
443 #endif
444 #if defined ( USE_MATRIX_TEST_DEBUG )
445  ,id ( MTest.ID++), calls ( 0 )
446 #endif
447  {
448  switch ( constructor )
449  {
450  case EM4CONST_IDENTITY:
451  makeIdentity();
452  break;
453  case EM4CONST_NOTHING:
454  break;
455  case EM4CONST_COPY:
456  *this = other;
457  break;
458  case EM4CONST_TRANSPOSED:
459  other.getTransposed(*this);
460  break;
461  case EM4CONST_INVERSE:
462  if (!other.getInverse(*this))
463  memset(M, 0, 16*sizeof(T));
464  break;
465  case EM4CONST_INVERSE_TRANSPOSED:
466  if (!other.getInverse(*this))
467  memset(M, 0, 16*sizeof(T));
468  else
469  *this=getTransposed();
470  break;
471  }
472  }
473 
475  template <class T>
476  inline CMatrix4<T> CMatrix4<T>::operator+(const CMatrix4<T>& other) const
477  {
478  CMatrix4<T> temp ( EM4CONST_NOTHING );
479 
480  temp[0] = M[0]+other[0];
481  temp[1] = M[1]+other[1];
482  temp[2] = M[2]+other[2];
483  temp[3] = M[3]+other[3];
484  temp[4] = M[4]+other[4];
485  temp[5] = M[5]+other[5];
486  temp[6] = M[6]+other[6];
487  temp[7] = M[7]+other[7];
488  temp[8] = M[8]+other[8];
489  temp[9] = M[9]+other[9];
490  temp[10] = M[10]+other[10];
491  temp[11] = M[11]+other[11];
492  temp[12] = M[12]+other[12];
493  temp[13] = M[13]+other[13];
494  temp[14] = M[14]+other[14];
495  temp[15] = M[15]+other[15];
496 
497  return temp;
498  }
499 
501  template <class T>
503  {
504  M[0]+=other[0];
505  M[1]+=other[1];
506  M[2]+=other[2];
507  M[3]+=other[3];
508  M[4]+=other[4];
509  M[5]+=other[5];
510  M[6]+=other[6];
511  M[7]+=other[7];
512  M[8]+=other[8];
513  M[9]+=other[9];
514  M[10]+=other[10];
515  M[11]+=other[11];
516  M[12]+=other[12];
517  M[13]+=other[13];
518  M[14]+=other[14];
519  M[15]+=other[15];
520 
521  return *this;
522  }
523 
525  template <class T>
526  inline CMatrix4<T> CMatrix4<T>::operator-(const CMatrix4<T>& other) const
527  {
528  CMatrix4<T> temp ( EM4CONST_NOTHING );
529 
530  temp[0] = M[0]-other[0];
531  temp[1] = M[1]-other[1];
532  temp[2] = M[2]-other[2];
533  temp[3] = M[3]-other[3];
534  temp[4] = M[4]-other[4];
535  temp[5] = M[5]-other[5];
536  temp[6] = M[6]-other[6];
537  temp[7] = M[7]-other[7];
538  temp[8] = M[8]-other[8];
539  temp[9] = M[9]-other[9];
540  temp[10] = M[10]-other[10];
541  temp[11] = M[11]-other[11];
542  temp[12] = M[12]-other[12];
543  temp[13] = M[13]-other[13];
544  temp[14] = M[14]-other[14];
545  temp[15] = M[15]-other[15];
546 
547  return temp;
548  }
549 
551  template <class T>
553  {
554  M[0]-=other[0];
555  M[1]-=other[1];
556  M[2]-=other[2];
557  M[3]-=other[3];
558  M[4]-=other[4];
559  M[5]-=other[5];
560  M[6]-=other[6];
561  M[7]-=other[7];
562  M[8]-=other[8];
563  M[9]-=other[9];
564  M[10]-=other[10];
565  M[11]-=other[11];
566  M[12]-=other[12];
567  M[13]-=other[13];
568  M[14]-=other[14];
569  M[15]-=other[15];
570 
571  return *this;
572  }
573 
575  template <class T>
576  inline CMatrix4<T> CMatrix4<T>::operator*(const T& scalar) const
577  {
578  CMatrix4<T> temp ( EM4CONST_NOTHING );
579 
580  temp[0] = M[0]*scalar;
581  temp[1] = M[1]*scalar;
582  temp[2] = M[2]*scalar;
583  temp[3] = M[3]*scalar;
584  temp[4] = M[4]*scalar;
585  temp[5] = M[5]*scalar;
586  temp[6] = M[6]*scalar;
587  temp[7] = M[7]*scalar;
588  temp[8] = M[8]*scalar;
589  temp[9] = M[9]*scalar;
590  temp[10] = M[10]*scalar;
591  temp[11] = M[11]*scalar;
592  temp[12] = M[12]*scalar;
593  temp[13] = M[13]*scalar;
594  temp[14] = M[14]*scalar;
595  temp[15] = M[15]*scalar;
596 
597  return temp;
598  }
599 
601  template <class T>
602  inline CMatrix4<T>& CMatrix4<T>::operator*=(const T& scalar)
603  {
604  M[0]*=scalar;
605  M[1]*=scalar;
606  M[2]*=scalar;
607  M[3]*=scalar;
608  M[4]*=scalar;
609  M[5]*=scalar;
610  M[6]*=scalar;
611  M[7]*=scalar;
612  M[8]*=scalar;
613  M[9]*=scalar;
614  M[10]*=scalar;
615  M[11]*=scalar;
616  M[12]*=scalar;
617  M[13]*=scalar;
618  M[14]*=scalar;
619  M[15]*=scalar;
620 
621  return *this;
622  }
623 
625  template <class T>
627  {
628 #if defined ( USE_MATRIX_TEST )
629  // do checks on your own in order to avoid copy creation
630  if ( !other.isIdentity() )
631  {
632  if ( this->isIdentity() )
633  {
634  return (*this = other);
635  }
636  else
637  {
638  CMatrix4<T> temp ( *this );
639  return setbyproduct_nocheck( temp, other );
640  }
641  }
642  return *this;
643 #else
644  CMatrix4<T> temp ( *this );
645  return setbyproduct_nocheck( temp, other );
646 #endif
647  }
648 
650  // set this matrix to the product of two other matrices
651  // goal is to reduce stack use and copy
652  template <class T>
654  {
655  const T *m1 = other_a.M;
656  const T *m2 = other_b.M;
657 
658  M[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
659  M[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
660  M[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
661  M[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
662 
663  M[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
664  M[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
665  M[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
666  M[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
667 
668  M[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
669  M[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
670  M[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
671  M[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
672 
673  M[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
674  M[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
675  M[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
676  M[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
677 #if defined ( USE_MATRIX_TEST )
678  definitelyIdentityMatrix=false;
679 #endif
680  return *this;
681  }
682 
683 
685  // set this matrix to the product of two other matrices
686  // goal is to reduce stack use and copy
687  template <class T>
688  inline CMatrix4<T>& CMatrix4<T>::setbyproduct(const CMatrix4<T>& other_a, const CMatrix4<T>& other_b )
689  {
690 #if defined ( USE_MATRIX_TEST )
691  if ( other_a.isIdentity () )
692  return (*this = other_b);
693  else
694  if ( other_b.isIdentity () )
695  return (*this = other_a);
696  else
697  return setbyproduct_nocheck(other_a,other_b);
698 #else
699  return setbyproduct_nocheck(other_a,other_b);
700 #endif
701  }
702 
704  template <class T>
706  {
707 #if defined ( USE_MATRIX_TEST )
708  // Testing purpose..
709  if ( this->isIdentity() )
710  return m2;
711  if ( m2.isIdentity() )
712  return *this;
713 #endif
714 
715  CMatrix4<T> m3 ( EM4CONST_NOTHING );
716 
717  const T *m1 = M;
718 
719  m3[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
720  m3[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
721  m3[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
722  m3[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
723 
724  m3[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
725  m3[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
726  m3[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
727  m3[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
728 
729  m3[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
730  m3[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
731  m3[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
732  m3[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
733 
734  m3[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
735  m3[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
736  m3[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
737  m3[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
738  return m3;
739  }
740 
741 
742 
743  template <class T>
745  {
746  return vector3d<T>(M[12], M[13], M[14]);
747  }
748 
749 
750  template <class T>
752  {
753  M[12] = translation.X;
754  M[13] = translation.Y;
755  M[14] = translation.Z;
756 #if defined ( USE_MATRIX_TEST )
757  definitelyIdentityMatrix=false;
758 #endif
759  return *this;
760  }
761 
762  template <class T>
764  {
765  M[12] = -translation.X;
766  M[13] = -translation.Y;
767  M[14] = -translation.Z;
768 #if defined ( USE_MATRIX_TEST )
769  definitelyIdentityMatrix=false;
770 #endif
771  return *this;
772  }
773 
774  template <class T>
776  {
777  M[0] = scale.X;
778  M[5] = scale.Y;
779  M[10] = scale.Z;
780 #if defined ( USE_MATRIX_TEST )
781  definitelyIdentityMatrix=false;
782 #endif
783  return *this;
784  }
785 
787 
794  template <class T>
796  {
797  // See http://www.robertblum.com/articles/2005/02/14/decomposing-matrices
798 
799  // Deal with the 0 rotation case first
800  // Prior to Irrlicht 1.6, we always returned this value.
801  if(core::iszero(M[1]) && core::iszero(M[2]) &&
802  core::iszero(M[4]) && core::iszero(M[6]) &&
803  core::iszero(M[8]) && core::iszero(M[9]))
804  return vector3d<T>(M[0], M[5], M[10]);
805 
806  // We have to do the full calculation.
807  return vector3d<T>(sqrtf(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]),
808  sqrtf(M[4] * M[4] + M[5] * M[5] + M[6] * M[6]),
809  sqrtf(M[8] * M[8] + M[9] * M[9] + M[10] * M[10]));
810  }
811 
812  template <class T>
814  {
815  return setRotationRadians( rotation * core::DEGTORAD );
816  }
817 
818  template <class T>
820  {
821  return setInverseRotationRadians( rotation * core::DEGTORAD );
822  }
823 
824  template <class T>
826  {
827  const f64 cr = cos( rotation.X );
828  const f64 sr = sin( rotation.X );
829  const f64 cp = cos( rotation.Y );
830  const f64 sp = sin( rotation.Y );
831  const f64 cy = cos( rotation.Z );
832  const f64 sy = sin( rotation.Z );
833 
834  M[0] = (T)( cp*cy );
835  M[1] = (T)( cp*sy );
836  M[2] = (T)( -sp );
837 
838  const f64 srsp = sr*sp;
839  const f64 crsp = cr*sp;
840 
841  M[4] = (T)( srsp*cy-cr*sy );
842  M[5] = (T)( srsp*sy+cr*cy );
843  M[6] = (T)( sr*cp );
844 
845  M[8] = (T)( crsp*cy+sr*sy );
846  M[9] = (T)( crsp*sy-sr*cy );
847  M[10] = (T)( cr*cp );
848 #if defined ( USE_MATRIX_TEST )
849  definitelyIdentityMatrix=false;
850 #endif
851  return *this;
852  }
853 
854 
856 
859  template <class T>
861  {
862  const CMatrix4<T> &mat = *this;
863  core::vector3d<T> scale = getScale();
864  // we need to check for negative scale on to axes, which would bring up wrong results
865  if (scale.Y<0 && scale.Z<0)
866  {
867  scale.Y =-scale.Y;
868  scale.Z =-scale.Z;
869  }
870  else if (scale.X<0 && scale.Z<0)
871  {
872  scale.X =-scale.X;
873  scale.Z =-scale.Z;
874  }
875  else if (scale.X<0 && scale.Y<0)
876  {
877  scale.X =-scale.X;
878  scale.Y =-scale.Y;
879  }
880  const core::vector3d<f64> invScale(core::reciprocal(scale.X),core::reciprocal(scale.Y),core::reciprocal(scale.Z));
881 
882  f64 Y = -asin(core::clamp(mat[2]*invScale.X, -1.0, 1.0));
883  const f64 C = cos(Y);
884  Y *= RADTODEG64;
885 
886  f64 rotx, roty, X, Z;
887 
888  if (!core::iszero(C))
889  {
890  const f64 invC = core::reciprocal(C);
891  rotx = mat[10] * invC * invScale.Z;
892  roty = mat[6] * invC * invScale.Y;
893  X = atan2( roty, rotx ) * RADTODEG64;
894  rotx = mat[0] * invC * invScale.X;
895  roty = mat[1] * invC * invScale.X;
896  Z = atan2( roty, rotx ) * RADTODEG64;
897  }
898  else
899  {
900  X = 0.0;
901  rotx = mat[5] * invScale.Y;
902  roty = -mat[4] * invScale.Y;
903  Z = atan2( roty, rotx ) * RADTODEG64;
904  }
905 
906  // fix values that get below zero
907  if (X < 0.0) X += 360.0;
908  if (Y < 0.0) Y += 360.0;
909  if (Z < 0.0) Z += 360.0;
910 
911  return vector3d<T>((T)X,(T)Y,(T)Z);
912  }
913 
914 
916  template <class T>
918  {
919  f64 cr = cos( rotation.X );
920  f64 sr = sin( rotation.X );
921  f64 cp = cos( rotation.Y );
922  f64 sp = sin( rotation.Y );
923  f64 cy = cos( rotation.Z );
924  f64 sy = sin( rotation.Z );
925 
926  M[0] = (T)( cp*cy );
927  M[4] = (T)( cp*sy );
928  M[8] = (T)( -sp );
929 
930  f64 srsp = sr*sp;
931  f64 crsp = cr*sp;
932 
933  M[1] = (T)( srsp*cy-cr*sy );
934  M[5] = (T)( srsp*sy+cr*cy );
935  M[9] = (T)( sr*cp );
936 
937  M[2] = (T)( crsp*cy+sr*sy );
938  M[6] = (T)( crsp*sy-sr*cy );
939  M[10] = (T)( cr*cp );
940 #if defined ( USE_MATRIX_TEST )
941  definitelyIdentityMatrix=false;
942 #endif
943  return *this;
944  }
945 
947  template <class T>
948  inline CMatrix4<T>& CMatrix4<T>::setRotationAxisRadians( const T& angle, const vector3d<T>& axis )
949  {
950  const f64 c = cos(angle);
951  const f64 s = sin(angle);
952  const f64 t = 1.0 - c;
953 
954  const f64 tx = t * axis.X;
955  const f64 ty = t * axis.Y;
956  const f64 tz = t * axis.Z;
957 
958  const f64 sx = s * axis.X;
959  const f64 sy = s * axis.Y;
960  const f64 sz = s * axis.Z;
961 
962  M[0] = (T)(tx * axis.X + c);
963  M[1] = (T)(tx * axis.Y + sz);
964  M[2] = (T)(tx * axis.Z - sy);
965 
966  M[4] = (T)(ty * axis.X - sz);
967  M[5] = (T)(ty * axis.Y + c);
968  M[6] = (T)(ty * axis.Z + sx);
969 
970  M[8] = (T)(tz * axis.X + sy);
971  M[9] = (T)(tz * axis.Y - sx);
972  M[10] = (T)(tz * axis.Z + c);
973 
974 #if defined ( USE_MATRIX_TEST )
975  definitelyIdentityMatrix=false;
976 #endif
977  return *this;
978  }
979 
980 
983  template <class T>
985  {
986  memset(M, 0, 16*sizeof(T));
987  M[0] = M[5] = M[10] = M[15] = (T)1;
988 #if defined ( USE_MATRIX_TEST )
989  definitelyIdentityMatrix=true;
990 #endif
991  return *this;
992  }
993 
994 
995  /*
996  check identity with epsilon
997  solve floating range problems..
998  */
999  template <class T>
1000  inline bool CMatrix4<T>::isIdentity() const
1001  {
1002 #if defined ( USE_MATRIX_TEST )
1003  if (definitelyIdentityMatrix)
1004  return true;
1005 #endif
1006  if (!core::equals( M[12], (T)0 ) || !core::equals( M[13], (T)0 ) || !core::equals( M[14], (T)0 ) || !core::equals( M[15], (T)1 ))
1007  return false;
1008 
1009  if (!core::equals( M[ 0], (T)1 ) || !core::equals( M[ 1], (T)0 ) || !core::equals( M[ 2], (T)0 ) || !core::equals( M[ 3], (T)0 ))
1010  return false;
1011 
1012  if (!core::equals( M[ 4], (T)0 ) || !core::equals( M[ 5], (T)1 ) || !core::equals( M[ 6], (T)0 ) || !core::equals( M[ 7], (T)0 ))
1013  return false;
1014 
1015  if (!core::equals( M[ 8], (T)0 ) || !core::equals( M[ 9], (T)0 ) || !core::equals( M[10], (T)1 ) || !core::equals( M[11], (T)0 ))
1016  return false;
1017 /*
1018  if (!core::equals( M[ 0], (T)1 ) ||
1019  !core::equals( M[ 5], (T)1 ) ||
1020  !core::equals( M[10], (T)1 ) ||
1021  !core::equals( M[15], (T)1 ))
1022  return false;
1023 
1024  for (s32 i=0; i<4; ++i)
1025  for (s32 j=0; j<4; ++j)
1026  if ((j != i) && (!iszero((*this)(i,j))))
1027  return false;
1028 */
1029 #if defined ( USE_MATRIX_TEST )
1030  definitelyIdentityMatrix=true;
1031 #endif
1032  return true;
1033  }
1034 
1035 
1036  /* Check orthogonality of matrix. */
1037  template <class T>
1038  inline bool CMatrix4<T>::isOrthogonal() const
1039  {
1040  T dp=M[0] * M[4 ] + M[1] * M[5 ] + M[2 ] * M[6 ] + M[3 ] * M[7 ];
1041  if (!iszero(dp))
1042  return false;
1043  dp = M[0] * M[8 ] + M[1] * M[9 ] + M[2 ] * M[10] + M[3 ] * M[11];
1044  if (!iszero(dp))
1045  return false;
1046  dp = M[0] * M[12] + M[1] * M[13] + M[2 ] * M[14] + M[3 ] * M[15];
1047  if (!iszero(dp))
1048  return false;
1049  dp = M[4] * M[8 ] + M[5] * M[9 ] + M[6 ] * M[10] + M[7 ] * M[11];
1050  if (!iszero(dp))
1051  return false;
1052  dp = M[4] * M[12] + M[5] * M[13] + M[6 ] * M[14] + M[7 ] * M[15];
1053  if (!iszero(dp))
1054  return false;
1055  dp = M[8] * M[12] + M[9] * M[13] + M[10] * M[14] + M[11] * M[15];
1056  return (iszero(dp));
1057  }
1058 
1059 
1060  /*
1061  doesn't solve floating range problems..
1062  but takes care on +/- 0 on translation because we are changing it..
1063  reducing floating point branches
1064  but it needs the floats in memory..
1065  */
1066  template <class T>
1068  {
1069 #if defined ( USE_MATRIX_TEST )
1070  if (definitelyIdentityMatrix)
1071  return true;
1072 #endif
1073  if(IR(M[0])!=F32_VALUE_1) return false;
1074  if(IR(M[1])!=0) return false;
1075  if(IR(M[2])!=0) return false;
1076  if(IR(M[3])!=0) return false;
1077 
1078  if(IR(M[4])!=0) return false;
1079  if(IR(M[5])!=F32_VALUE_1) return false;
1080  if(IR(M[6])!=0) return false;
1081  if(IR(M[7])!=0) return false;
1082 
1083  if(IR(M[8])!=0) return false;
1084  if(IR(M[9])!=0) return false;
1085  if(IR(M[10])!=F32_VALUE_1) return false;
1086  if(IR(M[11])!=0) return false;
1087 
1088  if(IR(M[12])!=0) return false;
1089  if(IR(M[13])!=0) return false;
1090  if(IR(M[13])!=0) return false;
1091  if(IR(M[15])!=F32_VALUE_1) return false;
1092 
1093 #if defined ( USE_MATRIX_TEST )
1094  definitelyIdentityMatrix=true;
1095 #endif
1096  return true;
1097  }
1098 
1099 
1100  template <class T>
1101  inline void CMatrix4<T>::rotateVect( vector3df& vect ) const
1102  {
1103  vector3df tmp = vect;
1104  vect.X = tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8];
1105  vect.Y = tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9];
1106  vect.Z = tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10];
1107  }
1108 
1110  template <class T>
1111  inline void CMatrix4<T>::rotateVect(core::vector3df& out, const core::vector3df& in) const
1112  {
1113  out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
1114  out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
1115  out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
1116  }
1117 
1119  template <class T>
1120  inline void CMatrix4<T>::rotateVect(T *out, const core::vector3df& in) const
1121  {
1122  out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
1123  out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
1124  out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
1125  }
1126 
1127  template <class T>
1128  inline void CMatrix4<T>::inverseRotateVect( vector3df& vect ) const
1129  {
1130  vector3df tmp = vect;
1131  vect.X = tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2];
1132  vect.Y = tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6];
1133  vect.Z = tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10];
1134  }
1135 
1136  template <class T>
1137  inline void CMatrix4<T>::transformVect( vector3df& vect) const
1138  {
1139  f32 vector[3];
1140 
1141  vector[0] = vect.X*M[0] + vect.Y*M[4] + vect.Z*M[8] + M[12];
1142  vector[1] = vect.X*M[1] + vect.Y*M[5] + vect.Z*M[9] + M[13];
1143  vector[2] = vect.X*M[2] + vect.Y*M[6] + vect.Z*M[10] + M[14];
1144 
1145  vect.X = vector[0];
1146  vect.Y = vector[1];
1147  vect.Z = vector[2];
1148  }
1149 
1150  template <class T>
1151  inline void CMatrix4<T>::transformVect( vector3df& out, const vector3df& in) const
1152  {
1153  out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
1154  out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
1155  out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
1156  }
1157 
1158 
1159  template <class T>
1160  inline void CMatrix4<T>::transformVect(T *out, const core::vector3df &in) const
1161  {
1162  out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
1163  out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
1164  out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
1165  out[3] = in.X*M[3] + in.Y*M[7] + in.Z*M[11] + M[15];
1166  }
1167 
1168  template <class T>
1169  inline void CMatrix4<T>::transformVec3(T *out, const T * in) const
1170  {
1171  out[0] = in[0]*M[0] + in[1]*M[4] + in[2]*M[8] + M[12];
1172  out[1] = in[0]*M[1] + in[1]*M[5] + in[2]*M[9] + M[13];
1173  out[2] = in[0]*M[2] + in[1]*M[6] + in[2]*M[10] + M[14];
1174  }
1175 
1176 
1178  template <class T>
1180  {
1181  vector3df member;
1182  // Transform the plane member point, i.e. rotate, translate and scale it.
1183  transformVect(member, plane.getMemberPoint());
1184 
1185  // Transform the normal by the transposed inverse of the matrix
1186  CMatrix4<T> transposedInverse(*this, EM4CONST_INVERSE_TRANSPOSED);
1187  vector3df normal = plane.Normal;
1188  transposedInverse.transformVect(normal);
1189 
1190  plane.setPlane(member, normal);
1191  }
1192 
1194  template <class T>
1196  {
1197  out = in;
1198  transformPlane( out );
1199  }
1200 
1202  template <class T>
1204  {
1205 #if defined ( USE_MATRIX_TEST )
1206  if (isIdentity())
1207  return;
1208 #endif
1209 
1210  transformVect(box.MinEdge);
1211  transformVect(box.MaxEdge);
1212  box.repair();
1213  }
1214 
1216  template <class T>
1218  {
1219 #if defined ( USE_MATRIX_TEST )
1220  if (isIdentity())
1221  return;
1222 #endif
1223 
1224  const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z};
1225  const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z};
1226 
1227  f32 Bmin[3];
1228  f32 Bmax[3];
1229 
1230  Bmin[0] = Bmax[0] = M[12];
1231  Bmin[1] = Bmax[1] = M[13];
1232  Bmin[2] = Bmax[2] = M[14];
1233 
1234  const CMatrix4<T> &m = *this;
1235 
1236  for (u32 i = 0; i < 3; ++i)
1237  {
1238  for (u32 j = 0; j < 3; ++j)
1239  {
1240  const f32 a = m(j,i) * Amin[j];
1241  const f32 b = m(j,i) * Amax[j];
1242 
1243  if (a < b)
1244  {
1245  Bmin[i] += a;
1246  Bmax[i] += b;
1247  }
1248  else
1249  {
1250  Bmin[i] += b;
1251  Bmax[i] += a;
1252  }
1253  }
1254  }
1255 
1256  box.MinEdge.X = Bmin[0];
1257  box.MinEdge.Y = Bmin[1];
1258  box.MinEdge.Z = Bmin[2];
1259 
1260  box.MaxEdge.X = Bmax[0];
1261  box.MaxEdge.Y = Bmax[1];
1262  box.MaxEdge.Z = Bmax[2];
1263  }
1264 
1265 
1267  template <class T>
1268  inline void CMatrix4<T>::multiplyWith1x4Matrix(T* matrix) const
1269  {
1270  /*
1271  0 1 2 3
1272  4 5 6 7
1273  8 9 10 11
1274  12 13 14 15
1275  */
1276 
1277  T mat[4];
1278  mat[0] = matrix[0];
1279  mat[1] = matrix[1];
1280  mat[2] = matrix[2];
1281  mat[3] = matrix[3];
1282 
1283  matrix[0] = M[0]*mat[0] + M[4]*mat[1] + M[8]*mat[2] + M[12]*mat[3];
1284  matrix[1] = M[1]*mat[0] + M[5]*mat[1] + M[9]*mat[2] + M[13]*mat[3];
1285  matrix[2] = M[2]*mat[0] + M[6]*mat[1] + M[10]*mat[2] + M[14]*mat[3];
1286  matrix[3] = M[3]*mat[0] + M[7]*mat[1] + M[11]*mat[2] + M[15]*mat[3];
1287  }
1288 
1289  template <class T>
1291  {
1292  vect.X = vect.X-M[12];
1293  vect.Y = vect.Y-M[13];
1294  vect.Z = vect.Z-M[14];
1295  }
1296 
1297  template <class T>
1298  inline void CMatrix4<T>::translateVect( vector3df& vect ) const
1299  {
1300  vect.X = vect.X+M[12];
1301  vect.Y = vect.Y+M[13];
1302  vect.Z = vect.Z+M[14];
1303  }
1304 
1305 
1306  template <class T>
1307  inline bool CMatrix4<T>::getInverse(CMatrix4<T>& out) const
1308  {
1312 
1313 #if defined ( USE_MATRIX_TEST )
1314  if ( this->isIdentity() )
1315  {
1316  out=*this;
1317  return true;
1318  }
1319 #endif
1320  const CMatrix4<T> &m = *this;
1321 
1322  f32 d = (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) -
1323  (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
1324  (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)) +
1325  (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) -
1326  (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
1327  (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0));
1328 
1329  if( core::iszero ( d, FLT_MIN ) )
1330  return false;
1331 
1332  d = core::reciprocal ( d );
1333 
1334  out(0, 0) = d * (m(1, 1) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) +
1335  m(1, 2) * (m(2, 3) * m(3, 1) - m(2, 1) * m(3, 3)) +
1336  m(1, 3) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)));
1337  out(0, 1) = d * (m(2, 1) * (m(0, 2) * m(3, 3) - m(0, 3) * m(3, 2)) +
1338  m(2, 2) * (m(0, 3) * m(3, 1) - m(0, 1) * m(3, 3)) +
1339  m(2, 3) * (m(0, 1) * m(3, 2) - m(0, 2) * m(3, 1)));
1340  out(0, 2) = d * (m(3, 1) * (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) +
1341  m(3, 2) * (m(0, 3) * m(1, 1) - m(0, 1) * m(1, 3)) +
1342  m(3, 3) * (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)));
1343  out(0, 3) = d * (m(0, 1) * (m(1, 3) * m(2, 2) - m(1, 2) * m(2, 3)) +
1344  m(0, 2) * (m(1, 1) * m(2, 3) - m(1, 3) * m(2, 1)) +
1345  m(0, 3) * (m(1, 2) * m(2, 1) - m(1, 1) * m(2, 2)));
1346  out(1, 0) = d * (m(1, 2) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) +
1347  m(1, 3) * (m(2, 2) * m(3, 0) - m(2, 0) * m(3, 2)) +
1348  m(1, 0) * (m(2, 3) * m(3, 2) - m(2, 2) * m(3, 3)));
1349  out(1, 1) = d * (m(2, 2) * (m(0, 0) * m(3, 3) - m(0, 3) * m(3, 0)) +
1350  m(2, 3) * (m(0, 2) * m(3, 0) - m(0, 0) * m(3, 2)) +
1351  m(2, 0) * (m(0, 3) * m(3, 2) - m(0, 2) * m(3, 3)));
1352  out(1, 2) = d * (m(3, 2) * (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) +
1353  m(3, 3) * (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2)) +
1354  m(3, 0) * (m(0, 3) * m(1, 2) - m(0, 2) * m(1, 3)));
1355  out(1, 3) = d * (m(0, 2) * (m(1, 3) * m(2, 0) - m(1, 0) * m(2, 3)) +
1356  m(0, 3) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
1357  m(0, 0) * (m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2)));
1358  out(2, 0) = d * (m(1, 3) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)) +
1359  m(1, 0) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
1360  m(1, 1) * (m(2, 3) * m(3, 0) - m(2, 0) * m(3, 3)));
1361  out(2, 1) = d * (m(2, 3) * (m(0, 0) * m(3, 1) - m(0, 1) * m(3, 0)) +
1362  m(2, 0) * (m(0, 1) * m(3, 3) - m(0, 3) * m(3, 1)) +
1363  m(2, 1) * (m(0, 3) * m(3, 0) - m(0, 0) * m(3, 3)));
1364  out(2, 2) = d * (m(3, 3) * (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) +
1365  m(3, 0) * (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) +
1366  m(3, 1) * (m(0, 3) * m(1, 0) - m(0, 0) * m(1, 3)));
1367  out(2, 3) = d * (m(0, 3) * (m(1, 1) * m(2, 0) - m(1, 0) * m(2, 1)) +
1368  m(0, 0) * (m(1, 3) * m(2, 1) - m(1, 1) * m(2, 3)) +
1369  m(0, 1) * (m(1, 0) * m(2, 3) - m(1, 3) * m(2, 0)));
1370  out(3, 0) = d * (m(1, 0) * (m(2, 2) * m(3, 1) - m(2, 1) * m(3, 2)) +
1371  m(1, 1) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
1372  m(1, 2) * (m(2, 1) * m(3, 0) - m(2, 0) * m(3, 1)));
1373  out(3, 1) = d * (m(2, 0) * (m(0, 2) * m(3, 1) - m(0, 1) * m(3, 2)) +
1374  m(2, 1) * (m(0, 0) * m(3, 2) - m(0, 2) * m(3, 0)) +
1375  m(2, 2) * (m(0, 1) * m(3, 0) - m(0, 0) * m(3, 1)));
1376  out(3, 2) = d * (m(3, 0) * (m(0, 2) * m(1, 1) - m(0, 1) * m(1, 2)) +
1377  m(3, 1) * (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) +
1378  m(3, 2) * (m(0, 1) * m(1, 0) - m(0, 0) * m(1, 1)));
1379  out(3, 3) = d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) +
1380  m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) +
1381  m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0)));
1382 
1383 #if defined ( USE_MATRIX_TEST )
1384  out.definitelyIdentityMatrix = definitelyIdentityMatrix;
1385 #endif
1386  return true;
1387  }
1388 
1389 
1392  template <class T>
1394  {
1395  out.M[0 ] = M[0];
1396  out.M[1 ] = M[4];
1397  out.M[2 ] = M[8];
1398  out.M[3 ] = 0;
1399 
1400  out.M[4 ] = M[1];
1401  out.M[5 ] = M[5];
1402  out.M[6 ] = M[9];
1403  out.M[7 ] = 0;
1404 
1405  out.M[8 ] = M[2];
1406  out.M[9 ] = M[6];
1407  out.M[10] = M[10];
1408  out.M[11] = 0;
1409 
1410  out.M[12] = (T)-(M[12]*M[0] + M[13]*M[1] + M[14]*M[2]);
1411  out.M[13] = (T)-(M[12]*M[4] + M[13]*M[5] + M[14]*M[6]);
1412  out.M[14] = (T)-(M[12]*M[8] + M[13]*M[9] + M[14]*M[10]);
1413  out.M[15] = 1;
1414 
1415 #if defined ( USE_MATRIX_TEST )
1416  out.definitelyIdentityMatrix = definitelyIdentityMatrix;
1417 #endif
1418  return true;
1419  }
1420 
1423  template <class T>
1425  {
1426 #if defined ( USE_MATRIX_TEST )
1427  if (definitelyIdentityMatrix)
1428  return true;
1429 #endif
1430  CMatrix4<T> temp ( EM4CONST_NOTHING );
1431 
1432  if (getInverse(temp))
1433  {
1434  *this = temp;
1435  return true;
1436  }
1437 
1438  return false;
1439  }
1440 
1441 
1442  template <class T>
1444  {
1445  if (this==&other)
1446  return *this;
1447  memcpy(M, other.M, 16*sizeof(T));
1448 #if defined ( USE_MATRIX_TEST )
1449  definitelyIdentityMatrix=other.definitelyIdentityMatrix;
1450 #endif
1451  return *this;
1452  }
1453 
1454 
1455  template <class T>
1456  inline CMatrix4<T>& CMatrix4<T>::operator=(const T& scalar)
1457  {
1458  for (s32 i = 0; i < 16; ++i)
1459  M[i]=scalar;
1460 
1461 #if defined ( USE_MATRIX_TEST )
1462  definitelyIdentityMatrix=false;
1463 #endif
1464  return *this;
1465  }
1466 
1467 
1468  template <class T>
1469  inline bool CMatrix4<T>::operator==(const CMatrix4<T> &other) const
1470  {
1471 #if defined ( USE_MATRIX_TEST )
1472  if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
1473  return true;
1474 #endif
1475  for (s32 i = 0; i < 16; ++i)
1476  if (M[i] != other.M[i])
1477  return false;
1478 
1479  return true;
1480  }
1481 
1482 
1483  template <class T>
1484  inline bool CMatrix4<T>::operator!=(const CMatrix4<T> &other) const
1485  {
1486  return !(*this == other);
1487  }
1488 
1489 
1490  // Builds a right-handed perspective projection matrix based on a field of view
1491  template <class T>
1493  f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
1494  {
1495  const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
1496  _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
1497  const T w = static_cast<T>(h / aspectRatio);
1498 
1499  _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1500  M[0] = w;
1501  M[1] = 0;
1502  M[2] = 0;
1503  M[3] = 0;
1504 
1505  M[4] = 0;
1506  M[5] = (T)h;
1507  M[6] = 0;
1508  M[7] = 0;
1509 
1510  M[8] = 0;
1511  M[9] = 0;
1512  M[10] = (T)(zFar/(zNear-zFar)); // DirectX version
1513 // M[10] = (T)(zFar+zNear/(zNear-zFar)); // OpenGL version
1514  M[11] = -1;
1515 
1516  M[12] = 0;
1517  M[13] = 0;
1518  M[14] = (T)(zNear*zFar/(zNear-zFar)); // DirectX version
1519 // M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar)); // OpenGL version
1520  M[15] = 0;
1521 
1522 #if defined ( USE_MATRIX_TEST )
1523  definitelyIdentityMatrix=false;
1524 #endif
1525  return *this;
1526  }
1527 
1528 
1529  // Builds a left-handed perspective projection matrix based on a field of view
1530  template <class T>
1532  f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
1533  {
1534  const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
1535  _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
1536  const T w = static_cast<T>(h / aspectRatio);
1537 
1538  _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1539  M[0] = w;
1540  M[1] = 0;
1541  M[2] = 0;
1542  M[3] = 0;
1543 
1544  M[4] = 0;
1545  M[5] = (T)h;
1546  M[6] = 0;
1547  M[7] = 0;
1548 
1549  M[8] = 0;
1550  M[9] = 0;
1551  M[10] = (T)(zFar/(zFar-zNear));
1552  M[11] = 1;
1553 
1554  M[12] = 0;
1555  M[13] = 0;
1556  M[14] = (T)(-zNear*zFar/(zFar-zNear));
1557  M[15] = 0;
1558 
1559 #if defined ( USE_MATRIX_TEST )
1560  definitelyIdentityMatrix=false;
1561 #endif
1562  return *this;
1563  }
1564 
1565 
1566  // Builds a left-handed perspective projection matrix based on a field of view, with far plane culling at infinity
1567  template <class T>
1569  f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon)
1570  {
1571  const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
1572  _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
1573  const T w = static_cast<T>(h / aspectRatio);
1574 
1575  M[0] = w;
1576  M[1] = 0;
1577  M[2] = 0;
1578  M[3] = 0;
1579 
1580  M[4] = 0;
1581  M[5] = (T)h;
1582  M[6] = 0;
1583  M[7] = 0;
1584 
1585  M[8] = 0;
1586  M[9] = 0;
1587  M[10] = (T)(1.f-epsilon);
1588  M[11] = 1;
1589 
1590  M[12] = 0;
1591  M[13] = 0;
1592  M[14] = (T)(zNear*(epsilon-1.f));
1593  M[15] = 0;
1594 
1595 #if defined ( USE_MATRIX_TEST )
1596  definitelyIdentityMatrix=false;
1597 #endif
1598  return *this;
1599  }
1600 
1601 
1602  // Builds a left-handed orthogonal projection matrix.
1603  template <class T>
1605  f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
1606  {
1607  _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1608  _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1609  _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1610  M[0] = (T)(2/widthOfViewVolume);
1611  M[1] = 0;
1612  M[2] = 0;
1613  M[3] = 0;
1614 
1615  M[4] = 0;
1616  M[5] = (T)(2/heightOfViewVolume);
1617  M[6] = 0;
1618  M[7] = 0;
1619 
1620  M[8] = 0;
1621  M[9] = 0;
1622  M[10] = (T)(1/(zFar-zNear));
1623  M[11] = 0;
1624 
1625  M[12] = 0;
1626  M[13] = 0;
1627  M[14] = (T)(zNear/(zNear-zFar));
1628  M[15] = 1;
1629 
1630 #if defined ( USE_MATRIX_TEST )
1631  definitelyIdentityMatrix=false;
1632 #endif
1633  return *this;
1634  }
1635 
1636 
1637  // Builds a right-handed orthogonal projection matrix.
1638  template <class T>
1640  f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
1641  {
1642  _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1643  _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1644  _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1645  M[0] = (T)(2/widthOfViewVolume);
1646  M[1] = 0;
1647  M[2] = 0;
1648  M[3] = 0;
1649 
1650  M[4] = 0;
1651  M[5] = (T)(2/heightOfViewVolume);
1652  M[6] = 0;
1653  M[7] = 0;
1654 
1655  M[8] = 0;
1656  M[9] = 0;
1657  M[10] = (T)(1/(zNear-zFar));
1658  M[11] = 0;
1659 
1660  M[12] = 0;
1661  M[13] = 0;
1662  M[14] = (T)(zNear/(zNear-zFar));
1663  M[15] = 1;
1664 
1665 #if defined ( USE_MATRIX_TEST )
1666  definitelyIdentityMatrix=false;
1667 #endif
1668  return *this;
1669  }
1670 
1671 
1672  // Builds a right-handed perspective projection matrix.
1673  template <class T>
1675  f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
1676  {
1677  _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1678  _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1679  _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1680  M[0] = (T)(2*zNear/widthOfViewVolume);
1681  M[1] = 0;
1682  M[2] = 0;
1683  M[3] = 0;
1684 
1685  M[4] = 0;
1686  M[5] = (T)(2*zNear/heightOfViewVolume);
1687  M[6] = 0;
1688  M[7] = 0;
1689 
1690  M[8] = 0;
1691  M[9] = 0;
1692  M[10] = (T)(zFar/(zNear-zFar));
1693  M[11] = -1;
1694 
1695  M[12] = 0;
1696  M[13] = 0;
1697  M[14] = (T)(zNear*zFar/(zNear-zFar));
1698  M[15] = 0;
1699 
1700 #if defined ( USE_MATRIX_TEST )
1701  definitelyIdentityMatrix=false;
1702 #endif
1703  return *this;
1704  }
1705 
1706 
1707  // Builds a left-handed perspective projection matrix.
1708  template <class T>
1710  f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
1711  {
1712  _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1713  _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1714  _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1715  M[0] = (T)(2*zNear/widthOfViewVolume);
1716  M[1] = 0;
1717  M[2] = 0;
1718  M[3] = 0;
1719 
1720  M[4] = 0;
1721  M[5] = (T)(2*zNear/heightOfViewVolume);
1722  M[6] = 0;
1723  M[7] = 0;
1724 
1725  M[8] = 0;
1726  M[9] = 0;
1727  M[10] = (T)(zFar/(zFar-zNear));
1728  M[11] = 1;
1729 
1730  M[12] = 0;
1731  M[13] = 0;
1732  M[14] = (T)(zNear*zFar/(zNear-zFar));
1733  M[15] = 0;
1734 #if defined ( USE_MATRIX_TEST )
1735  definitelyIdentityMatrix=false;
1736 #endif
1737  return *this;
1738  }
1739 
1740 
1741  // Builds a matrix that flattens geometry into a plane.
1742  template <class T>
1744  {
1745  plane.Normal.normalize();
1746  const f32 d = plane.Normal.dotProduct(light);
1747 
1748  M[ 0] = (T)(-plane.Normal.X * light.X + d);
1749  M[ 1] = (T)(-plane.Normal.X * light.Y);
1750  M[ 2] = (T)(-plane.Normal.X * light.Z);
1751  M[ 3] = (T)(-plane.Normal.X * point);
1752 
1753  M[ 4] = (T)(-plane.Normal.Y * light.X);
1754  M[ 5] = (T)(-plane.Normal.Y * light.Y + d);
1755  M[ 6] = (T)(-plane.Normal.Y * light.Z);
1756  M[ 7] = (T)(-plane.Normal.Y * point);
1757 
1758  M[ 8] = (T)(-plane.Normal.Z * light.X);
1759  M[ 9] = (T)(-plane.Normal.Z * light.Y);
1760  M[10] = (T)(-plane.Normal.Z * light.Z + d);
1761  M[11] = (T)(-plane.Normal.Z * point);
1762 
1763  M[12] = (T)(-plane.D * light.X);
1764  M[13] = (T)(-plane.D * light.Y);
1765  M[14] = (T)(-plane.D * light.Z);
1766  M[15] = (T)(-plane.D * point + d);
1767 #if defined ( USE_MATRIX_TEST )
1768  definitelyIdentityMatrix=false;
1769 #endif
1770  return *this;
1771  }
1772 
1773  // Builds a left-handed look-at matrix.
1774  template <class T>
1776  const vector3df& position,
1777  const vector3df& target,
1778  const vector3df& upVector)
1779  {
1780  vector3df zaxis = target - position;
1781  zaxis.normalize();
1782 
1783  vector3df xaxis = upVector.crossProduct(zaxis);
1784  xaxis.normalize();
1785 
1786  vector3df yaxis = zaxis.crossProduct(xaxis);
1787 
1788  M[0] = (T)xaxis.X;
1789  M[1] = (T)yaxis.X;
1790  M[2] = (T)zaxis.X;
1791  M[3] = 0;
1792 
1793  M[4] = (T)xaxis.Y;
1794  M[5] = (T)yaxis.Y;
1795  M[6] = (T)zaxis.Y;
1796  M[7] = 0;
1797 
1798  M[8] = (T)xaxis.Z;
1799  M[9] = (T)yaxis.Z;
1800  M[10] = (T)zaxis.Z;
1801  M[11] = 0;
1802 
1803  M[12] = (T)-xaxis.dotProduct(position);
1804  M[13] = (T)-yaxis.dotProduct(position);
1805  M[14] = (T)-zaxis.dotProduct(position);
1806  M[15] = 1;
1807 #if defined ( USE_MATRIX_TEST )
1808  definitelyIdentityMatrix=false;
1809 #endif
1810  return *this;
1811  }
1812 
1813 
1814  // Builds a right-handed look-at matrix.
1815  template <class T>
1817  const vector3df& position,
1818  const vector3df& target,
1819  const vector3df& upVector)
1820  {
1821  vector3df zaxis = position - target;
1822  zaxis.normalize();
1823 
1824  vector3df xaxis = upVector.crossProduct(zaxis);
1825  xaxis.normalize();
1826 
1827  vector3df yaxis = zaxis.crossProduct(xaxis);
1828 
1829  M[0] = (T)xaxis.X;
1830  M[1] = (T)yaxis.X;
1831  M[2] = (T)zaxis.X;
1832  M[3] = 0;
1833 
1834  M[4] = (T)xaxis.Y;
1835  M[5] = (T)yaxis.Y;
1836  M[6] = (T)zaxis.Y;
1837  M[7] = 0;
1838 
1839  M[8] = (T)xaxis.Z;
1840  M[9] = (T)yaxis.Z;
1841  M[10] = (T)zaxis.Z;
1842  M[11] = 0;
1843 
1844  M[12] = (T)-xaxis.dotProduct(position);
1845  M[13] = (T)-yaxis.dotProduct(position);
1846  M[14] = (T)-zaxis.dotProduct(position);
1847  M[15] = 1;
1848 #if defined ( USE_MATRIX_TEST )
1849  definitelyIdentityMatrix=false;
1850 #endif
1851  return *this;
1852  }
1853 
1854 
1855  // creates a new matrix as interpolated matrix from this and the passed one.
1856  template <class T>
1858  {
1859  CMatrix4<T> mat ( EM4CONST_NOTHING );
1860 
1861  for (u32 i=0; i < 16; i += 4)
1862  {
1863  mat.M[i+0] = (T)(M[i+0] + ( b.M[i+0] - M[i+0] ) * time);
1864  mat.M[i+1] = (T)(M[i+1] + ( b.M[i+1] - M[i+1] ) * time);
1865  mat.M[i+2] = (T)(M[i+2] + ( b.M[i+2] - M[i+2] ) * time);
1866  mat.M[i+3] = (T)(M[i+3] + ( b.M[i+3] - M[i+3] ) * time);
1867  }
1868  return mat;
1869  }
1870 
1871 
1872  // returns transposed matrix
1873  template <class T>
1875  {
1876  CMatrix4<T> t ( EM4CONST_NOTHING );
1877  getTransposed ( t );
1878  return t;
1879  }
1880 
1881 
1882  // returns transposed matrix
1883  template <class T>
1884  inline void CMatrix4<T>::getTransposed( CMatrix4<T>& o ) const
1885  {
1886  o[ 0] = M[ 0];
1887  o[ 1] = M[ 4];
1888  o[ 2] = M[ 8];
1889  o[ 3] = M[12];
1890 
1891  o[ 4] = M[ 1];
1892  o[ 5] = M[ 5];
1893  o[ 6] = M[ 9];
1894  o[ 7] = M[13];
1895 
1896  o[ 8] = M[ 2];
1897  o[ 9] = M[ 6];
1898  o[10] = M[10];
1899  o[11] = M[14];
1900 
1901  o[12] = M[ 3];
1902  o[13] = M[ 7];
1903  o[14] = M[11];
1904  o[15] = M[15];
1905 #if defined ( USE_MATRIX_TEST )
1906  o.definitelyIdentityMatrix=definitelyIdentityMatrix;
1907 #endif
1908  }
1909 
1910 
1911  // used to scale <-1,-1><1,1> to viewport
1912  template <class T>
1914  {
1915  const f32 scaleX = (viewport.getWidth() - 0.75f ) * 0.5f;
1916  const f32 scaleY = -(viewport.getHeight() - 0.75f ) * 0.5f;
1917 
1918  const f32 dx = -0.5f + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) * 0.5f );
1919  const f32 dy = -0.5f + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) * 0.5f );
1920 
1921  makeIdentity();
1922  M[12] = (T)dx;
1923  M[13] = (T)dy;
1924  return setScale(core::vector3d<T>((T)scaleX, (T)scaleY, (T)zScale));
1925  }
1926 
1928 
1933  template <class T>
1935  {
1936  // unit vectors
1937  core::vector3df f(from);
1938  core::vector3df t(to);
1939  f.normalize();
1940  t.normalize();
1941 
1942  // axis multiplication by sin
1943  core::vector3df vs(t.crossProduct(f));
1944 
1945  // axis of rotation
1946  core::vector3df v(vs);
1947  v.normalize();
1948 
1949  // cosinus angle
1950  T ca = f.dotProduct(t);
1951 
1952  core::vector3df vt(v * (1 - ca));
1953 
1954  M[0] = vt.X * v.X + ca;
1955  M[5] = vt.Y * v.Y + ca;
1956  M[10] = vt.Z * v.Z + ca;
1957 
1958  vt.X *= v.Y;
1959  vt.Z *= v.X;
1960  vt.Y *= v.Z;
1961 
1962  M[1] = vt.X - vs.Z;
1963  M[2] = vt.Z + vs.Y;
1964  M[3] = 0;
1965 
1966  M[4] = vt.X + vs.Z;
1967  M[6] = vt.Y - vs.X;
1968  M[7] = 0;
1969 
1970  M[8] = vt.Z - vs.Y;
1971  M[9] = vt.Y + vs.X;
1972  M[11] = 0;
1973 
1974  M[12] = 0;
1975  M[13] = 0;
1976  M[14] = 0;
1977  M[15] = 1;
1978 
1979  return *this;
1980  }
1981 
1983 
1989  template <class T>
1991  const core::vector3df& camPos,
1992  const core::vector3df& center,
1993  const core::vector3df& translation,
1994  const core::vector3df& axis,
1995  const core::vector3df& from)
1996  {
1997  // axis of rotation
1998  core::vector3df up = axis;
1999  up.normalize();
2000  const core::vector3df forward = (camPos - center).normalize();
2001  const core::vector3df right = up.crossProduct(forward).normalize();
2002 
2003  // correct look vector
2004  const core::vector3df look = right.crossProduct(up);
2005 
2006  // rotate from to
2007  // axis multiplication by sin
2008  const core::vector3df vs = look.crossProduct(from);
2009 
2010  // cosinus angle
2011  const f32 ca = from.dotProduct(look);
2012 
2013  core::vector3df vt(up * (1.f - ca));
2014 
2015  M[0] = static_cast<T>(vt.X * up.X + ca);
2016  M[5] = static_cast<T>(vt.Y * up.Y + ca);
2017  M[10] = static_cast<T>(vt.Z * up.Z + ca);
2018 
2019  vt.X *= up.Y;
2020  vt.Z *= up.X;
2021  vt.Y *= up.Z;
2022 
2023  M[1] = static_cast<T>(vt.X - vs.Z);
2024  M[2] = static_cast<T>(vt.Z + vs.Y);
2025  M[3] = 0;
2026 
2027  M[4] = static_cast<T>(vt.X + vs.Z);
2028  M[6] = static_cast<T>(vt.Y - vs.X);
2029  M[7] = 0;
2030 
2031  M[8] = static_cast<T>(vt.Z - vs.Y);
2032  M[9] = static_cast<T>(vt.Y + vs.X);
2033  M[11] = 0;
2034 
2035  setRotationCenter(center, translation);
2036  }
2037 
2038 
2040  template <class T>
2041  inline void CMatrix4<T>::setRotationCenter(const core::vector3df& center, const core::vector3df& translation)
2042  {
2043  M[12] = -M[0]*center.X - M[4]*center.Y - M[8]*center.Z + (center.X - translation.X );
2044  M[13] = -M[1]*center.X - M[5]*center.Y - M[9]*center.Z + (center.Y - translation.Y );
2045  M[14] = -M[2]*center.X - M[6]*center.Y - M[10]*center.Z + (center.Z - translation.Z );
2046  M[15] = (T) 1.0;
2047 #if defined ( USE_MATRIX_TEST )
2048  definitelyIdentityMatrix=false;
2049 #endif
2050  }
2051 
2064  template <class T>
2066  const core::vector2df &rotatecenter,
2067  const core::vector2df &translate,
2068  const core::vector2df &scale)
2069  {
2070  const f32 c = cosf(rotateRad);
2071  const f32 s = sinf(rotateRad);
2072 
2073  M[0] = (T)(c * scale.X);
2074  M[1] = (T)(s * scale.Y);
2075  M[2] = 0;
2076  M[3] = 0;
2077 
2078  M[4] = (T)(-s * scale.X);
2079  M[5] = (T)(c * scale.Y);
2080  M[6] = 0;
2081  M[7] = 0;
2082 
2083  M[8] = (T)(c * scale.X * rotatecenter.X + -s * rotatecenter.Y + translate.X);
2084  M[9] = (T)(s * scale.Y * rotatecenter.X + c * rotatecenter.Y + translate.Y);
2085  M[10] = 1;
2086  M[11] = 0;
2087 
2088  M[12] = 0;
2089  M[13] = 0;
2090  M[14] = 0;
2091  M[15] = 1;
2092 #if defined ( USE_MATRIX_TEST )
2093  definitelyIdentityMatrix=false;
2094 #endif
2095  return *this;
2096  }
2097 
2098 
2099  // rotate about z axis, center ( 0.5, 0.5 )
2100  template <class T>
2102  {
2103  const f32 c = cosf(rotateRad);
2104  const f32 s = sinf(rotateRad);
2105  M[0] = (T)c;
2106  M[1] = (T)s;
2107 
2108  M[4] = (T)-s;
2109  M[5] = (T)c;
2110 
2111  M[8] = (T)(0.5f * ( s - c) + 0.5f);
2112  M[9] = (T)(-0.5f * ( s + c) + 0.5f);
2113 
2114 #if defined ( USE_MATRIX_TEST )
2115  definitelyIdentityMatrix = definitelyIdentityMatrix && (rotateRad==0.0f);
2116 #endif
2117  return *this;
2118  }
2119 
2120 
2121  template <class T>
2123  {
2124  M[8] = (T)x;
2125  M[9] = (T)y;
2126 
2127 #if defined ( USE_MATRIX_TEST )
2128  definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f);
2129 #endif
2130  return *this;
2131  }
2132 
2133 
2134  template <class T>
2136  {
2137  M[2] = (T)x;
2138  M[6] = (T)y;
2139 
2140 #if defined ( USE_MATRIX_TEST )
2141  definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f) ;
2142 #endif
2143  return *this;
2144  }
2145 
2146  template <class T>
2148  {
2149  M[0] = (T)sx;
2150  M[5] = (T)sy;
2151 #if defined ( USE_MATRIX_TEST )
2152  definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
2153 #endif
2154  return *this;
2155  }
2156 
2157 
2158  template <class T>
2160  {
2161  M[0] = (T)sx;
2162  M[5] = (T)sy;
2163  M[8] = (T)(0.5f - 0.5f * sx);
2164  M[9] = (T)(0.5f - 0.5f * sy);
2165 
2166 #if defined ( USE_MATRIX_TEST )
2167  definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
2168 #endif
2169  return *this;
2170  }
2171 
2172 
2173  // sets all matrix data members at once
2174  template <class T>
2175  inline CMatrix4<T>& CMatrix4<T>::setM(const T* data)
2176  {
2177  memcpy(M,data, 16*sizeof(T));
2178 
2179 #if defined ( USE_MATRIX_TEST )
2180  definitelyIdentityMatrix=false;
2181 #endif
2182  return *this;
2183  }
2184 
2185 
2186  // sets if the matrix is definitely identity matrix
2187  template <class T>
2188  inline void CMatrix4<T>::setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix)
2189  {
2190 #if defined ( USE_MATRIX_TEST )
2191  definitelyIdentityMatrix = isDefinitelyIdentityMatrix;
2192 #endif
2193  }
2194 
2195 
2196  // gets if the matrix is definitely identity matrix
2197  template <class T>
2199  {
2200 #if defined ( USE_MATRIX_TEST )
2201  return definitelyIdentityMatrix;
2202 #else
2203  return false;
2204 #endif
2205  }
2206 
2207 
2209  template <class T>
2210  inline bool CMatrix4<T>::equals(const core::CMatrix4<T>& other, const T tolerance) const
2211  {
2212 #if defined ( USE_MATRIX_TEST )
2213  if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
2214  return true;
2215 #endif
2216  for (s32 i = 0; i < 16; ++i)
2217  if (!core::equals(M[i],other.M[i], tolerance))
2218  return false;
2219 
2220  return true;
2221  }
2222 
2223 
2224  // Multiply by scalar.
2225  template <class T>
2226  inline CMatrix4<T> operator*(const T scalar, const CMatrix4<T>& mat)
2227  {
2228  return mat*scalar;
2229  }
2230 
2231 
2234 
2236  IRRLICHT_API extern const matrix4 IdentityMatrix;
2237 
2238 } // end namespace core
2239 } // end namespace irr
2240 
2241 #endif
2242 
void rotateVect(vector3df &vect) const
Rotate a vector by the rotation part of this matrix.
Definition: matrix4.h:1101
bool getInversePrimitive(CMatrix4< T > &out) const
Inverts a primitive matrix which only contains a translation and a rotation.
Definition: matrix4.h:1393
const f64 RADTODEG64
64bit constant for converting from radians to degrees
Definition: irrMath.h:83
T D
Distance from origin.
Definition: plane3d.h:231
CMatrix4< T > & buildCameraLookAtMatrixLH(const vector3df &position, const vector3df &target, const vector3df &upVector)
Builds a left-handed look-at matrix.
Definition: matrix4.h:1775
vector3d< T > MaxEdge
The far edge.
Definition: aabbox3d.h:320
T Y
Y coordinate of the vector.
Definition: vector3d.h:411
bool iszero(const f64 a, const f64 tolerance=ROUNDING_ERROR_f64)
returns if a equals zero, taking rounding errors into account
Definition: irrMath.h:270
CMatrix4< T > & buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
Builds a right-handed orthogonal projection matrix.
Definition: matrix4.h:1639
const T * pointer() const
Returns pointer to internal array.
Definition: matrix4.h:99
IRRLICHT_API const matrix4 IdentityMatrix
global const identity matrix
void setDefinitelyIdentityMatrix(bool isDefinitelyIdentityMatrix)
Sets if the matrix is definitely identity matrix.
Definition: matrix4.h:2188
CMatrix4< T > & buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
Builds a right-handed perspective projection matrix based on a field of view.
Definition: matrix4.h:1492
core::vector3d< T > getScale() const
Get Scale.
Definition: matrix4.h:795
CMatrix4< T > & setTextureTranslateTransposed(f32 x, f32 y)
Set texture transformation translation, using a transposed representation.
Definition: matrix4.h:2135
const T & operator[](u32 index) const
Simple operator for linearly accessing every element of the matrix.
Definition: matrix4.h:90
u32 IR(f32 x)
Definition: irrMath.h:353
void transformBox(core::aabbox3d< f32 > &box) const
Transforms a axis aligned bounding box.
Definition: matrix4.h:1203
float f32
32 bit floating point variable.
Definition: irrTypes.h:104
void transformVect(vector3df &vect) const
Transforms the vector by this matrix.
Definition: matrix4.h:1137
CMatrix4< T > & setTextureTranslate(f32 x, f32 y)
Set texture transformation translation.
Definition: matrix4.h:2122
CMatrix4< T > & setScale(const T scale)
Set Scale.
Definition: matrix4.h:196
vector3d< T > Normal
Normal vector of the plane.
Definition: plane3d.h:228
position2d< T > UpperLeftCorner
Upper left corner.
Definition: rect.h:265
CMatrix4< T > & operator+=(const CMatrix4< T > &other)
Add another matrix.
Definition: matrix4.h:502
void transformVec3(T *out, const T *in) const
An alternate transform vector method, reading from and writing to an array of 3 floats.
Definition: matrix4.h:1169
T Y
Y coordinate of vector.
Definition: vector2d.h:319
void setRotationCenter(const core::vector3df &center, const core::vector3df &translate)
Builds a combined matrix which translates to a center before rotation and translates from origin afte...
Definition: matrix4.h:2041
#define IRRLICHT_API
Set FPU settings.
T X
X coordinate of the vector.
Definition: vector3d.h:408
CMatrix4< T > & setRotationAxisRadians(const T &angle, const vector3d< T > &axis)
Make a rotation matrix from angle and axis, assuming left handed rotation.
Definition: matrix4.h:948
void transformBoxEx(core::aabbox3d< f32 > &box) const
Transforms a axis aligned bounding box.
Definition: matrix4.h:1217
CMatrix4< T > & setInverseRotationRadians(const vector3d< T > &rotation)
Make an inverted rotation matrix from Euler angles.
Definition: matrix4.h:917
Everything in the Irrlicht Engine can be found in this namespace.
Definition: aabbox3d.h:12
3d vector template class with lots of operators and methods.
Definition: vector3d.h:22
bool isOrthogonal() const
Returns true if the matrix is orthogonal.
Definition: matrix4.h:1038
bool equals(const core::CMatrix4< T > &other, const T tolerance=(T) ROUNDING_ERROR_f64) const
Compare two matrices using the equal method.
Definition: matrix4.h:2210
vector3d< T > getTranslation() const
Gets the current translation.
Definition: matrix4.h:744
CMatrix4< T > & buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
Builds a right-handed perspective projection matrix.
Definition: matrix4.h:1674
CMatrix4< T > & setTextureRotationCenter(f32 radAngle)
Set texture transformation rotation.
Definition: matrix4.h:2101
CMatrix4< T > & buildNDCToDCMatrix(const core::rect< s32 > &area, f32 zScale)
Builds a matrix which transforms a normalized Device Coordinate to Device Coordinates.
Definition: matrix4.h:1913
double f64
64 bit floating point variable.
Definition: irrTypes.h:108
bool isIdentity() const
Returns true if the matrix is the identity matrix.
Definition: matrix4.h:1000
vector3d< T > crossProduct(const vector3d< T > &p) const
Calculates the cross product with another vector.
Definition: vector3d.h:147
position2d< T > LowerRightCorner
Lower right corner.
Definition: rect.h:267
CMatrix4< T > & buildTextureTransform(f32 rotateRad, const core::vector2df &rotatecenter, const core::vector2df &translate, const core::vector2df &scale)
Set to a texture transformation matrix with the given parameters.
Definition: matrix4.h:2065
CMatrix4< T > & setbyproduct_nocheck(const CMatrix4< T > &other_a, const CMatrix4< T > &other_b)
Set this matrix to the product of two matrices.
Definition: matrix4.h:653
CMatrix4< T > & operator*=(const CMatrix4< T > &other)
Multiply by another matrix.
Definition: matrix4.h:626
CMatrix4< T > & setInverseRotationDegrees(const vector3d< T > &rotation)
Make an inverted rotation matrix from Euler angles.
Definition: matrix4.h:819
vector3d< T > getMemberPoint() const
Gets a member point of the plane.
Definition: plane3d.h:155
CMatrix4< T > & setScale(const vector3d< T > &scale)
Set Scale.
Definition: matrix4.h:775
void multiplyWith1x4Matrix(T *matrix) const
Multiplies this matrix by a 1x4 matrix.
Definition: matrix4.h:1268
CMatrix4< T > & setbyproduct(const CMatrix4< T > &other_a, const CMatrix4< T > &other_b)
set this matrix to the product of two matrices
Definition: matrix4.h:688
const f64 ROUNDING_ERROR_f64
Definition: irrMath.h:50
signed int s32
32 bit signed variable.
Definition: irrTypes.h:66
CMatrix4< T > & buildCameraLookAtMatrixRH(const vector3df &position, const vector3df &target, const vector3df &upVector)
Builds a right-handed look-at matrix.
Definition: matrix4.h:1816
bool getDefinitelyIdentityMatrix() const
Gets if the matrix is definitely identity matrix.
Definition: matrix4.h:2198
bool operator==(const CMatrix4< T > &other) const
Returns true if other matrix is equal to this matrix.
Definition: matrix4.h:1469
T getWidth() const
Get width of rectangle.
Definition: rect.h:184
REALINLINE f32 reciprocal(const f32 f)
Definition: irrMath.h:535
void setPlane(const vector3d< T > &point, const vector3d< T > &nvector)
Definition: plane3d.h:58
CMatrix4< T > & setTextureScale(f32 sx, f32 sy)
Set texture transformation scale.
Definition: matrix4.h:2147
CMatrix4< T > & buildRotateFromTo(const core::vector3df &from, const core::vector3df &to)
Builds a matrix that rotates from one vector to another.
Definition: matrix4.h:1934
#define F32_VALUE_1
Definition: irrMath.h:344
CMatrix4< T > & setRotationDegrees(const vector3d< T > &rotation)
Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
Definition: matrix4.h:813
unsigned int u32
32 bit unsigned variable.
Definition: irrTypes.h:58
void inverseTranslateVect(vector3df &vect) const
Translate a vector by the inverse of the translation part of this matrix.
Definition: matrix4.h:1290
CMatrix4< T > operator+(const CMatrix4< T > &other) const
Add another matrix.
Definition: matrix4.h:476
CMatrix4< T > & buildShadowMatrix(const core::vector3df &light, core::plane3df plane, f32 point=1.0f)
Builds a matrix that flattens geometry into a plane.
Definition: matrix4.h:1743
CMatrix4(eConstructor constructor=EM4CONST_IDENTITY)
Default constructor.
Definition: matrix4.h:417
bool getInverse(CMatrix4< T > &out) const
Gets the inversed matrix of this one.
Definition: matrix4.h:1307
#define _IRR_DEBUG_BREAK_IF(_CONDITION_)
define a break macro for debugging.
Definition: irrTypes.h:178
CMatrix4< T > & operator=(const CMatrix4< T > &other)
Sets this matrix equal to the other matrix.
Definition: matrix4.h:1443
CMatrix4< T > & setInverseTranslation(const vector3d< T > &translation)
Set the inverse translation of the current matrix. Will erase any previous values.
Definition: matrix4.h:763
const f32 DEGTORAD
32bit Constant for converting from degrees to radians
Definition: irrMath.h:74
CMatrix4< T > & buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
Builds a left-handed perspective projection matrix.
Definition: matrix4.h:1709
vector3d< T > & normalize()
Normalizes the vector.
Definition: vector3d.h:168
CMatrix4< T > operator-(const CMatrix4< T > &other) const
Subtract another matrix.
Definition: matrix4.h:526
T getHeight() const
Get height of rectangle.
Definition: rect.h:190
vector3d< T > MinEdge
The near edge.
Definition: aabbox3d.h:317
4x4 matrix. Mostly used as transformation matrix for 3d calculations.
Definition: matrix4.h:45
CMatrix4< T > getTransposed() const
Gets transposed matrix.
Definition: matrix4.h:1874
CMatrix4< T > & setTranslation(const vector3d< T > &translation)
Set the translation of the current matrix. Will erase any previous values.
Definition: matrix4.h:751
bool makeInverse()
Calculates inverse of matrix. Slow.
Definition: matrix4.h:1424
CMatrix4< T > & setTextureScaleCenter(f32 sx, f32 sy)
Set texture transformation scale, and recenter at (0.5,0.5)
Definition: matrix4.h:2159
CMatrix4< T > operator*(const CMatrix4< T > &other) const
Multiply by another matrix.
Definition: matrix4.h:705
CMatrix4< T > & buildProjectionMatrixPerspectiveFovInfinityLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon=0)
Builds a left-handed perspective projection matrix based on a field of view, with far plane at infini...
Definition: matrix4.h:1568
void buildAxisAlignedBillboard(const core::vector3df &camPos, const core::vector3df &center, const core::vector3df &translation, const core::vector3df &axis, const core::vector3df &from)
Builds a matrix which rotates a source vector to a look vector over an arbitrary axis.
Definition: matrix4.h:1990
T & operator[](u32 index)
Simple operator for linearly accessing every element of the matrix.
Definition: matrix4.h:81
T Z
Z coordinate of the vector.
Definition: vector3d.h:414
core::vector3d< T > getRotationDegrees() const
Returns the rotation, as set by setRotation().
Definition: matrix4.h:860
#define FLT_MIN
Definition: irrMath.h:35
CMatrix4< T > & buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
Builds a left-handed perspective projection matrix based on a field of view.
Definition: matrix4.h:1531
CMatrix4< T > & buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
Builds a left-handed orthogonal projection matrix.
Definition: matrix4.h:1604
CMatrix4< f32 > matrix4
Typedef for f32 matrix.
Definition: matrix4.h:2233
bool isIdentity_integer_base() const
Returns true if the matrix is the identity matrix.
Definition: matrix4.h:1067
const T & operator()(const s32 row, const s32 col) const
Simple operator for directly accessing every element of the matrix.
Definition: matrix4.h:78
T dotProduct(const vector3d< T > &other) const
Get the dot product with another vector.
Definition: vector3d.h:125
eConstructor
Constructor Flags.
Definition: matrix4.h:50
void inverseRotateVect(vector3df &vect) const
Rotate a vector by the inverse of the rotation part of this matrix.
Definition: matrix4.h:1128
CMatrix4< T > operator*(const T scalar, const CMatrix4< T > &mat)
Definition: matrix4.h:2226
void repair()
Repairs the box.
Definition: aabbox3d.h:172
CMatrix4< T > & setRotationRadians(const vector3d< T > &rotation)
Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
Definition: matrix4.h:825
void transformPlane(core::plane3d< f32 > &plane) const
Transforms a plane by this matrix.
Definition: matrix4.h:1179
CMatrix4< T > & setM(const T *data)
Sets all matrix data members at once.
Definition: matrix4.h:2175
bool operator!=(const CMatrix4< T > &other) const
Returns true if other matrix is not equal to this matrix.
Definition: matrix4.h:1484
bool equals(const f64 a, const f64 b, const f64 tolerance=ROUNDING_ERROR_f64)
returns if a equals b, taking possible rounding errors into account
Definition: irrMath.h:185
void translateVect(vector3df &vect) const
Translate a vector by the translation part of this matrix.
Definition: matrix4.h:1298
CMatrix4< T > & makeIdentity()
Set matrix to identity.
Definition: matrix4.h:984
CMatrix4< T > interpolate(const core::CMatrix4< T > &b, f32 time) const
Creates a new matrix as interpolated matrix from two other ones.
Definition: matrix4.h:1857
T & operator()(const s32 row, const s32 col)
Simple operator for directly accessing every element of the matrix.
Definition: matrix4.h:69
const T clamp(const T &value, const T &low, const T &high)
clamps a value between low and high
Definition: irrMath.h:166
CMatrix4< T > & operator-=(const CMatrix4< T > &other)
Subtract another matrix.
Definition: matrix4.h:552
T X
X coordinate of vector.
Definition: vector2d.h:316