LCOV - code coverage report
Current view: top level - usr/include/irrlicht - matrix4.h (source / functions) Hit Total Coverage
Test: report Lines: 276 316 87.3 %
Date: 2015-07-11 18:23:49 Functions: 27 32 84.4 %

          Line data    Source code
       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             : 
      42             :         //! 4x4 matrix. Mostly used as transformation matrix for 3d calculations.
      43             :         /** The matrix is a D3D style matrix, row major with translations in the 4th row. */
      44             :         template <class T>
      45             :         class CMatrix4
      46             :         {
      47             :                 public:
      48             : 
      49             :                         //! Constructor Flags
      50             :                         enum eConstructor
      51             :                         {
      52             :                                 EM4CONST_NOTHING = 0,
      53             :                                 EM4CONST_COPY,
      54             :                                 EM4CONST_IDENTITY,
      55             :                                 EM4CONST_TRANSPOSED,
      56             :                                 EM4CONST_INVERSE,
      57             :                                 EM4CONST_INVERSE_TRANSPOSED
      58             :                         };
      59             : 
      60             :                         //! Default constructor
      61             :                         /** \param constructor Choose the initialization style */
      62             :                         CMatrix4( eConstructor constructor = EM4CONST_IDENTITY );
      63             :                         //! Copy constructor
      64             :                         /** \param other Other matrix to copy from
      65             :                         \param constructor Choose the initialization style */
      66             :                         CMatrix4(const CMatrix4<T>& other, eConstructor constructor = EM4CONST_COPY);
      67             : 
      68             :                         //! Simple operator for directly accessing every element of the matrix.
      69    22819888 :                         T& operator()(const s32 row, const s32 col)
      70             :                         {
      71             : #if defined ( USE_MATRIX_TEST )
      72             :                                 definitelyIdentityMatrix=false;
      73             : #endif
      74    22819888 :                                 return M[ row * 4 + col ];
      75             :                         }
      76             : 
      77             :                         //! Simple operator for directly accessing every element of the matrix.
      78   410758920 :                         const T& operator()(const s32 row, const s32 col) const { return M[row * 4 + col]; }
      79             : 
      80             :                         //! Simple operator for linearly accessing every element of the matrix.
      81    30090608 :                         T& operator[](u32 index)
      82             :                         {
      83             : #if defined ( USE_MATRIX_TEST )
      84             :                                 definitelyIdentityMatrix=false;
      85             : #endif
      86    30090608 :                                 return M[index];
      87             :                         }
      88             : 
      89             :                         //! Simple operator for linearly accessing every element of the matrix.
      90    29093440 :                         const T& operator[](u32 index) const { return M[index]; }
      91             : 
      92             :                         //! Sets this matrix equal to the other matrix.
      93             :                         inline CMatrix4<T>& operator=(const CMatrix4<T> &other);
      94             : 
      95             :                         //! Sets all elements of this matrix to the value.
      96             :                         inline CMatrix4<T>& operator=(const T& scalar);
      97             : 
      98             :                         //! Returns pointer to internal array
      99             :                         const T* pointer() const { return M; }
     100     5704312 :                         T* pointer()
     101             :                         {
     102             : #if defined ( USE_MATRIX_TEST )
     103             :                                 definitelyIdentityMatrix=false;
     104             : #endif
     105     5704312 :                                 return M;
     106             :                         }
     107             : 
     108             :                         //! Returns true if other matrix is equal to this matrix.
     109             :                         bool operator==(const CMatrix4<T> &other) const;
     110             : 
     111             :                         //! Returns true if other matrix is not equal to this matrix.
     112             :                         bool operator!=(const CMatrix4<T> &other) const;
     113             : 
     114             :                         //! Add another matrix.
     115             :                         CMatrix4<T> operator+(const CMatrix4<T>& other) const;
     116             : 
     117             :                         //! Add another matrix.
     118             :                         CMatrix4<T>& operator+=(const CMatrix4<T>& other);
     119             : 
     120             :                         //! Subtract another matrix.
     121             :                         CMatrix4<T> operator-(const CMatrix4<T>& other) const;
     122             : 
     123             :                         //! Subtract another matrix.
     124             :                         CMatrix4<T>& operator-=(const CMatrix4<T>& other);
     125             : 
     126             :                         //! set this matrix to the product of two matrices
     127             :                         /** Calculate b*a */
     128             :                         inline CMatrix4<T>& setbyproduct(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
     129             : 
     130             :                         //! Set this matrix to the product of two matrices
     131             :                         /** Calculate b*a, no optimization used,
     132             :                         use it if you know you never have a identity matrix */
     133             :                         CMatrix4<T>& setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
     134             : 
     135             :                         //! Multiply by another matrix.
     136             :                         /** Calculate other*this */
     137             :                         CMatrix4<T> operator*(const CMatrix4<T>& other) const;
     138             : 
     139             :                         //! Multiply by another matrix.
     140             :                         /** Calculate and return other*this */
     141             :                         CMatrix4<T>& operator*=(const CMatrix4<T>& other);
     142             : 
     143             :                         //! Multiply by scalar.
     144             :                         CMatrix4<T> operator*(const T& scalar) const;
     145             : 
     146             :                         //! Multiply by scalar.
     147             :                         CMatrix4<T>& operator*=(const T& scalar);
     148             : 
     149             :                         //! Set matrix to identity.
     150             :                         inline CMatrix4<T>& makeIdentity();
     151             : 
     152             :                         //! Returns true if the matrix is the identity matrix
     153             :                         inline bool isIdentity() const;
     154             : 
     155             :                         //! Returns true if the matrix is orthogonal
     156             :                         inline bool isOrthogonal() const;
     157             : 
     158             :                         //! Returns true if the matrix is the identity matrix
     159             :                         bool isIdentity_integer_base () const;
     160             : 
     161             :                         //! Set the translation of the current matrix. Will erase any previous values.
     162             :                         CMatrix4<T>& setTranslation( const vector3d<T>& translation );
     163             : 
     164             :                         //! Gets the current translation
     165             :                         vector3d<T> getTranslation() const;
     166             : 
     167             :                         //! Set the inverse translation of the current matrix. Will erase any previous values.
     168             :                         CMatrix4<T>& setInverseTranslation( const vector3d<T>& translation );
     169             : 
     170             :                         //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
     171             :                         inline CMatrix4<T>& setRotationRadians( const vector3d<T>& rotation );
     172             : 
     173             :                         //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
     174             :                         CMatrix4<T>& setRotationDegrees( const vector3d<T>& rotation );
     175             : 
     176             :                         //! Returns the rotation, as set by setRotation().
     177             :                         /** This code was orginally written by by Chev. */
     178             :                         core::vector3d<T> getRotationDegrees() const;
     179             : 
     180             :                         //! Make an inverted rotation matrix from Euler angles.
     181             :                         /** The 4th row and column are unmodified. */
     182             :                         inline CMatrix4<T>& setInverseRotationRadians( const vector3d<T>& rotation );
     183             : 
     184             :                         //! Make an inverted rotation matrix from Euler angles.
     185             :                         /** The 4th row and column are unmodified. */
     186             :                         inline CMatrix4<T>& setInverseRotationDegrees( const vector3d<T>& rotation );
     187             : 
     188             :                         //! Make a rotation matrix from angle and axis, assuming left handed rotation.
     189             :                         /** The 4th row and column are unmodified. */
     190             :                         inline CMatrix4<T>& setRotationAxisRadians(const T& angle, const vector3d<T>& axis);
     191             : 
     192             :                         //! Set Scale
     193             :                         CMatrix4<T>& setScale( const vector3d<T>& scale );
     194             : 
     195             :                         //! Set Scale
     196             :                         CMatrix4<T>& setScale( const T scale ) { return setScale(core::vector3d<T>(scale,scale,scale)); }
     197             : 
     198             :                         //! Get Scale
     199             :                         core::vector3d<T> getScale() const;
     200             : 
     201             :                         //! Translate a vector by the inverse of the translation part of this matrix.
     202             :                         void inverseTranslateVect( vector3df& vect ) const;
     203             : 
     204             :                         //! Rotate a vector by the inverse of the rotation part of this matrix.
     205             :                         void inverseRotateVect( vector3df& vect ) const;
     206             : 
     207             :                         //! Rotate a vector by the rotation part of this matrix.
     208             :                         void rotateVect( vector3df& vect ) const;
     209             : 
     210             :                         //! An alternate transform vector method, writing into a second vector
     211             :                         void rotateVect(core::vector3df& out, const core::vector3df& in) const;
     212             : 
     213             :                         //! An alternate transform vector method, writing into an array of 3 floats
     214             :                         void rotateVect(T *out,const core::vector3df &in) const;
     215             : 
     216             :                         //! Transforms the vector by this matrix
     217             :                         void transformVect( vector3df& vect) const;
     218             : 
     219             :                         //! Transforms input vector by this matrix and stores result in output vector
     220             :                         void transformVect( vector3df& out, const vector3df& in ) const;
     221             : 
     222             :                         //! An alternate transform vector method, writing into an array of 4 floats
     223             :                         void transformVect(T *out,const core::vector3df &in) const;
     224             : 
     225             :                         //! An alternate transform vector method, reading from and writing to an array of 3 floats
     226             :                         void transformVec3(T *out, const T * in) const;
     227             : 
     228             :                         //! Translate a vector by the translation part of this matrix.
     229             :                         void translateVect( vector3df& vect ) const;
     230             : 
     231             :                         //! Transforms a plane by this matrix
     232             :                         void transformPlane( core::plane3d<f32> &plane) const;
     233             : 
     234             :                         //! Transforms a plane by this matrix
     235             :                         void transformPlane( const core::plane3d<f32> &in, core::plane3d<f32> &out) const;
     236             : 
     237             :                         //! Transforms a axis aligned bounding box
     238             :                         /** The result box of this operation may not be accurate at all. For
     239             :                         correct results, use transformBoxEx() */
     240             :                         void transformBox(core::aabbox3d<f32>& box) const;
     241             : 
     242             :                         //! Transforms a axis aligned bounding box
     243             :                         /** The result box of this operation should by accurate, but this operation
     244             :                         is slower than transformBox(). */
     245             :                         void transformBoxEx(core::aabbox3d<f32>& box) const;
     246             : 
     247             :                         //! Multiplies this matrix by a 1x4 matrix
     248             :                         void multiplyWith1x4Matrix(T* matrix) const;
     249             : 
     250             :                         //! Calculates inverse of matrix. Slow.
     251             :                         /** \return Returns false if there is no inverse matrix.*/
     252             :                         bool makeInverse();
     253             : 
     254             : 
     255             :                         //! Inverts a primitive matrix which only contains a translation and a rotation
     256             :                         /** \param out: where result matrix is written to. */
     257             :                         bool getInversePrimitive ( CMatrix4<T>& out ) const;
     258             : 
     259             :                         //! Gets the inversed matrix of this one
     260             :                         /** \param out: where result matrix is written to.
     261             :                         \return Returns false if there is no inverse matrix. */
     262             :                         bool getInverse(CMatrix4<T>& out) const;
     263             : 
     264             :                         //! Builds a right-handed perspective projection matrix based on a field of view
     265             :                         CMatrix4<T>& buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
     266             : 
     267             :                         //! Builds a left-handed perspective projection matrix based on a field of view
     268             :                         CMatrix4<T>& buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
     269             : 
     270             :                         //! Builds a left-handed perspective projection matrix based on a field of view, with far plane at infinity
     271             :                         CMatrix4<T>& buildProjectionMatrixPerspectiveFovInfinityLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon=0);
     272             : 
     273             :                         //! Builds a right-handed perspective projection matrix.
     274             :                         CMatrix4<T>& buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
     275             : 
     276             :                         //! Builds a left-handed perspective projection matrix.
     277             :                         CMatrix4<T>& buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
     278             : 
     279             :                         //! Builds a left-handed orthogonal projection matrix.
     280             :                         CMatrix4<T>& buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
     281             : 
     282             :                         //! Builds a right-handed orthogonal projection matrix.
     283             :                         CMatrix4<T>& buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
     284             : 
     285             :                         //! Builds a left-handed look-at matrix.
     286             :                         CMatrix4<T>& buildCameraLookAtMatrixLH(
     287             :                                         const vector3df& position,
     288             :                                         const vector3df& target,
     289             :                                         const vector3df& upVector);
     290             : 
     291             :                         //! Builds a right-handed look-at matrix.
     292             :                         CMatrix4<T>& buildCameraLookAtMatrixRH(
     293             :                                         const vector3df& position,
     294             :                                         const vector3df& target,
     295             :                                         const vector3df& upVector);
     296             : 
     297             :                         //! Builds a matrix that flattens geometry into a plane.
     298             :                         /** \param light: light source
     299             :                         \param plane: plane into which the geometry if flattened into
     300             :                         \param point: value between 0 and 1, describing the light source.
     301             :                         If this is 1, it is a point light, if it is 0, it is a directional light. */
     302             :                         CMatrix4<T>& buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point=1.0f);
     303             : 
     304             :                         //! Builds a matrix which transforms a normalized Device Coordinate to Device Coordinates.
     305             :                         /** Used to scale <-1,-1><1,1> to viewport, for example from <-1,-1> <1,1> to the viewport <0,0><0,640> */
     306             :                         CMatrix4<T>& buildNDCToDCMatrix( const core::rect<s32>& area, f32 zScale);
     307             : 
     308             :                         //! Creates a new matrix as interpolated matrix from two other ones.
     309             :                         /** \param b: other matrix to interpolate with
     310             :                         \param time: Must be a value between 0 and 1. */
     311             :                         CMatrix4<T> interpolate(const core::CMatrix4<T>& b, f32 time) const;
     312             : 
     313             :                         //! Gets transposed matrix
     314             :                         CMatrix4<T> getTransposed() const;
     315             : 
     316             :                         //! Gets transposed matrix
     317             :                         inline void getTransposed( CMatrix4<T>& dest ) const;
     318             : 
     319             :                         //! Builds a matrix that rotates from one vector to another
     320             :                         /** \param from: vector to rotate from
     321             :                         \param to: vector to rotate to
     322             :                          */
     323             :                         CMatrix4<T>& buildRotateFromTo(const core::vector3df& from, const core::vector3df& to);
     324             : 
     325             :                         //! Builds a combined matrix which translates to a center before rotation and translates from origin afterwards
     326             :                         /** \param center Position to rotate around
     327             :                         \param translate Translation applied after the rotation
     328             :                          */
     329             :                         void setRotationCenter(const core::vector3df& center, const core::vector3df& translate);
     330             : 
     331             :                         //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis
     332             :                         /** \param camPos: viewer position in world coo
     333             :                         \param center: object position in world-coo and rotation pivot
     334             :                         \param translation: object final translation from center
     335             :                         \param axis: axis to rotate about
     336             :                         \param from: source vector to rotate from
     337             :                          */
     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             :                         */
     348             :                         //! Set to a texture transformation matrix with the given parameters.
     349             :                         CMatrix4<T>& buildTextureTransform( f32 rotateRad,
     350             :                                         const core::vector2df &rotatecenter,
     351             :                                         const core::vector2df &translate,
     352             :                                         const core::vector2df &scale);
     353             : 
     354             :                         //! Set texture transformation rotation
     355             :                         /** Rotate about z axis, recenter at (0.5,0.5).
     356             :                         Doesn't clear other elements than those affected
     357             :                         \param radAngle Angle in radians
     358             :                         \return Altered matrix */
     359             :                         CMatrix4<T>& setTextureRotationCenter( f32 radAngle );
     360             : 
     361             :                         //! Set texture transformation translation
     362             :                         /** Doesn't clear other elements than those affected.
     363             :                         \param x Offset on x axis
     364             :                         \param y Offset on y axis
     365             :                         \return Altered matrix */
     366             :                         CMatrix4<T>& setTextureTranslate( f32 x, f32 y );
     367             : 
     368             :                         //! Set texture transformation translation, using a transposed representation
     369             :                         /** Doesn't clear other elements than those affected.
     370             :                         \param x Offset on x axis
     371             :                         \param y Offset on y axis
     372             :                         \return Altered matrix */
     373             :                         CMatrix4<T>& setTextureTranslateTransposed( f32 x, f32 y );
     374             : 
     375             :                         //! Set texture transformation scale
     376             :                         /** Doesn't clear other elements than those affected.
     377             :                         \param sx Scale factor on x axis
     378             :                         \param sy Scale factor on y axis
     379             :                         \return Altered matrix. */
     380             :                         CMatrix4<T>& setTextureScale( f32 sx, f32 sy );
     381             : 
     382             :                         //! Set texture transformation scale, and recenter at (0.5,0.5)
     383             :                         /** Doesn't clear other elements than those affected.
     384             :                         \param sx Scale factor on x axis
     385             :                         \param sy Scale factor on y axis
     386             :                         \return Altered matrix. */
     387             :                         CMatrix4<T>& setTextureScaleCenter( f32 sx, f32 sy );
     388             : 
     389             :                         //! Sets all matrix data members at once
     390             :                         CMatrix4<T>& setM(const T* data);
     391             : 
     392             :                         //! Sets if the matrix is definitely identity matrix
     393             :                         void setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix);
     394             : 
     395             :                         //! Gets if the matrix is definitely identity matrix
     396             :                         bool getDefinitelyIdentityMatrix() const;
     397             : 
     398             :                         //! Compare two matrices using the equal method
     399             :                         bool equals(const core::CMatrix4<T>& other, const T tolerance=(T)ROUNDING_ERROR_f64) const;
     400             : 
     401             :                 private:
     402             :                         //! Matrix data, stored in row-major order
     403             :                         T M[16];
     404             : #if defined ( USE_MATRIX_TEST )
     405             :                         //! Flag is this matrix is identity matrix
     406             :                         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     5271019 :         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     5271019 :                 switch ( constructor )
     426             :                 {
     427             :                         case EM4CONST_NOTHING:
     428             :                         case EM4CONST_COPY:
     429     3306741 :                                 break;
     430             :                         case EM4CONST_IDENTITY:
     431             :                         case EM4CONST_INVERSE:
     432             :                         default:
     433     1964278 :                                 makeIdentity();
     434     1964278 :                                 break;
     435             :                 }
     436     5271019 :         }
     437             : 
     438             :         // Copy constructor
     439             :         template <class T>
     440     7252520 :         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     7252520 :                 switch ( constructor )
     449             :                 {
     450             :                         case EM4CONST_IDENTITY:
     451           0 :                                 makeIdentity();
     452           0 :                                 break;
     453             :                         case EM4CONST_NOTHING:
     454           0 :                                 break;
     455             :                         case EM4CONST_COPY:
     456     7252520 :                                 *this = other;
     457     7252520 :                                 break;
     458             :                         case EM4CONST_TRANSPOSED:
     459           0 :                                 other.getTransposed(*this);
     460           0 :                                 break;
     461             :                         case EM4CONST_INVERSE:
     462           0 :                                 if (!other.getInverse(*this))
     463           0 :                                         memset(M, 0, 16*sizeof(T));
     464           0 :                                 break;
     465             :                         case EM4CONST_INVERSE_TRANSPOSED:
     466           0 :                                 if (!other.getInverse(*this))
     467           0 :                                         memset(M, 0, 16*sizeof(T));
     468             :                                 else
     469           0 :                                         *this=getTransposed();
     470           0 :                                 break;
     471             :                 }
     472     7252520 :         }
     473             : 
     474             :         //! Add another matrix.
     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             : 
     500             :         //! Add another matrix.
     501             :         template <class T>
     502             :         inline CMatrix4<T>& CMatrix4<T>::operator+=(const CMatrix4<T>& other)
     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             : 
     524             :         //! Subtract another matrix.
     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             : 
     550             :         //! Subtract another matrix.
     551             :         template <class T>
     552             :         inline CMatrix4<T>& CMatrix4<T>::operator-=(const CMatrix4<T>& other)
     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             : 
     574             :         //! Multiply by scalar.
     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             : 
     600             :         //! Multiply by scalar.
     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             : 
     624             :         //! Multiply by another matrix.
     625             :         template <class T>
     626     2970788 :         inline CMatrix4<T>& CMatrix4<T>::operator*=(const CMatrix4<T>& other)
     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     2970788 :                 CMatrix4<T> temp ( *this );
     645     2970788 :                 return setbyproduct_nocheck( temp, other );
     646             : #endif
     647             :         }
     648             : 
     649             :         //! multiply by another matrix
     650             :         // set this matrix to the product of two other matrices
     651             :         // goal is to reduce stack use and copy
     652             :         template <class T>
     653     2970788 :         inline CMatrix4<T>& CMatrix4<T>::setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b )
     654             :         {
     655     2970788 :                 const T *m1 = other_a.M;
     656     2970788 :                 const T *m2 = other_b.M;
     657             : 
     658     2970788 :                 M[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
     659     2970788 :                 M[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
     660     2970788 :                 M[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
     661     2970788 :                 M[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
     662             : 
     663     2970788 :                 M[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
     664     2970788 :                 M[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
     665     2970788 :                 M[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
     666     2970788 :                 M[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
     667             : 
     668     2970788 :                 M[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
     669     2970788 :                 M[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
     670     2970788 :                 M[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
     671     2970788 :                 M[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
     672             : 
     673     2970788 :                 M[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
     674     2970788 :                 M[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
     675     2970788 :                 M[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
     676     2970788 :                 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     2970788 :                 return *this;
     681             :         }
     682             : 
     683             : 
     684             :         //! multiply by another matrix
     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             : 
     703             :         //! multiply by another matrix
     704             :         template <class T>
     705      454585 :         inline CMatrix4<T> CMatrix4<T>::operator*(const CMatrix4<T>& m2) const
     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      454585 :                 CMatrix4<T> m3 ( EM4CONST_NOTHING );
     716             : 
     717      454585 :                 const T *m1 = M;
     718             : 
     719      454585 :                 m3[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
     720      454585 :                 m3[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
     721      454585 :                 m3[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
     722      454585 :                 m3[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
     723             : 
     724      454585 :                 m3[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
     725      454585 :                 m3[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
     726      454585 :                 m3[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
     727      454585 :                 m3[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
     728             : 
     729      454585 :                 m3[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
     730      454585 :                 m3[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
     731      454585 :                 m3[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
     732      454585 :                 m3[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
     733             : 
     734      454585 :                 m3[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
     735      454585 :                 m3[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
     736      454585 :                 m3[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
     737      454585 :                 m3[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
     738      454585 :                 return m3;
     739             :         }
     740             : 
     741             : 
     742             : 
     743             :         template <class T>
     744       18647 :         inline vector3d<T> CMatrix4<T>::getTranslation() const
     745             :         {
     746       18647 :                 return vector3d<T>(M[12], M[13], M[14]);
     747             :         }
     748             : 
     749             : 
     750             :         template <class T>
     751      362692 :         inline CMatrix4<T>& CMatrix4<T>::setTranslation( const vector3d<T>& translation )
     752             :         {
     753      362692 :                 M[12] = translation.X;
     754      362692 :                 M[13] = translation.Y;
     755      362692 :                 M[14] = translation.Z;
     756             : #if defined ( USE_MATRIX_TEST )
     757             :                 definitelyIdentityMatrix=false;
     758             : #endif
     759      362692 :                 return *this;
     760             :         }
     761             : 
     762             :         template <class T>
     763             :         inline CMatrix4<T>& CMatrix4<T>::setInverseTranslation( const vector3d<T>& translation )
     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>
     775      119798 :         inline CMatrix4<T>& CMatrix4<T>::setScale( const vector3d<T>& scale )
     776             :         {
     777      119798 :                 M[0] = scale.X;
     778      119798 :                 M[5] = scale.Y;
     779      119798 :                 M[10] = scale.Z;
     780             : #if defined ( USE_MATRIX_TEST )
     781             :                 definitelyIdentityMatrix=false;
     782             : #endif
     783      119798 :                 return *this;
     784             :         }
     785             : 
     786             :         //! Returns the absolute values of the scales of the matrix.
     787             :         /**
     788             :         Note that this returns the absolute (positive) values unless only scale is set.
     789             :         Unfortunately it does not appear to be possible to extract any original negative
     790             :         values. The best that we could do would be to arbitrarily make one scale
     791             :         negative if one or three of them were negative.
     792             :         FIXME - return the original values.
     793             :         */
     794             :         template <class T>
     795             :         inline vector3d<T> CMatrix4<T>::getScale() const
     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>
     813      361526 :         inline CMatrix4<T>& CMatrix4<T>::setRotationDegrees( const vector3d<T>& rotation )
     814             :         {
     815      361526 :                 return setRotationRadians( rotation * core::DEGTORAD );
     816             :         }
     817             : 
     818             :         template <class T>
     819             :         inline CMatrix4<T>& CMatrix4<T>::setInverseRotationDegrees( const vector3d<T>& rotation )
     820             :         {
     821             :                 return setInverseRotationRadians( rotation * core::DEGTORAD );
     822             :         }
     823             : 
     824             :         template <class T>
     825      361526 :         inline CMatrix4<T>& CMatrix4<T>::setRotationRadians( const vector3d<T>& rotation )
     826             :         {
     827      361526 :                 const f64 cr = cos( rotation.X );
     828      361526 :                 const f64 sr = sin( rotation.X );
     829      361526 :                 const f64 cp = cos( rotation.Y );
     830      361526 :                 const f64 sp = sin( rotation.Y );
     831      361526 :                 const f64 cy = cos( rotation.Z );
     832      361526 :                 const f64 sy = sin( rotation.Z );
     833             : 
     834      361526 :                 M[0] = (T)( cp*cy );
     835      361526 :                 M[1] = (T)( cp*sy );
     836      361526 :                 M[2] = (T)( -sp );
     837             : 
     838      361526 :                 const f64 srsp = sr*sp;
     839      361526 :                 const f64 crsp = cr*sp;
     840             : 
     841      361526 :                 M[4] = (T)( srsp*cy-cr*sy );
     842      361526 :                 M[5] = (T)( srsp*sy+cr*cy );
     843      361526 :                 M[6] = (T)( sr*cp );
     844             : 
     845      361526 :                 M[8] = (T)( crsp*cy+sr*sy );
     846      361526 :                 M[9] = (T)( crsp*sy-sr*cy );
     847      361526 :                 M[10] = (T)( cr*cp );
     848             : #if defined ( USE_MATRIX_TEST )
     849             :                 definitelyIdentityMatrix=false;
     850             : #endif
     851      361526 :                 return *this;
     852             :         }
     853             : 
     854             : 
     855             :         //! Returns a rotation that is equivalent to that set by setRotationDegrees().
     856             :         /** This code was sent in by Chev.  Note that it does not necessarily return
     857             :         the *same* Euler angles as those set by setRotationDegrees(), but the rotation will
     858             :         be equivalent, i.e. will have the same result when used to rotate a vector or node. */
     859             :         template <class T>
     860             :         inline core::vector3d<T> CMatrix4<T>::getRotationDegrees() const
     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             : 
     915             :         //! Sets matrix to rotation matrix of inverse angles given as parameters
     916             :         template <class T>
     917             :         inline CMatrix4<T>& CMatrix4<T>::setInverseRotationRadians( const vector3d<T>& rotation )
     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             : 
     946             :         //! Sets matrix to rotation matrix defined by axis and angle, assuming LH rotation
     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             : 
     981             :         /*!
     982             :         */
     983             :         template <class T>
     984     1965444 :         inline CMatrix4<T>& CMatrix4<T>::makeIdentity()
     985             :         {
     986     1965444 :                 memset(M, 0, 16*sizeof(T));
     987     1965444 :                 M[0] = M[5] = M[10] = M[15] = (T)1;
     988             : #if defined ( USE_MATRIX_TEST )
     989             :                 definitelyIdentityMatrix=true;
     990             : #endif
     991     1965444 :                 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>
    1067             :         inline bool CMatrix4<T>::isIdentity_integer_base() const
    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       53120 :         inline void CMatrix4<T>::rotateVect( vector3df& vect ) const
    1102             :         {
    1103       53120 :                 vector3df tmp = vect;
    1104       53120 :                 vect.X = tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8];
    1105       53120 :                 vect.Y = tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9];
    1106       53120 :                 vect.Z = tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10];
    1107       53120 :         }
    1108             : 
    1109             :         //! An alternate transform vector method, writing into a second vector
    1110             :         template <class T>
    1111        2332 :         inline void CMatrix4<T>::rotateVect(core::vector3df& out, const core::vector3df& in) const
    1112             :         {
    1113        2332 :                 out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
    1114        2332 :                 out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
    1115        2332 :                 out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
    1116        2332 :         }
    1117             : 
    1118             :         //! An alternate transform vector method, writing into an array of 3 floats
    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        1166 :         inline void CMatrix4<T>::transformVect( vector3df& out, const vector3df& in) const
    1152             :         {
    1153        1166 :                 out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
    1154        1166 :                 out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
    1155        1166 :                 out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
    1156        1166 :         }
    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             : 
    1177             :         //! Transforms a plane by this matrix
    1178             :         template <class T>
    1179             :         inline void CMatrix4<T>::transformPlane( core::plane3d<f32> &plane) const
    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             : 
    1193             :         //! Transforms a plane by this matrix
    1194             :         template <class T>
    1195             :         inline void CMatrix4<T>::transformPlane( const core::plane3d<f32> &in, core::plane3d<f32> &out) const
    1196             :         {
    1197             :                 out = in;
    1198             :                 transformPlane( out );
    1199             :         }
    1200             : 
    1201             :         //! Transforms a axis aligned bounding box
    1202             :         template <class T>
    1203             :         inline void CMatrix4<T>::transformBox(core::aabbox3d<f32>& box) const
    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             : 
    1215             :         //! Transforms a axis aligned bounding box more accurately than transformBox()
    1216             :         template <class T>
    1217          52 :         inline void CMatrix4<T>::transformBoxEx(core::aabbox3d<f32>& box) const
    1218             :         {
    1219             : #if defined ( USE_MATRIX_TEST )
    1220             :                 if (isIdentity())
    1221             :                         return;
    1222             : #endif
    1223             : 
    1224          52 :                 const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z};
    1225          52 :                 const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z};
    1226             : 
    1227             :                 f32 Bmin[3];
    1228             :                 f32 Bmax[3];
    1229             : 
    1230          52 :                 Bmin[0] = Bmax[0] = M[12];
    1231          52 :                 Bmin[1] = Bmax[1] = M[13];
    1232          52 :                 Bmin[2] = Bmax[2] = M[14];
    1233             : 
    1234          52 :                 const CMatrix4<T> &m = *this;
    1235             : 
    1236         208 :                 for (u32 i = 0; i < 3; ++i)
    1237             :                 {
    1238         624 :                         for (u32 j = 0; j < 3; ++j)
    1239             :                         {
    1240         468 :                                 const f32 a = m(j,i) * Amin[j];
    1241         468 :                                 const f32 b = m(j,i) * Amax[j];
    1242             : 
    1243         468 :                                 if (a < b)
    1244             :                                 {
    1245         154 :                                         Bmin[i] += a;
    1246         154 :                                         Bmax[i] += b;
    1247             :                                 }
    1248             :                                 else
    1249             :                                 {
    1250         314 :                                         Bmin[i] += b;
    1251         314 :                                         Bmax[i] += a;
    1252             :                                 }
    1253             :                         }
    1254             :                 }
    1255             : 
    1256          52 :                 box.MinEdge.X = Bmin[0];
    1257          52 :                 box.MinEdge.Y = Bmin[1];
    1258          52 :                 box.MinEdge.Z = Bmin[2];
    1259             : 
    1260          52 :                 box.MaxEdge.X = Bmax[0];
    1261          52 :                 box.MaxEdge.Y = Bmax[1];
    1262          52 :                 box.MaxEdge.Z = Bmax[2];
    1263          52 :         }
    1264             : 
    1265             : 
    1266             :         //! Multiplies this matrix by a 1x4 matrix
    1267             :         template <class T>
    1268           0 :         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           0 :                 mat[0] = matrix[0];
    1279           0 :                 mat[1] = matrix[1];
    1280           0 :                 mat[2] = matrix[2];
    1281           0 :                 mat[3] = matrix[3];
    1282             : 
    1283           0 :                 matrix[0] = M[0]*mat[0] + M[4]*mat[1] + M[8]*mat[2] + M[12]*mat[3];
    1284           0 :                 matrix[1] = M[1]*mat[0] + M[5]*mat[1] + M[9]*mat[2] + M[13]*mat[3];
    1285           0 :                 matrix[2] = M[2]*mat[0] + M[6]*mat[1] + M[10]*mat[2] + M[14]*mat[3];
    1286           0 :                 matrix[3] = M[3]*mat[0] + M[7]*mat[1] + M[11]*mat[2] + M[15]*mat[3];
    1287           0 :         }
    1288             : 
    1289             :         template <class T>
    1290             :         inline void CMatrix4<T>::inverseTranslateVect( vector3df& vect ) const
    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     1426243 :         inline bool CMatrix4<T>::getInverse(CMatrix4<T>& out) const
    1308             :         {
    1309             :                 /// Calculates the inverse of this Matrix
    1310             :                 /// The inverse is calculated using Cramers rule.
    1311             :                 /// If no inverse exists then 'false' is returned.
    1312             : 
    1313             : #if defined ( USE_MATRIX_TEST )
    1314             :                 if ( this->isIdentity() )
    1315             :                 {
    1316             :                         out=*this;
    1317             :                         return true;
    1318             :                 }
    1319             : #endif
    1320     1426243 :                 const CMatrix4<T> &m = *this;
    1321             : 
    1322    11409944 :                 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    11409944 :                         (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    11409944 :                         (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    11409944 :                         (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    11409944 :                         (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    57049720 :                         (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     1426243 :                 if( core::iszero ( d, FLT_MIN ) )
    1330           0 :                         return false;
    1331             : 
    1332     1426243 :                 d = core::reciprocal ( d );
    1333             : 
    1334    15688673 :                 out(0, 0) = d * (m(1, 1) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) +
    1335     7131215 :                                 m(1, 2) * (m(2, 3) * m(3, 1) - m(2, 1) * m(3, 3)) +
    1336     7131215 :                                 m(1, 3) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)));
    1337    15688673 :                 out(0, 1) = d * (m(2, 1) * (m(0, 2) * m(3, 3) - m(0, 3) * m(3, 2)) +
    1338     7131215 :                                 m(2, 2) * (m(0, 3) * m(3, 1) - m(0, 1) * m(3, 3)) +
    1339     7131215 :                                 m(2, 3) * (m(0, 1) * m(3, 2) - m(0, 2) * m(3, 1)));
    1340    15688673 :                 out(0, 2) = d * (m(3, 1) * (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) +
    1341     7131215 :                                 m(3, 2) * (m(0, 3) * m(1, 1) - m(0, 1) * m(1, 3)) +
    1342     7131215 :                                 m(3, 3) * (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)));
    1343    15688673 :                 out(0, 3) = d * (m(0, 1) * (m(1, 3) * m(2, 2) - m(1, 2) * m(2, 3)) +
    1344     7131215 :                                 m(0, 2) * (m(1, 1) * m(2, 3) - m(1, 3) * m(2, 1)) +
    1345     7131215 :                                 m(0, 3) * (m(1, 2) * m(2, 1) - m(1, 1) * m(2, 2)));
    1346    15688673 :                 out(1, 0) = d * (m(1, 2) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) +
    1347     7131215 :                                 m(1, 3) * (m(2, 2) * m(3, 0) - m(2, 0) * m(3, 2)) +
    1348     7131215 :                                 m(1, 0) * (m(2, 3) * m(3, 2) - m(2, 2) * m(3, 3)));
    1349    15688673 :                 out(1, 1) = d * (m(2, 2) * (m(0, 0) * m(3, 3) - m(0, 3) * m(3, 0)) +
    1350     7131215 :                                 m(2, 3) * (m(0, 2) * m(3, 0) - m(0, 0) * m(3, 2)) +
    1351     7131215 :                                 m(2, 0) * (m(0, 3) * m(3, 2) - m(0, 2) * m(3, 3)));
    1352    15688673 :                 out(1, 2) = d * (m(3, 2) * (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) +
    1353     7131215 :                                 m(3, 3) * (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2)) +
    1354     7131215 :                                 m(3, 0) * (m(0, 3) * m(1, 2) - m(0, 2) * m(1, 3)));
    1355    15688673 :                 out(1, 3) = d * (m(0, 2) * (m(1, 3) * m(2, 0) - m(1, 0) * m(2, 3)) +
    1356     7131215 :                                 m(0, 3) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
    1357     7131215 :                                 m(0, 0) * (m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2)));
    1358    15688673 :                 out(2, 0) = d * (m(1, 3) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)) +
    1359     7131215 :                                 m(1, 0) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
    1360     7131215 :                                 m(1, 1) * (m(2, 3) * m(3, 0) - m(2, 0) * m(3, 3)));
    1361    15688673 :                 out(2, 1) = d * (m(2, 3) * (m(0, 0) * m(3, 1) - m(0, 1) * m(3, 0)) +
    1362     7131215 :                                 m(2, 0) * (m(0, 1) * m(3, 3) - m(0, 3) * m(3, 1)) +
    1363     7131215 :                                 m(2, 1) * (m(0, 3) * m(3, 0) - m(0, 0) * m(3, 3)));
    1364    15688673 :                 out(2, 2) = d * (m(3, 3) * (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) +
    1365     7131215 :                                 m(3, 0) * (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) +
    1366     7131215 :                                 m(3, 1) * (m(0, 3) * m(1, 0) - m(0, 0) * m(1, 3)));
    1367    15688673 :                 out(2, 3) = d * (m(0, 3) * (m(1, 1) * m(2, 0) - m(1, 0) * m(2, 1)) +
    1368     7131215 :                                 m(0, 0) * (m(1, 3) * m(2, 1) - m(1, 1) * m(2, 3)) +
    1369     7131215 :                                 m(0, 1) * (m(1, 0) * m(2, 3) - m(1, 3) * m(2, 0)));
    1370    15688673 :                 out(3, 0) = d * (m(1, 0) * (m(2, 2) * m(3, 1) - m(2, 1) * m(3, 2)) +
    1371     7131215 :                                 m(1, 1) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
    1372     7131215 :                                 m(1, 2) * (m(2, 1) * m(3, 0) - m(2, 0) * m(3, 1)));
    1373    15688673 :                 out(3, 1) = d * (m(2, 0) * (m(0, 2) * m(3, 1) - m(0, 1) * m(3, 2)) +
    1374     7131215 :                                 m(2, 1) * (m(0, 0) * m(3, 2) - m(0, 2) * m(3, 0)) +
    1375     7131215 :                                 m(2, 2) * (m(0, 1) * m(3, 0) - m(0, 0) * m(3, 1)));
    1376    15688673 :                 out(3, 2) = d * (m(3, 0) * (m(0, 2) * m(1, 1) - m(0, 1) * m(1, 2)) +
    1377     7131215 :                                 m(3, 1) * (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) +
    1378     7131215 :                                 m(3, 2) * (m(0, 1) * m(1, 0) - m(0, 0) * m(1, 1)));
    1379    15688673 :                 out(3, 3) = d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) +
    1380     7131215 :                                 m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) +
    1381     7131215 :                                 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     1426243 :                 return true;
    1387             :         }
    1388             : 
    1389             : 
    1390             :         //! Inverts a primitive matrix which only contains a translation and a rotation
    1391             :         //! \param out: where result matrix is written to.
    1392             :         template <class T>
    1393             :         inline bool CMatrix4<T>::getInversePrimitive ( CMatrix4<T>& out ) const
    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             : 
    1421             :         /*!
    1422             :         */
    1423             :         template <class T>
    1424     1426078 :         inline bool CMatrix4<T>::makeInverse()
    1425             :         {
    1426             : #if defined ( USE_MATRIX_TEST )
    1427             :                 if (definitelyIdentityMatrix)
    1428             :                         return true;
    1429             : #endif
    1430     1426078 :                 CMatrix4<T> temp ( EM4CONST_NOTHING );
    1431             : 
    1432     1426078 :                 if (getInverse(temp))
    1433             :                 {
    1434     1426078 :                         *this = temp;
    1435     1426078 :                         return true;
    1436             :                 }
    1437             : 
    1438           0 :                 return false;
    1439             :         }
    1440             : 
    1441             : 
    1442             :         template <class T>
    1443    11892038 :         inline CMatrix4<T>& CMatrix4<T>::operator=(const CMatrix4<T> &other)
    1444             :         {
    1445    11892038 :                 if (this==&other)
    1446           0 :                         return *this;
    1447    11892038 :                 memcpy(M, other.M, 16*sizeof(T));
    1448             : #if defined ( USE_MATRIX_TEST )
    1449             :                 definitelyIdentityMatrix=other.definitelyIdentityMatrix;
    1450             : #endif
    1451    11892038 :                 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           0 :         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           0 :                 for (s32 i = 0; i < 16; ++i)
    1476           0 :                         if (M[i] != other.M[i])
    1477           0 :                                 return false;
    1478             : 
    1479           0 :                 return true;
    1480             :         }
    1481             : 
    1482             : 
    1483             :         template <class T>
    1484           0 :         inline bool CMatrix4<T>::operator!=(const CMatrix4<T> &other) const
    1485             :         {
    1486           0 :                 return !(*this == other);
    1487             :         }
    1488             : 
    1489             : 
    1490             :         // Builds a right-handed perspective projection matrix based on a field of view
    1491             :         template <class T>
    1492             :         inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovRH(
    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>
    1531             :         inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovLH(
    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>
    1568             :         inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovInfinityLH(
    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>
    1604           1 :         inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoLH(
    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           1 :                 M[0] = (T)(2/widthOfViewVolume);
    1611           1 :                 M[1] = 0;
    1612           1 :                 M[2] = 0;
    1613           1 :                 M[3] = 0;
    1614             : 
    1615           1 :                 M[4] = 0;
    1616           1 :                 M[5] = (T)(2/heightOfViewVolume);
    1617           1 :                 M[6] = 0;
    1618           1 :                 M[7] = 0;
    1619             : 
    1620           1 :                 M[8] = 0;
    1621           1 :                 M[9] = 0;
    1622           1 :                 M[10] = (T)(1/(zFar-zNear));
    1623           1 :                 M[11] = 0;
    1624             : 
    1625           1 :                 M[12] = 0;
    1626           1 :                 M[13] = 0;
    1627           1 :                 M[14] = (T)(zNear/(zNear-zFar));
    1628           1 :                 M[15] = 1;
    1629             : 
    1630             : #if defined ( USE_MATRIX_TEST )
    1631             :                 definitelyIdentityMatrix=false;
    1632             : #endif
    1633           1 :                 return *this;
    1634             :         }
    1635             : 
    1636             : 
    1637             :         // Builds a right-handed orthogonal projection matrix.
    1638             :         template <class T>
    1639             :         inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoRH(
    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>
    1674             :         inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveRH(
    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>
    1709             :         inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveLH(
    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>
    1743             :         inline CMatrix4<T>& CMatrix4<T>::buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point)
    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>
    1775             :         inline CMatrix4<T>& CMatrix4<T>::buildCameraLookAtMatrixLH(
    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>
    1816             :         inline CMatrix4<T>& CMatrix4<T>::buildCameraLookAtMatrixRH(
    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>
    1857             :         inline CMatrix4<T> CMatrix4<T>::interpolate(const core::CMatrix4<T>& b, f32 time) const
    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>
    1874     1426078 :         inline CMatrix4<T> CMatrix4<T>::getTransposed() const
    1875             :         {
    1876     1426078 :                 CMatrix4<T> t ( EM4CONST_NOTHING );
    1877     1426078 :                 getTransposed ( t );
    1878     1426078 :                 return t;
    1879             :         }
    1880             : 
    1881             : 
    1882             :         // returns transposed matrix
    1883             :         template <class T>
    1884     1426078 :         inline void CMatrix4<T>::getTransposed( CMatrix4<T>& o ) const
    1885             :         {
    1886     1426078 :                 o[ 0] = M[ 0];
    1887     1426078 :                 o[ 1] = M[ 4];
    1888     1426078 :                 o[ 2] = M[ 8];
    1889     1426078 :                 o[ 3] = M[12];
    1890             : 
    1891     1426078 :                 o[ 4] = M[ 1];
    1892     1426078 :                 o[ 5] = M[ 5];
    1893     1426078 :                 o[ 6] = M[ 9];
    1894     1426078 :                 o[ 7] = M[13];
    1895             : 
    1896     1426078 :                 o[ 8] = M[ 2];
    1897     1426078 :                 o[ 9] = M[ 6];
    1898     1426078 :                 o[10] = M[10];
    1899     1426078 :                 o[11] = M[14];
    1900             : 
    1901     1426078 :                 o[12] = M[ 3];
    1902     1426078 :                 o[13] = M[ 7];
    1903     1426078 :                 o[14] = M[11];
    1904     1426078 :                 o[15] = M[15];
    1905             : #if defined ( USE_MATRIX_TEST )
    1906             :                 o.definitelyIdentityMatrix=definitelyIdentityMatrix;
    1907             : #endif
    1908     1426078 :         }
    1909             : 
    1910             : 
    1911             :         // used to scale <-1,-1><1,1> to viewport
    1912             :         template <class T>
    1913             :         inline CMatrix4<T>& CMatrix4<T>::buildNDCToDCMatrix( const core::rect<s32>& viewport, f32 zScale)
    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             : 
    1927             :         //! Builds a matrix that rotates from one vector to another
    1928             :         /** \param from: vector to rotate from
    1929             :         \param to: vector to rotate to
    1930             : 
    1931             :                 http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm
    1932             :          */
    1933             :         template <class T>
    1934       53120 :         inline CMatrix4<T>& CMatrix4<T>::buildRotateFromTo(const core::vector3df& from, const core::vector3df& to)
    1935             :         {
    1936             :                 // unit vectors
    1937       53120 :                 core::vector3df f(from);
    1938       53120 :                 core::vector3df t(to);
    1939       53120 :                 f.normalize();
    1940       53120 :                 t.normalize();
    1941             : 
    1942             :                 // axis multiplication by sin
    1943       53120 :                 core::vector3df vs(t.crossProduct(f));
    1944             : 
    1945             :                 // axis of rotation
    1946       53120 :                 core::vector3df v(vs);
    1947       53120 :                 v.normalize();
    1948             : 
    1949             :                 // cosinus angle
    1950       53120 :                 T ca = f.dotProduct(t);
    1951             : 
    1952       53120 :                 core::vector3df vt(v * (1 - ca));
    1953             : 
    1954       53120 :                 M[0] = vt.X * v.X + ca;
    1955       53120 :                 M[5] = vt.Y * v.Y + ca;
    1956       53120 :                 M[10] = vt.Z * v.Z + ca;
    1957             : 
    1958       53120 :                 vt.X *= v.Y;
    1959       53120 :                 vt.Z *= v.X;
    1960       53120 :                 vt.Y *= v.Z;
    1961             : 
    1962       53120 :                 M[1] = vt.X - vs.Z;
    1963       53120 :                 M[2] = vt.Z + vs.Y;
    1964       53120 :                 M[3] = 0;
    1965             : 
    1966       53120 :                 M[4] = vt.X + vs.Z;
    1967       53120 :                 M[6] = vt.Y - vs.X;
    1968       53120 :                 M[7] = 0;
    1969             : 
    1970       53120 :                 M[8] = vt.Z - vs.Y;
    1971       53120 :                 M[9] = vt.Y + vs.X;
    1972       53120 :                 M[11] = 0;
    1973             : 
    1974       53120 :                 M[12] = 0;
    1975       53120 :                 M[13] = 0;
    1976       53120 :                 M[14] = 0;
    1977       53120 :                 M[15] = 1;
    1978             : 
    1979       53120 :                 return *this;
    1980             :         }
    1981             : 
    1982             :         //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis
    1983             :         /** \param camPos: viewer position in world coord
    1984             :         \param center: object position in world-coord, rotation pivot
    1985             :         \param translation: object final translation from center
    1986             :         \param axis: axis to rotate about
    1987             :         \param from: source vector to rotate from
    1988             :          */
    1989             :         template <class T>
    1990             :         inline void CMatrix4<T>::buildAxisAlignedBillboard(
    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             : 
    2039             :         //! Builds a combined matrix which translate to a center before rotation and translate afterwards
    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             : 
    2052             :         /*!
    2053             :                 Generate texture coordinates as linear functions so that:
    2054             :                         u = Ux*x + Uy*y + Uz*z + Uw
    2055             :                         v = Vx*x + Vy*y + Vz*z + Vw
    2056             :                 The matrix M for this case is:
    2057             :                         Ux  Vx  0  0
    2058             :                         Uy  Vy  0  0
    2059             :                         Uz  Vz  0  0
    2060             :                         Uw  Vw  0  0
    2061             :         */
    2062             : 
    2063             : 
    2064             :         template <class T>
    2065             :         inline CMatrix4<T>& CMatrix4<T>::buildTextureTransform( f32 rotateRad,
    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>
    2101             :         inline CMatrix4<T>& CMatrix4<T>::setTextureRotationCenter( f32 rotateRad )
    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>
    2122           0 :         inline CMatrix4<T>& CMatrix4<T>::setTextureTranslate ( f32 x, f32 y )
    2123             :         {
    2124           0 :                 M[8] = (T)x;
    2125           0 :                 M[9] = (T)y;
    2126             : 
    2127             : #if defined ( USE_MATRIX_TEST )
    2128             :                 definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f);
    2129             : #endif
    2130           0 :                 return *this;
    2131             :         }
    2132             : 
    2133             : 
    2134             :         template <class T>
    2135             :         inline CMatrix4<T>& CMatrix4<T>::setTextureTranslateTransposed ( f32 x, f32 y )
    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>
    2147           0 :         inline CMatrix4<T>& CMatrix4<T>::setTextureScale ( f32 sx, f32 sy )
    2148             :         {
    2149           0 :                 M[0] = (T)sx;
    2150           0 :                 M[5] = (T)sy;
    2151             : #if defined ( USE_MATRIX_TEST )
    2152             :                 definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
    2153             : #endif
    2154           0 :                 return *this;
    2155             :         }
    2156             : 
    2157             : 
    2158             :         template <class T>
    2159             :         inline CMatrix4<T>& CMatrix4<T>::setTextureScaleCenter( f32 sx, f32 sy )
    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>
    2198             :         inline bool CMatrix4<T>::getDefinitelyIdentityMatrix() const
    2199             :         {
    2200             : #if defined ( USE_MATRIX_TEST )
    2201             :                 return definitelyIdentityMatrix;
    2202             : #else
    2203             :                 return false;
    2204             : #endif
    2205             :         }
    2206             : 
    2207             : 
    2208             :         //! Compare two matrices using the equal method
    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             : 
    2232             :         //! Typedef for f32 matrix
    2233             :         typedef CMatrix4<f32> matrix4;
    2234             : 
    2235             :         //! global const identity matrix
    2236             :         IRRLICHT_API extern const matrix4 IdentityMatrix;
    2237             : 
    2238             : } // end namespace core
    2239             : } // end namespace irr
    2240             : 
    2241             : #endif
    2242             : 

Generated by: LCOV version 1.11