From 7028cbe09c688437910a25623098762bf0fa592d Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Mon, 28 Mar 2016 22:28:34 +1000 Subject: Move Irrlicht to src/others. --- .../irrlicht-1.8.1/doc/html/matrix4_8h_source.html | 2179 ++++++++++++++++++++ 1 file changed, 2179 insertions(+) create mode 100644 src/others/irrlicht-1.8.1/doc/html/matrix4_8h_source.html (limited to 'src/others/irrlicht-1.8.1/doc/html/matrix4_8h_source.html') diff --git a/src/others/irrlicht-1.8.1/doc/html/matrix4_8h_source.html b/src/others/irrlicht-1.8.1/doc/html/matrix4_8h_source.html new file mode 100644 index 0000000..c41bf13 --- /dev/null +++ b/src/others/irrlicht-1.8.1/doc/html/matrix4_8h_source.html @@ -0,0 +1,2179 @@ + + + + +Irrlicht 3D Engine: matrix4.h Source File + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + + + + + +
+
Irrlicht 3D Engine + +
+ +
+ + + + + + +
+
+
+ + + + +
+
+ +
+
+
+ +
+
+
+
matrix4.h
+
+
+Go to the documentation of this file.
00001 // Copyright (C) 2002-2012 Nikolaus Gebhardt
+00002 // This file is part of the "Irrlicht Engine".
+00003 // For conditions of distribution and use, see copyright notice in irrlicht.h
+00004 
+00005 #ifndef __IRR_MATRIX_H_INCLUDED__
+00006 #define __IRR_MATRIX_H_INCLUDED__
+00007 
+00008 #include "irrMath.h"
+00009 #include "vector3d.h"
+00010 #include "vector2d.h"
+00011 #include "plane3d.h"
+00012 #include "aabbox3d.h"
+00013 #include "rect.h"
+00014 #include "irrString.h"
+00015 
+00016 // enable this to keep track of changes to the matrix
+00017 // and make simpler identity check for seldomly changing matrices
+00018 // otherwise identity check will always compare the elements
+00019 //#define USE_MATRIX_TEST
+00020 
+00021 // this is only for debugging purposes
+00022 //#define USE_MATRIX_TEST_DEBUG
+00023 
+00024 #if defined( USE_MATRIX_TEST_DEBUG )
+00025 
+00026 struct MatrixTest
+00027 {
+00028     MatrixTest () : ID(0), Calls(0) {}
+00029     char buf[256];
+00030     int Calls;
+00031     int ID;
+00032 };
+00033 static MatrixTest MTest;
+00034 
+00035 #endif
+00036 
+00037 namespace irr
+00038 {
+00039 namespace core
+00040 {
+00041 
+00043 
+00044     template <class T>
+00045     class CMatrix4
+00046     {
+00047         public:
+00048 
+00050             enum eConstructor
+00051             {
+00052                 EM4CONST_NOTHING = 0,
+00053                 EM4CONST_COPY,
+00054                 EM4CONST_IDENTITY,
+00055                 EM4CONST_TRANSPOSED,
+00056                 EM4CONST_INVERSE,
+00057                 EM4CONST_INVERSE_TRANSPOSED
+00058             };
+00059 
+00061 
+00062             CMatrix4( eConstructor constructor = EM4CONST_IDENTITY );
+00064 
+00066             CMatrix4(const CMatrix4<T>& other, eConstructor constructor = EM4CONST_COPY);
+00067 
+00069             T& operator()(const s32 row, const s32 col)
+00070             {
+00071 #if defined ( USE_MATRIX_TEST )
+00072                 definitelyIdentityMatrix=false;
+00073 #endif
+00074                 return M[ row * 4 + col ];
+00075             }
+00076 
+00078             const T& operator()(const s32 row, const s32 col) const { return M[row * 4 + col]; }
+00079 
+00081             T& operator[](u32 index)
+00082             {
+00083 #if defined ( USE_MATRIX_TEST )
+00084                 definitelyIdentityMatrix=false;
+00085 #endif
+00086                 return M[index];
+00087             }
+00088 
+00090             const T& operator[](u32 index) const { return M[index]; }
+00091 
+00093             inline CMatrix4<T>& operator=(const CMatrix4<T> &other);
+00094 
+00096             inline CMatrix4<T>& operator=(const T& scalar);
+00097 
+00099             const T* pointer() const { return M; }
+00100             T* pointer()
+00101             {
+00102 #if defined ( USE_MATRIX_TEST )
+00103                 definitelyIdentityMatrix=false;
+00104 #endif
+00105                 return M;
+00106             }
+00107 
+00109             bool operator==(const CMatrix4<T> &other) const;
+00110 
+00112             bool operator!=(const CMatrix4<T> &other) const;
+00113 
+00115             CMatrix4<T> operator+(const CMatrix4<T>& other) const;
+00116 
+00118             CMatrix4<T>& operator+=(const CMatrix4<T>& other);
+00119 
+00121             CMatrix4<T> operator-(const CMatrix4<T>& other) const;
+00122 
+00124             CMatrix4<T>& operator-=(const CMatrix4<T>& other);
+00125 
+00127 
+00128             inline CMatrix4<T>& setbyproduct(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
+00129 
+00131 
+00133             CMatrix4<T>& setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
+00134 
+00136 
+00137             CMatrix4<T> operator*(const CMatrix4<T>& other) const;
+00138 
+00140 
+00141             CMatrix4<T>& operator*=(const CMatrix4<T>& other);
+00142 
+00144             CMatrix4<T> operator*(const T& scalar) const;
+00145 
+00147             CMatrix4<T>& operator*=(const T& scalar);
+00148 
+00150             inline CMatrix4<T>& makeIdentity();
+00151 
+00153             inline bool isIdentity() const;
+00154 
+00156             inline bool isOrthogonal() const;
+00157 
+00159             bool isIdentity_integer_base () const;
+00160 
+00162             CMatrix4<T>& setTranslation( const vector3d<T>& translation );
+00163 
+00165             vector3d<T> getTranslation() const;
+00166 
+00168             CMatrix4<T>& setInverseTranslation( const vector3d<T>& translation );
+00169 
+00171             inline CMatrix4<T>& setRotationRadians( const vector3d<T>& rotation );
+00172 
+00174             CMatrix4<T>& setRotationDegrees( const vector3d<T>& rotation );
+00175 
+00177 
+00178             core::vector3d<T> getRotationDegrees() const;
+00179 
+00181 
+00182             inline CMatrix4<T>& setInverseRotationRadians( const vector3d<T>& rotation );
+00183 
+00185 
+00186             inline CMatrix4<T>& setInverseRotationDegrees( const vector3d<T>& rotation );
+00187 
+00189 
+00190             inline CMatrix4<T>& setRotationAxisRadians(const T& angle, const vector3d<T>& axis);
+00191 
+00193             CMatrix4<T>& setScale( const vector3d<T>& scale );
+00194 
+00196             CMatrix4<T>& setScale( const T scale ) { return setScale(core::vector3d<T>(scale,scale,scale)); }
+00197 
+00199             core::vector3d<T> getScale() const;
+00200 
+00202             void inverseTranslateVect( vector3df& vect ) const;
+00203 
+00205             void inverseRotateVect( vector3df& vect ) const;
+00206 
+00208             void rotateVect( vector3df& vect ) const;
+00209 
+00211             void rotateVect(core::vector3df& out, const core::vector3df& in) const;
+00212 
+00214             void rotateVect(T *out,const core::vector3df &in) const;
+00215 
+00217             void transformVect( vector3df& vect) const;
+00218 
+00220             void transformVect( vector3df& out, const vector3df& in ) const;
+00221 
+00223             void transformVect(T *out,const core::vector3df &in) const;
+00224 
+00226             void transformVec3(T *out, const T * in) const;
+00227 
+00229             void translateVect( vector3df& vect ) const;
+00230 
+00232             void transformPlane( core::plane3d<f32> &plane) const;
+00233 
+00235             void transformPlane( const core::plane3d<f32> &in, core::plane3d<f32> &out) const;
+00236 
+00238 
+00240             void transformBox(core::aabbox3d<f32>& box) const;
+00241 
+00243 
+00245             void transformBoxEx(core::aabbox3d<f32>& box) const;
+00246 
+00248             void multiplyWith1x4Matrix(T* matrix) const;
+00249 
+00251 
+00252             bool makeInverse();
+00253 
+00254 
+00256 
+00257             bool getInversePrimitive ( CMatrix4<T>& out ) const;
+00258 
+00260 
+00262             bool getInverse(CMatrix4<T>& out) const;
+00263 
+00265             CMatrix4<T>& buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
+00266 
+00268             CMatrix4<T>& buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
+00269 
+00271             CMatrix4<T>& buildProjectionMatrixPerspectiveFovInfinityLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon=0);
+00272 
+00274             CMatrix4<T>& buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
+00275 
+00277             CMatrix4<T>& buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
+00278 
+00280             CMatrix4<T>& buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
+00281 
+00283             CMatrix4<T>& buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
+00284 
+00286             CMatrix4<T>& buildCameraLookAtMatrixLH(
+00287                     const vector3df& position,
+00288                     const vector3df& target,
+00289                     const vector3df& upVector);
+00290 
+00292             CMatrix4<T>& buildCameraLookAtMatrixRH(
+00293                     const vector3df& position,
+00294                     const vector3df& target,
+00295                     const vector3df& upVector);
+00296 
+00298 
+00302             CMatrix4<T>& buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point=1.0f);
+00303 
+00305 
+00306             CMatrix4<T>& buildNDCToDCMatrix( const core::rect<s32>& area, f32 zScale);
+00307 
+00309 
+00311             CMatrix4<T> interpolate(const core::CMatrix4<T>& b, f32 time) const;
+00312 
+00314             CMatrix4<T> getTransposed() const;
+00315 
+00317             inline void getTransposed( CMatrix4<T>& dest ) const;
+00318 
+00320 
+00323             CMatrix4<T>& buildRotateFromTo(const core::vector3df& from, const core::vector3df& to);
+00324 
+00326 
+00329             void setRotationCenter(const core::vector3df& center, const core::vector3df& translate);
+00330 
+00332 
+00338             void buildAxisAlignedBillboard(const core::vector3df& camPos,
+00339                         const core::vector3df& center,
+00340                         const core::vector3df& translation,
+00341                         const core::vector3df& axis,
+00342                         const core::vector3df& from);
+00343 
+00344             /*
+00345                 construct 2D Texture transformations
+00346                 rotate about center, scale, and transform.
+00347             */
+00349             CMatrix4<T>& buildTextureTransform( f32 rotateRad,
+00350                     const core::vector2df &rotatecenter,
+00351                     const core::vector2df &translate,
+00352                     const core::vector2df &scale);
+00353 
+00355 
+00359             CMatrix4<T>& setTextureRotationCenter( f32 radAngle );
+00360 
+00362 
+00366             CMatrix4<T>& setTextureTranslate( f32 x, f32 y );
+00367 
+00369 
+00373             CMatrix4<T>& setTextureTranslateTransposed( f32 x, f32 y );
+00374 
+00376 
+00380             CMatrix4<T>& setTextureScale( f32 sx, f32 sy );
+00381 
+00383 
+00387             CMatrix4<T>& setTextureScaleCenter( f32 sx, f32 sy );
+00388 
+00390             CMatrix4<T>& setM(const T* data);
+00391 
+00393             void setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix);
+00394 
+00396             bool getDefinitelyIdentityMatrix() const;
+00397 
+00399             bool equals(const core::CMatrix4<T>& other, const T tolerance=(T)ROUNDING_ERROR_f64) const;
+00400 
+00401         private:
+00403             T M[16];
+00404 #if defined ( USE_MATRIX_TEST )
+00405 
+00406             mutable u32 definitelyIdentityMatrix;
+00407 #endif
+00408 #if defined ( USE_MATRIX_TEST_DEBUG )
+00409             u32 id;
+00410             mutable u32 calls;
+00411 #endif
+00412 
+00413     };
+00414 
+00415     // Default constructor
+00416     template <class T>
+00417     inline CMatrix4<T>::CMatrix4( eConstructor constructor )
+00418 #if defined ( USE_MATRIX_TEST )
+00419         : definitelyIdentityMatrix(BIT_UNTESTED)
+00420 #endif
+00421 #if defined ( USE_MATRIX_TEST_DEBUG )
+00422         ,id ( MTest.ID++), calls ( 0 )
+00423 #endif
+00424     {
+00425         switch ( constructor )
+00426         {
+00427             case EM4CONST_NOTHING:
+00428             case EM4CONST_COPY:
+00429                 break;
+00430             case EM4CONST_IDENTITY:
+00431             case EM4CONST_INVERSE:
+00432             default:
+00433                 makeIdentity();
+00434                 break;
+00435         }
+00436     }
+00437 
+00438     // Copy constructor
+00439     template <class T>
+00440     inline CMatrix4<T>::CMatrix4( const CMatrix4<T>& other, eConstructor constructor)
+00441 #if defined ( USE_MATRIX_TEST )
+00442         : definitelyIdentityMatrix(BIT_UNTESTED)
+00443 #endif
+00444 #if defined ( USE_MATRIX_TEST_DEBUG )
+00445         ,id ( MTest.ID++), calls ( 0 )
+00446 #endif
+00447     {
+00448         switch ( constructor )
+00449         {
+00450             case EM4CONST_IDENTITY:
+00451                 makeIdentity();
+00452                 break;
+00453             case EM4CONST_NOTHING:
+00454                 break;
+00455             case EM4CONST_COPY:
+00456                 *this = other;
+00457                 break;
+00458             case EM4CONST_TRANSPOSED:
+00459                 other.getTransposed(*this);
+00460                 break;
+00461             case EM4CONST_INVERSE:
+00462                 if (!other.getInverse(*this))
+00463                     memset(M, 0, 16*sizeof(T));
+00464                 break;
+00465             case EM4CONST_INVERSE_TRANSPOSED:
+00466                 if (!other.getInverse(*this))
+00467                     memset(M, 0, 16*sizeof(T));
+00468                 else
+00469                     *this=getTransposed();
+00470                 break;
+00471         }
+00472     }
+00473 
+00475     template <class T>
+00476     inline CMatrix4<T> CMatrix4<T>::operator+(const CMatrix4<T>& other) const
+00477     {
+00478         CMatrix4<T> temp ( EM4CONST_NOTHING );
+00479 
+00480         temp[0] = M[0]+other[0];
+00481         temp[1] = M[1]+other[1];
+00482         temp[2] = M[2]+other[2];
+00483         temp[3] = M[3]+other[3];
+00484         temp[4] = M[4]+other[4];
+00485         temp[5] = M[5]+other[5];
+00486         temp[6] = M[6]+other[6];
+00487         temp[7] = M[7]+other[7];
+00488         temp[8] = M[8]+other[8];
+00489         temp[9] = M[9]+other[9];
+00490         temp[10] = M[10]+other[10];
+00491         temp[11] = M[11]+other[11];
+00492         temp[12] = M[12]+other[12];
+00493         temp[13] = M[13]+other[13];
+00494         temp[14] = M[14]+other[14];
+00495         temp[15] = M[15]+other[15];
+00496 
+00497         return temp;
+00498     }
+00499 
+00501     template <class T>
+00502     inline CMatrix4<T>& CMatrix4<T>::operator+=(const CMatrix4<T>& other)
+00503     {
+00504         M[0]+=other[0];
+00505         M[1]+=other[1];
+00506         M[2]+=other[2];
+00507         M[3]+=other[3];
+00508         M[4]+=other[4];
+00509         M[5]+=other[5];
+00510         M[6]+=other[6];
+00511         M[7]+=other[7];
+00512         M[8]+=other[8];
+00513         M[9]+=other[9];
+00514         M[10]+=other[10];
+00515         M[11]+=other[11];
+00516         M[12]+=other[12];
+00517         M[13]+=other[13];
+00518         M[14]+=other[14];
+00519         M[15]+=other[15];
+00520 
+00521         return *this;
+00522     }
+00523 
+00525     template <class T>
+00526     inline CMatrix4<T> CMatrix4<T>::operator-(const CMatrix4<T>& other) const
+00527     {
+00528         CMatrix4<T> temp ( EM4CONST_NOTHING );
+00529 
+00530         temp[0] = M[0]-other[0];
+00531         temp[1] = M[1]-other[1];
+00532         temp[2] = M[2]-other[2];
+00533         temp[3] = M[3]-other[3];
+00534         temp[4] = M[4]-other[4];
+00535         temp[5] = M[5]-other[5];
+00536         temp[6] = M[6]-other[6];
+00537         temp[7] = M[7]-other[7];
+00538         temp[8] = M[8]-other[8];
+00539         temp[9] = M[9]-other[9];
+00540         temp[10] = M[10]-other[10];
+00541         temp[11] = M[11]-other[11];
+00542         temp[12] = M[12]-other[12];
+00543         temp[13] = M[13]-other[13];
+00544         temp[14] = M[14]-other[14];
+00545         temp[15] = M[15]-other[15];
+00546 
+00547         return temp;
+00548     }
+00549 
+00551     template <class T>
+00552     inline CMatrix4<T>& CMatrix4<T>::operator-=(const CMatrix4<T>& other)
+00553     {
+00554         M[0]-=other[0];
+00555         M[1]-=other[1];
+00556         M[2]-=other[2];
+00557         M[3]-=other[3];
+00558         M[4]-=other[4];
+00559         M[5]-=other[5];
+00560         M[6]-=other[6];
+00561         M[7]-=other[7];
+00562         M[8]-=other[8];
+00563         M[9]-=other[9];
+00564         M[10]-=other[10];
+00565         M[11]-=other[11];
+00566         M[12]-=other[12];
+00567         M[13]-=other[13];
+00568         M[14]-=other[14];
+00569         M[15]-=other[15];
+00570 
+00571         return *this;
+00572     }
+00573 
+00575     template <class T>
+00576     inline CMatrix4<T> CMatrix4<T>::operator*(const T& scalar) const
+00577     {
+00578         CMatrix4<T> temp ( EM4CONST_NOTHING );
+00579 
+00580         temp[0] = M[0]*scalar;
+00581         temp[1] = M[1]*scalar;
+00582         temp[2] = M[2]*scalar;
+00583         temp[3] = M[3]*scalar;
+00584         temp[4] = M[4]*scalar;
+00585         temp[5] = M[5]*scalar;
+00586         temp[6] = M[6]*scalar;
+00587         temp[7] = M[7]*scalar;
+00588         temp[8] = M[8]*scalar;
+00589         temp[9] = M[9]*scalar;
+00590         temp[10] = M[10]*scalar;
+00591         temp[11] = M[11]*scalar;
+00592         temp[12] = M[12]*scalar;
+00593         temp[13] = M[13]*scalar;
+00594         temp[14] = M[14]*scalar;
+00595         temp[15] = M[15]*scalar;
+00596 
+00597         return temp;
+00598     }
+00599 
+00601     template <class T>
+00602     inline CMatrix4<T>& CMatrix4<T>::operator*=(const T& scalar)
+00603     {
+00604         M[0]*=scalar;
+00605         M[1]*=scalar;
+00606         M[2]*=scalar;
+00607         M[3]*=scalar;
+00608         M[4]*=scalar;
+00609         M[5]*=scalar;
+00610         M[6]*=scalar;
+00611         M[7]*=scalar;
+00612         M[8]*=scalar;
+00613         M[9]*=scalar;
+00614         M[10]*=scalar;
+00615         M[11]*=scalar;
+00616         M[12]*=scalar;
+00617         M[13]*=scalar;
+00618         M[14]*=scalar;
+00619         M[15]*=scalar;
+00620 
+00621         return *this;
+00622     }
+00623 
+00625     template <class T>
+00626     inline CMatrix4<T>& CMatrix4<T>::operator*=(const CMatrix4<T>& other)
+00627     {
+00628 #if defined ( USE_MATRIX_TEST )
+00629         // do checks on your own in order to avoid copy creation
+00630         if ( !other.isIdentity() )
+00631         {
+00632             if ( this->isIdentity() )
+00633             {
+00634                 return (*this = other);
+00635             }
+00636             else
+00637             {
+00638                 CMatrix4<T> temp ( *this );
+00639                 return setbyproduct_nocheck( temp, other );
+00640             }
+00641         }
+00642         return *this;
+00643 #else
+00644         CMatrix4<T> temp ( *this );
+00645         return setbyproduct_nocheck( temp, other );
+00646 #endif
+00647     }
+00648 
+00650     // set this matrix to the product of two other matrices
+00651     // goal is to reduce stack use and copy
+00652     template <class T>
+00653     inline CMatrix4<T>& CMatrix4<T>::setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b )
+00654     {
+00655         const T *m1 = other_a.M;
+00656         const T *m2 = other_b.M;
+00657 
+00658         M[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
+00659         M[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
+00660         M[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
+00661         M[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
+00662 
+00663         M[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
+00664         M[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
+00665         M[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
+00666         M[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
+00667 
+00668         M[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
+00669         M[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
+00670         M[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
+00671         M[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
+00672 
+00673         M[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
+00674         M[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
+00675         M[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
+00676         M[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
+00677 #if defined ( USE_MATRIX_TEST )
+00678         definitelyIdentityMatrix=false;
+00679 #endif
+00680         return *this;
+00681     }
+00682 
+00683 
+00685     // set this matrix to the product of two other matrices
+00686     // goal is to reduce stack use and copy
+00687     template <class T>
+00688     inline CMatrix4<T>& CMatrix4<T>::setbyproduct(const CMatrix4<T>& other_a, const CMatrix4<T>& other_b )
+00689     {
+00690 #if defined ( USE_MATRIX_TEST )
+00691         if ( other_a.isIdentity () )
+00692             return (*this = other_b);
+00693         else
+00694         if ( other_b.isIdentity () )
+00695             return (*this = other_a);
+00696         else
+00697             return setbyproduct_nocheck(other_a,other_b);
+00698 #else
+00699         return setbyproduct_nocheck(other_a,other_b);
+00700 #endif
+00701     }
+00702 
+00704     template <class T>
+00705     inline CMatrix4<T> CMatrix4<T>::operator*(const CMatrix4<T>& m2) const
+00706     {
+00707 #if defined ( USE_MATRIX_TEST )
+00708         // Testing purpose..
+00709         if ( this->isIdentity() )
+00710             return m2;
+00711         if ( m2.isIdentity() )
+00712             return *this;
+00713 #endif
+00714 
+00715         CMatrix4<T> m3 ( EM4CONST_NOTHING );
+00716 
+00717         const T *m1 = M;
+00718 
+00719         m3[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
+00720         m3[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
+00721         m3[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
+00722         m3[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
+00723 
+00724         m3[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
+00725         m3[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
+00726         m3[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
+00727         m3[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
+00728 
+00729         m3[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
+00730         m3[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
+00731         m3[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
+00732         m3[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
+00733 
+00734         m3[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
+00735         m3[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
+00736         m3[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
+00737         m3[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
+00738         return m3;
+00739     }
+00740 
+00741 
+00742 
+00743     template <class T>
+00744     inline vector3d<T> CMatrix4<T>::getTranslation() const
+00745     {
+00746         return vector3d<T>(M[12], M[13], M[14]);
+00747     }
+00748 
+00749 
+00750     template <class T>
+00751     inline CMatrix4<T>& CMatrix4<T>::setTranslation( const vector3d<T>& translation )
+00752     {
+00753         M[12] = translation.X;
+00754         M[13] = translation.Y;
+00755         M[14] = translation.Z;
+00756 #if defined ( USE_MATRIX_TEST )
+00757         definitelyIdentityMatrix=false;
+00758 #endif
+00759         return *this;
+00760     }
+00761 
+00762     template <class T>
+00763     inline CMatrix4<T>& CMatrix4<T>::setInverseTranslation( const vector3d<T>& translation )
+00764     {
+00765         M[12] = -translation.X;
+00766         M[13] = -translation.Y;
+00767         M[14] = -translation.Z;
+00768 #if defined ( USE_MATRIX_TEST )
+00769         definitelyIdentityMatrix=false;
+00770 #endif
+00771         return *this;
+00772     }
+00773 
+00774     template <class T>
+00775     inline CMatrix4<T>& CMatrix4<T>::setScale( const vector3d<T>& scale )
+00776     {
+00777         M[0] = scale.X;
+00778         M[5] = scale.Y;
+00779         M[10] = scale.Z;
+00780 #if defined ( USE_MATRIX_TEST )
+00781         definitelyIdentityMatrix=false;
+00782 #endif
+00783         return *this;
+00784     }
+00785 
+00787 
+00794     template <class T>
+00795     inline vector3d<T> CMatrix4<T>::getScale() const
+00796     {
+00797         // See http://www.robertblum.com/articles/2005/02/14/decomposing-matrices
+00798 
+00799         // Deal with the 0 rotation case first
+00800         // Prior to Irrlicht 1.6, we always returned this value.
+00801         if(core::iszero(M[1]) && core::iszero(M[2]) &&
+00802             core::iszero(M[4]) && core::iszero(M[6]) &&
+00803             core::iszero(M[8]) && core::iszero(M[9]))
+00804             return vector3d<T>(M[0], M[5], M[10]);
+00805 
+00806         // We have to do the full calculation.
+00807         return vector3d<T>(sqrtf(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]),
+00808                             sqrtf(M[4] * M[4] + M[5] * M[5] + M[6] * M[6]),
+00809                             sqrtf(M[8] * M[8] + M[9] * M[9] + M[10] * M[10]));
+00810     }
+00811 
+00812     template <class T>
+00813     inline CMatrix4<T>& CMatrix4<T>::setRotationDegrees( const vector3d<T>& rotation )
+00814     {
+00815         return setRotationRadians( rotation * core::DEGTORAD );
+00816     }
+00817 
+00818     template <class T>
+00819     inline CMatrix4<T>& CMatrix4<T>::setInverseRotationDegrees( const vector3d<T>& rotation )
+00820     {
+00821         return setInverseRotationRadians( rotation * core::DEGTORAD );
+00822     }
+00823 
+00824     template <class T>
+00825     inline CMatrix4<T>& CMatrix4<T>::setRotationRadians( const vector3d<T>& rotation )
+00826     {
+00827         const f64 cr = cos( rotation.X );
+00828         const f64 sr = sin( rotation.X );
+00829         const f64 cp = cos( rotation.Y );
+00830         const f64 sp = sin( rotation.Y );
+00831         const f64 cy = cos( rotation.Z );
+00832         const f64 sy = sin( rotation.Z );
+00833 
+00834         M[0] = (T)( cp*cy );
+00835         M[1] = (T)( cp*sy );
+00836         M[2] = (T)( -sp );
+00837 
+00838         const f64 srsp = sr*sp;
+00839         const f64 crsp = cr*sp;
+00840 
+00841         M[4] = (T)( srsp*cy-cr*sy );
+00842         M[5] = (T)( srsp*sy+cr*cy );
+00843         M[6] = (T)( sr*cp );
+00844 
+00845         M[8] = (T)( crsp*cy+sr*sy );
+00846         M[9] = (T)( crsp*sy-sr*cy );
+00847         M[10] = (T)( cr*cp );
+00848 #if defined ( USE_MATRIX_TEST )
+00849         definitelyIdentityMatrix=false;
+00850 #endif
+00851         return *this;
+00852     }
+00853 
+00854 
+00856 
+00859     template <class T>
+00860     inline core::vector3d<T> CMatrix4<T>::getRotationDegrees() const
+00861     {
+00862         const CMatrix4<T> &mat = *this;
+00863         core::vector3d<T> scale = getScale();
+00864         // we need to check for negative scale on to axes, which would bring up wrong results
+00865         if (scale.Y<0 && scale.Z<0)
+00866         {
+00867             scale.Y =-scale.Y;
+00868             scale.Z =-scale.Z;
+00869         }
+00870         else if (scale.X<0 && scale.Z<0)
+00871         {
+00872             scale.X =-scale.X;
+00873             scale.Z =-scale.Z;
+00874         }
+00875         else if (scale.X<0 && scale.Y<0)
+00876         {
+00877             scale.X =-scale.X;
+00878             scale.Y =-scale.Y;
+00879         }
+00880         const core::vector3d<f64> invScale(core::reciprocal(scale.X),core::reciprocal(scale.Y),core::reciprocal(scale.Z));
+00881 
+00882         f64 Y = -asin(core::clamp(mat[2]*invScale.X, -1.0, 1.0));
+00883         const f64 C = cos(Y);
+00884         Y *= RADTODEG64;
+00885 
+00886         f64 rotx, roty, X, Z;
+00887 
+00888         if (!core::iszero(C))
+00889         {
+00890             const f64 invC = core::reciprocal(C);
+00891             rotx = mat[10] * invC * invScale.Z;
+00892             roty = mat[6] * invC * invScale.Y;
+00893             X = atan2( roty, rotx ) * RADTODEG64;
+00894             rotx = mat[0] * invC * invScale.X;
+00895             roty = mat[1] * invC * invScale.X;
+00896             Z = atan2( roty, rotx ) * RADTODEG64;
+00897         }
+00898         else
+00899         {
+00900             X = 0.0;
+00901             rotx = mat[5] * invScale.Y;
+00902             roty = -mat[4] * invScale.Y;
+00903             Z = atan2( roty, rotx ) * RADTODEG64;
+00904         }
+00905 
+00906         // fix values that get below zero
+00907         if (X < 0.0) X += 360.0;
+00908         if (Y < 0.0) Y += 360.0;
+00909         if (Z < 0.0) Z += 360.0;
+00910 
+00911         return vector3d<T>((T)X,(T)Y,(T)Z);
+00912     }
+00913 
+00914 
+00916     template <class T>
+00917     inline CMatrix4<T>& CMatrix4<T>::setInverseRotationRadians( const vector3d<T>& rotation )
+00918     {
+00919         f64 cr = cos( rotation.X );
+00920         f64 sr = sin( rotation.X );
+00921         f64 cp = cos( rotation.Y );
+00922         f64 sp = sin( rotation.Y );
+00923         f64 cy = cos( rotation.Z );
+00924         f64 sy = sin( rotation.Z );
+00925 
+00926         M[0] = (T)( cp*cy );
+00927         M[4] = (T)( cp*sy );
+00928         M[8] = (T)( -sp );
+00929 
+00930         f64 srsp = sr*sp;
+00931         f64 crsp = cr*sp;
+00932 
+00933         M[1] = (T)( srsp*cy-cr*sy );
+00934         M[5] = (T)( srsp*sy+cr*cy );
+00935         M[9] = (T)( sr*cp );
+00936 
+00937         M[2] = (T)( crsp*cy+sr*sy );
+00938         M[6] = (T)( crsp*sy-sr*cy );
+00939         M[10] = (T)( cr*cp );
+00940 #if defined ( USE_MATRIX_TEST )
+00941         definitelyIdentityMatrix=false;
+00942 #endif
+00943         return *this;
+00944     }
+00945 
+00947     template <class T>
+00948     inline CMatrix4<T>& CMatrix4<T>::setRotationAxisRadians( const T& angle, const vector3d<T>& axis )
+00949     {
+00950         const f64 c = cos(angle);
+00951         const f64 s = sin(angle);
+00952         const f64 t = 1.0 - c;
+00953 
+00954         const f64 tx  = t * axis.X;
+00955         const f64 ty  = t * axis.Y;     
+00956         const f64 tz  = t * axis.Z;
+00957 
+00958         const f64 sx  = s * axis.X;
+00959         const f64 sy  = s * axis.Y;
+00960         const f64 sz  = s * axis.Z;
+00961         
+00962         M[0] = (T)(tx * axis.X + c);
+00963         M[1] = (T)(tx * axis.Y + sz);
+00964         M[2] = (T)(tx * axis.Z - sy);
+00965 
+00966         M[4] = (T)(ty * axis.X - sz);
+00967         M[5] = (T)(ty * axis.Y + c);
+00968         M[6] = (T)(ty * axis.Z + sx);
+00969 
+00970         M[8]  = (T)(tz * axis.X + sy);
+00971         M[9]  = (T)(tz * axis.Y - sx);
+00972         M[10] = (T)(tz * axis.Z + c);
+00973 
+00974 #if defined ( USE_MATRIX_TEST )
+00975         definitelyIdentityMatrix=false;
+00976 #endif
+00977         return *this;
+00978     }
+00979 
+00980 
+00983     template <class T>
+00984     inline CMatrix4<T>& CMatrix4<T>::makeIdentity()
+00985     {
+00986         memset(M, 0, 16*sizeof(T));
+00987         M[0] = M[5] = M[10] = M[15] = (T)1;
+00988 #if defined ( USE_MATRIX_TEST )
+00989         definitelyIdentityMatrix=true;
+00990 #endif
+00991         return *this;
+00992     }
+00993 
+00994 
+00995     /*
+00996         check identity with epsilon
+00997         solve floating range problems..
+00998     */
+00999     template <class T>
+01000     inline bool CMatrix4<T>::isIdentity() const
+01001     {
+01002 #if defined ( USE_MATRIX_TEST )
+01003         if (definitelyIdentityMatrix)
+01004             return true;
+01005 #endif
+01006         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 ))
+01007             return false;
+01008 
+01009         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 ))
+01010             return false;
+01011 
+01012         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 ))
+01013             return false;
+01014 
+01015         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 ))
+01016             return false;
+01017 /*
+01018         if (!core::equals( M[ 0], (T)1 ) ||
+01019             !core::equals( M[ 5], (T)1 ) ||
+01020             !core::equals( M[10], (T)1 ) ||
+01021             !core::equals( M[15], (T)1 ))
+01022             return false;
+01023 
+01024         for (s32 i=0; i<4; ++i)
+01025             for (s32 j=0; j<4; ++j)
+01026                 if ((j != i) && (!iszero((*this)(i,j))))
+01027                     return false;
+01028 */
+01029 #if defined ( USE_MATRIX_TEST )
+01030         definitelyIdentityMatrix=true;
+01031 #endif
+01032         return true;
+01033     }
+01034 
+01035 
+01036     /* Check orthogonality of matrix. */
+01037     template <class T>
+01038     inline bool CMatrix4<T>::isOrthogonal() const
+01039     {
+01040         T dp=M[0] * M[4 ] + M[1] * M[5 ] + M[2 ] * M[6 ] + M[3 ] * M[7 ];
+01041         if (!iszero(dp))
+01042             return false;
+01043         dp = M[0] * M[8 ] + M[1] * M[9 ] + M[2 ] * M[10] + M[3 ] * M[11];
+01044         if (!iszero(dp))
+01045             return false;
+01046         dp = M[0] * M[12] + M[1] * M[13] + M[2 ] * M[14] + M[3 ] * M[15];
+01047         if (!iszero(dp))
+01048             return false;
+01049         dp = M[4] * M[8 ] + M[5] * M[9 ] + M[6 ] * M[10] + M[7 ] * M[11];
+01050         if (!iszero(dp))
+01051             return false;
+01052         dp = M[4] * M[12] + M[5] * M[13] + M[6 ] * M[14] + M[7 ] * M[15];
+01053         if (!iszero(dp))
+01054             return false;
+01055         dp = M[8] * M[12] + M[9] * M[13] + M[10] * M[14] + M[11] * M[15];
+01056         return (iszero(dp));
+01057     }
+01058 
+01059 
+01060     /*
+01061         doesn't solve floating range problems..
+01062         but takes care on +/- 0 on translation because we are changing it..
+01063         reducing floating point branches
+01064         but it needs the floats in memory..
+01065     */
+01066     template <class T>
+01067     inline bool CMatrix4<T>::isIdentity_integer_base() const
+01068     {
+01069 #if defined ( USE_MATRIX_TEST )
+01070         if (definitelyIdentityMatrix)
+01071             return true;
+01072 #endif
+01073         if(IR(M[0])!=F32_VALUE_1)   return false;
+01074         if(IR(M[1])!=0)         return false;
+01075         if(IR(M[2])!=0)         return false;
+01076         if(IR(M[3])!=0)         return false;
+01077 
+01078         if(IR(M[4])!=0)         return false;
+01079         if(IR(M[5])!=F32_VALUE_1)   return false;
+01080         if(IR(M[6])!=0)         return false;
+01081         if(IR(M[7])!=0)         return false;
+01082 
+01083         if(IR(M[8])!=0)         return false;
+01084         if(IR(M[9])!=0)         return false;
+01085         if(IR(M[10])!=F32_VALUE_1)  return false;
+01086         if(IR(M[11])!=0)        return false;
+01087 
+01088         if(IR(M[12])!=0)        return false;
+01089         if(IR(M[13])!=0)        return false;
+01090         if(IR(M[13])!=0)        return false;
+01091         if(IR(M[15])!=F32_VALUE_1)  return false;
+01092 
+01093 #if defined ( USE_MATRIX_TEST )
+01094         definitelyIdentityMatrix=true;
+01095 #endif
+01096         return true;
+01097     }
+01098 
+01099 
+01100     template <class T>
+01101     inline void CMatrix4<T>::rotateVect( vector3df& vect ) const
+01102     {
+01103         vector3df tmp = vect;
+01104         vect.X = tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8];
+01105         vect.Y = tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9];
+01106         vect.Z = tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10];
+01107     }
+01108 
+01110     template <class T>
+01111     inline void CMatrix4<T>::rotateVect(core::vector3df& out, const core::vector3df& in) const
+01112     {
+01113         out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
+01114         out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
+01115         out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
+01116     }
+01117 
+01119     template <class T>
+01120     inline void CMatrix4<T>::rotateVect(T *out, const core::vector3df& in) const
+01121     {
+01122         out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
+01123         out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
+01124         out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
+01125     }
+01126 
+01127     template <class T>
+01128     inline void CMatrix4<T>::inverseRotateVect( vector3df& vect ) const
+01129     {
+01130         vector3df tmp = vect;
+01131         vect.X = tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2];
+01132         vect.Y = tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6];
+01133         vect.Z = tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10];
+01134     }
+01135 
+01136     template <class T>
+01137     inline void CMatrix4<T>::transformVect( vector3df& vect) const
+01138     {
+01139         f32 vector[3];
+01140 
+01141         vector[0] = vect.X*M[0] + vect.Y*M[4] + vect.Z*M[8] + M[12];
+01142         vector[1] = vect.X*M[1] + vect.Y*M[5] + vect.Z*M[9] + M[13];
+01143         vector[2] = vect.X*M[2] + vect.Y*M[6] + vect.Z*M[10] + M[14];
+01144 
+01145         vect.X = vector[0];
+01146         vect.Y = vector[1];
+01147         vect.Z = vector[2];
+01148     }
+01149 
+01150     template <class T>
+01151     inline void CMatrix4<T>::transformVect( vector3df& out, const vector3df& in) const
+01152     {
+01153         out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
+01154         out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
+01155         out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
+01156     }
+01157 
+01158 
+01159     template <class T>
+01160     inline void CMatrix4<T>::transformVect(T *out, const core::vector3df &in) const
+01161     {
+01162         out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
+01163         out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
+01164         out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
+01165         out[3] = in.X*M[3] + in.Y*M[7] + in.Z*M[11] + M[15];
+01166     }
+01167 
+01168     template <class T>
+01169     inline void CMatrix4<T>::transformVec3(T *out, const T * in) const
+01170     {
+01171         out[0] = in[0]*M[0] + in[1]*M[4] + in[2]*M[8] + M[12];
+01172         out[1] = in[0]*M[1] + in[1]*M[5] + in[2]*M[9] + M[13];
+01173         out[2] = in[0]*M[2] + in[1]*M[6] + in[2]*M[10] + M[14];
+01174     }
+01175 
+01176 
+01178     template <class T>
+01179     inline void CMatrix4<T>::transformPlane( core::plane3d<f32> &plane) const
+01180     {
+01181         vector3df member;
+01182         // Transform the plane member point, i.e. rotate, translate and scale it.
+01183         transformVect(member, plane.getMemberPoint());
+01184 
+01185         // Transform the normal by the transposed inverse of the matrix
+01186         CMatrix4<T> transposedInverse(*this, EM4CONST_INVERSE_TRANSPOSED);
+01187         vector3df normal = plane.Normal;
+01188         transposedInverse.transformVect(normal);
+01189 
+01190         plane.setPlane(member, normal);
+01191     }
+01192 
+01194     template <class T>
+01195     inline void CMatrix4<T>::transformPlane( const core::plane3d<f32> &in, core::plane3d<f32> &out) const
+01196     {
+01197         out = in;
+01198         transformPlane( out );
+01199     }
+01200 
+01202     template <class T>
+01203     inline void CMatrix4<T>::transformBox(core::aabbox3d<f32>& box) const
+01204     {
+01205 #if defined ( USE_MATRIX_TEST )
+01206         if (isIdentity())
+01207             return;
+01208 #endif
+01209 
+01210         transformVect(box.MinEdge);
+01211         transformVect(box.MaxEdge);
+01212         box.repair();
+01213     }
+01214 
+01216     template <class T>
+01217     inline void CMatrix4<T>::transformBoxEx(core::aabbox3d<f32>& box) const
+01218     {
+01219 #if defined ( USE_MATRIX_TEST )
+01220         if (isIdentity())
+01221             return;
+01222 #endif
+01223 
+01224         const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z};
+01225         const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z};
+01226 
+01227         f32 Bmin[3];
+01228         f32 Bmax[3];
+01229 
+01230         Bmin[0] = Bmax[0] = M[12];
+01231         Bmin[1] = Bmax[1] = M[13];
+01232         Bmin[2] = Bmax[2] = M[14];
+01233 
+01234         const CMatrix4<T> &m = *this;
+01235 
+01236         for (u32 i = 0; i < 3; ++i)
+01237         {
+01238             for (u32 j = 0; j < 3; ++j)
+01239             {
+01240                 const f32 a = m(j,i) * Amin[j];
+01241                 const f32 b = m(j,i) * Amax[j];
+01242 
+01243                 if (a < b)
+01244                 {
+01245                     Bmin[i] += a;
+01246                     Bmax[i] += b;
+01247                 }
+01248                 else
+01249                 {
+01250                     Bmin[i] += b;
+01251                     Bmax[i] += a;
+01252                 }
+01253             }
+01254         }
+01255 
+01256         box.MinEdge.X = Bmin[0];
+01257         box.MinEdge.Y = Bmin[1];
+01258         box.MinEdge.Z = Bmin[2];
+01259 
+01260         box.MaxEdge.X = Bmax[0];
+01261         box.MaxEdge.Y = Bmax[1];
+01262         box.MaxEdge.Z = Bmax[2];
+01263     }
+01264 
+01265 
+01267     template <class T>
+01268     inline void CMatrix4<T>::multiplyWith1x4Matrix(T* matrix) const
+01269     {
+01270         /*
+01271         0  1  2  3
+01272         4  5  6  7
+01273         8  9  10 11
+01274         12 13 14 15
+01275         */
+01276 
+01277         T mat[4];
+01278         mat[0] = matrix[0];
+01279         mat[1] = matrix[1];
+01280         mat[2] = matrix[2];
+01281         mat[3] = matrix[3];
+01282 
+01283         matrix[0] = M[0]*mat[0] + M[4]*mat[1] + M[8]*mat[2] + M[12]*mat[3];
+01284         matrix[1] = M[1]*mat[0] + M[5]*mat[1] + M[9]*mat[2] + M[13]*mat[3];
+01285         matrix[2] = M[2]*mat[0] + M[6]*mat[1] + M[10]*mat[2] + M[14]*mat[3];
+01286         matrix[3] = M[3]*mat[0] + M[7]*mat[1] + M[11]*mat[2] + M[15]*mat[3];
+01287     }
+01288 
+01289     template <class T>
+01290     inline void CMatrix4<T>::inverseTranslateVect( vector3df& vect ) const
+01291     {
+01292         vect.X = vect.X-M[12];
+01293         vect.Y = vect.Y-M[13];
+01294         vect.Z = vect.Z-M[14];
+01295     }
+01296 
+01297     template <class T>
+01298     inline void CMatrix4<T>::translateVect( vector3df& vect ) const
+01299     {
+01300         vect.X = vect.X+M[12];
+01301         vect.Y = vect.Y+M[13];
+01302         vect.Z = vect.Z+M[14];
+01303     }
+01304 
+01305 
+01306     template <class T>
+01307     inline bool CMatrix4<T>::getInverse(CMatrix4<T>& out) const
+01308     {
+01312 
+01313 #if defined ( USE_MATRIX_TEST )
+01314         if ( this->isIdentity() )
+01315         {
+01316             out=*this;
+01317             return true;
+01318         }
+01319 #endif
+01320         const CMatrix4<T> &m = *this;
+01321 
+01322         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)) -
+01323             (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
+01324             (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)) +
+01325             (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) -
+01326             (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
+01327             (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0));
+01328 
+01329         if( core::iszero ( d, FLT_MIN ) )
+01330             return false;
+01331 
+01332         d = core::reciprocal ( d );
+01333 
+01334         out(0, 0) = d * (m(1, 1) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) +
+01335                 m(1, 2) * (m(2, 3) * m(3, 1) - m(2, 1) * m(3, 3)) +
+01336                 m(1, 3) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)));
+01337         out(0, 1) = d * (m(2, 1) * (m(0, 2) * m(3, 3) - m(0, 3) * m(3, 2)) +
+01338                 m(2, 2) * (m(0, 3) * m(3, 1) - m(0, 1) * m(3, 3)) +
+01339                 m(2, 3) * (m(0, 1) * m(3, 2) - m(0, 2) * m(3, 1)));
+01340         out(0, 2) = d * (m(3, 1) * (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) +
+01341                 m(3, 2) * (m(0, 3) * m(1, 1) - m(0, 1) * m(1, 3)) +
+01342                 m(3, 3) * (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)));
+01343         out(0, 3) = d * (m(0, 1) * (m(1, 3) * m(2, 2) - m(1, 2) * m(2, 3)) +
+01344                 m(0, 2) * (m(1, 1) * m(2, 3) - m(1, 3) * m(2, 1)) +
+01345                 m(0, 3) * (m(1, 2) * m(2, 1) - m(1, 1) * m(2, 2)));
+01346         out(1, 0) = d * (m(1, 2) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) +
+01347                 m(1, 3) * (m(2, 2) * m(3, 0) - m(2, 0) * m(3, 2)) +
+01348                 m(1, 0) * (m(2, 3) * m(3, 2) - m(2, 2) * m(3, 3)));
+01349         out(1, 1) = d * (m(2, 2) * (m(0, 0) * m(3, 3) - m(0, 3) * m(3, 0)) +
+01350                 m(2, 3) * (m(0, 2) * m(3, 0) - m(0, 0) * m(3, 2)) +
+01351                 m(2, 0) * (m(0, 3) * m(3, 2) - m(0, 2) * m(3, 3)));
+01352         out(1, 2) = d * (m(3, 2) * (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) +
+01353                 m(3, 3) * (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2)) +
+01354                 m(3, 0) * (m(0, 3) * m(1, 2) - m(0, 2) * m(1, 3)));
+01355         out(1, 3) = d * (m(0, 2) * (m(1, 3) * m(2, 0) - m(1, 0) * m(2, 3)) +
+01356                 m(0, 3) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
+01357                 m(0, 0) * (m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2)));
+01358         out(2, 0) = d * (m(1, 3) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)) +
+01359                 m(1, 0) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
+01360                 m(1, 1) * (m(2, 3) * m(3, 0) - m(2, 0) * m(3, 3)));
+01361         out(2, 1) = d * (m(2, 3) * (m(0, 0) * m(3, 1) - m(0, 1) * m(3, 0)) +
+01362                 m(2, 0) * (m(0, 1) * m(3, 3) - m(0, 3) * m(3, 1)) +
+01363                 m(2, 1) * (m(0, 3) * m(3, 0) - m(0, 0) * m(3, 3)));
+01364         out(2, 2) = d * (m(3, 3) * (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) +
+01365                 m(3, 0) * (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) +
+01366                 m(3, 1) * (m(0, 3) * m(1, 0) - m(0, 0) * m(1, 3)));
+01367         out(2, 3) = d * (m(0, 3) * (m(1, 1) * m(2, 0) - m(1, 0) * m(2, 1)) +
+01368                 m(0, 0) * (m(1, 3) * m(2, 1) - m(1, 1) * m(2, 3)) +
+01369                 m(0, 1) * (m(1, 0) * m(2, 3) - m(1, 3) * m(2, 0)));
+01370         out(3, 0) = d * (m(1, 0) * (m(2, 2) * m(3, 1) - m(2, 1) * m(3, 2)) +
+01371                 m(1, 1) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
+01372                 m(1, 2) * (m(2, 1) * m(3, 0) - m(2, 0) * m(3, 1)));
+01373         out(3, 1) = d * (m(2, 0) * (m(0, 2) * m(3, 1) - m(0, 1) * m(3, 2)) +
+01374                 m(2, 1) * (m(0, 0) * m(3, 2) - m(0, 2) * m(3, 0)) +
+01375                 m(2, 2) * (m(0, 1) * m(3, 0) - m(0, 0) * m(3, 1)));
+01376         out(3, 2) = d * (m(3, 0) * (m(0, 2) * m(1, 1) - m(0, 1) * m(1, 2)) +
+01377                 m(3, 1) * (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) +
+01378                 m(3, 2) * (m(0, 1) * m(1, 0) - m(0, 0) * m(1, 1)));
+01379         out(3, 3) = d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) +
+01380                 m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) +
+01381                 m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0)));
+01382 
+01383 #if defined ( USE_MATRIX_TEST )
+01384         out.definitelyIdentityMatrix = definitelyIdentityMatrix;
+01385 #endif
+01386         return true;
+01387     }
+01388 
+01389 
+01392     template <class T>
+01393     inline bool CMatrix4<T>::getInversePrimitive ( CMatrix4<T>& out ) const
+01394     {
+01395         out.M[0 ] = M[0];
+01396         out.M[1 ] = M[4];
+01397         out.M[2 ] = M[8];
+01398         out.M[3 ] = 0;
+01399 
+01400         out.M[4 ] = M[1];
+01401         out.M[5 ] = M[5];
+01402         out.M[6 ] = M[9];
+01403         out.M[7 ] = 0;
+01404 
+01405         out.M[8 ] = M[2];
+01406         out.M[9 ] = M[6];
+01407         out.M[10] = M[10];
+01408         out.M[11] = 0;
+01409 
+01410         out.M[12] = (T)-(M[12]*M[0] + M[13]*M[1] + M[14]*M[2]);
+01411         out.M[13] = (T)-(M[12]*M[4] + M[13]*M[5] + M[14]*M[6]);
+01412         out.M[14] = (T)-(M[12]*M[8] + M[13]*M[9] + M[14]*M[10]);
+01413         out.M[15] = 1;
+01414 
+01415 #if defined ( USE_MATRIX_TEST )
+01416         out.definitelyIdentityMatrix = definitelyIdentityMatrix;
+01417 #endif
+01418         return true;
+01419     }
+01420 
+01423     template <class T>
+01424     inline bool CMatrix4<T>::makeInverse()
+01425     {
+01426 #if defined ( USE_MATRIX_TEST )
+01427         if (definitelyIdentityMatrix)
+01428             return true;
+01429 #endif
+01430         CMatrix4<T> temp ( EM4CONST_NOTHING );
+01431 
+01432         if (getInverse(temp))
+01433         {
+01434             *this = temp;
+01435             return true;
+01436         }
+01437 
+01438         return false;
+01439     }
+01440 
+01441 
+01442     template <class T>
+01443     inline CMatrix4<T>& CMatrix4<T>::operator=(const CMatrix4<T> &other)
+01444     {
+01445         if (this==&other)
+01446             return *this;
+01447         memcpy(M, other.M, 16*sizeof(T));
+01448 #if defined ( USE_MATRIX_TEST )
+01449         definitelyIdentityMatrix=other.definitelyIdentityMatrix;
+01450 #endif
+01451         return *this;
+01452     }
+01453 
+01454 
+01455     template <class T>
+01456     inline CMatrix4<T>& CMatrix4<T>::operator=(const T& scalar)
+01457     {
+01458         for (s32 i = 0; i < 16; ++i)
+01459             M[i]=scalar;
+01460 
+01461 #if defined ( USE_MATRIX_TEST )
+01462         definitelyIdentityMatrix=false;
+01463 #endif
+01464         return *this;
+01465     }
+01466 
+01467 
+01468     template <class T>
+01469     inline bool CMatrix4<T>::operator==(const CMatrix4<T> &other) const
+01470     {
+01471 #if defined ( USE_MATRIX_TEST )
+01472         if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
+01473             return true;
+01474 #endif
+01475         for (s32 i = 0; i < 16; ++i)
+01476             if (M[i] != other.M[i])
+01477                 return false;
+01478 
+01479         return true;
+01480     }
+01481 
+01482 
+01483     template <class T>
+01484     inline bool CMatrix4<T>::operator!=(const CMatrix4<T> &other) const
+01485     {
+01486         return !(*this == other);
+01487     }
+01488 
+01489 
+01490     // Builds a right-handed perspective projection matrix based on a field of view
+01491     template <class T>
+01492     inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovRH(
+01493             f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
+01494     {
+01495         const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
+01496         _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
+01497         const T w = static_cast<T>(h / aspectRatio);
+01498 
+01499         _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
+01500         M[0] = w;
+01501         M[1] = 0;
+01502         M[2] = 0;
+01503         M[3] = 0;
+01504 
+01505         M[4] = 0;
+01506         M[5] = (T)h;
+01507         M[6] = 0;
+01508         M[7] = 0;
+01509 
+01510         M[8] = 0;
+01511         M[9] = 0;
+01512         M[10] = (T)(zFar/(zNear-zFar)); // DirectX version
+01513 //      M[10] = (T)(zFar+zNear/(zNear-zFar)); // OpenGL version
+01514         M[11] = -1;
+01515 
+01516         M[12] = 0;
+01517         M[13] = 0;
+01518         M[14] = (T)(zNear*zFar/(zNear-zFar)); // DirectX version
+01519 //      M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar)); // OpenGL version
+01520         M[15] = 0;
+01521 
+01522 #if defined ( USE_MATRIX_TEST )
+01523         definitelyIdentityMatrix=false;
+01524 #endif
+01525         return *this;
+01526     }
+01527 
+01528 
+01529     // Builds a left-handed perspective projection matrix based on a field of view
+01530     template <class T>
+01531     inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovLH(
+01532             f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
+01533     {
+01534         const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
+01535         _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
+01536         const T w = static_cast<T>(h / aspectRatio);
+01537 
+01538         _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
+01539         M[0] = w;
+01540         M[1] = 0;
+01541         M[2] = 0;
+01542         M[3] = 0;
+01543 
+01544         M[4] = 0;
+01545         M[5] = (T)h;
+01546         M[6] = 0;
+01547         M[7] = 0;
+01548 
+01549         M[8] = 0;
+01550         M[9] = 0;
+01551         M[10] = (T)(zFar/(zFar-zNear));
+01552         M[11] = 1;
+01553 
+01554         M[12] = 0;
+01555         M[13] = 0;
+01556         M[14] = (T)(-zNear*zFar/(zFar-zNear));
+01557         M[15] = 0;
+01558 
+01559 #if defined ( USE_MATRIX_TEST )
+01560         definitelyIdentityMatrix=false;
+01561 #endif
+01562         return *this;
+01563     }
+01564 
+01565 
+01566     // Builds a left-handed perspective projection matrix based on a field of view, with far plane culling at infinity
+01567     template <class T>
+01568     inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovInfinityLH(
+01569             f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon)
+01570     {
+01571         const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
+01572         _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
+01573         const T w = static_cast<T>(h / aspectRatio);
+01574 
+01575         M[0] = w;
+01576         M[1] = 0;
+01577         M[2] = 0;
+01578         M[3] = 0;
+01579 
+01580         M[4] = 0;
+01581         M[5] = (T)h;
+01582         M[6] = 0;
+01583         M[7] = 0;
+01584 
+01585         M[8] = 0;
+01586         M[9] = 0;
+01587         M[10] = (T)(1.f-epsilon);
+01588         M[11] = 1;
+01589 
+01590         M[12] = 0;
+01591         M[13] = 0;
+01592         M[14] = (T)(zNear*(epsilon-1.f));
+01593         M[15] = 0;
+01594 
+01595 #if defined ( USE_MATRIX_TEST )
+01596         definitelyIdentityMatrix=false;
+01597 #endif
+01598         return *this;
+01599     }
+01600 
+01601 
+01602     // Builds a left-handed orthogonal projection matrix.
+01603     template <class T>
+01604     inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoLH(
+01605             f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
+01606     {
+01607         _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
+01608         _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
+01609         _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
+01610         M[0] = (T)(2/widthOfViewVolume);
+01611         M[1] = 0;
+01612         M[2] = 0;
+01613         M[3] = 0;
+01614 
+01615         M[4] = 0;
+01616         M[5] = (T)(2/heightOfViewVolume);
+01617         M[6] = 0;
+01618         M[7] = 0;
+01619 
+01620         M[8] = 0;
+01621         M[9] = 0;
+01622         M[10] = (T)(1/(zFar-zNear));
+01623         M[11] = 0;
+01624 
+01625         M[12] = 0;
+01626         M[13] = 0;
+01627         M[14] = (T)(zNear/(zNear-zFar));
+01628         M[15] = 1;
+01629 
+01630 #if defined ( USE_MATRIX_TEST )
+01631         definitelyIdentityMatrix=false;
+01632 #endif
+01633         return *this;
+01634     }
+01635 
+01636 
+01637     // Builds a right-handed orthogonal projection matrix.
+01638     template <class T>
+01639     inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoRH(
+01640             f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
+01641     {
+01642         _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
+01643         _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
+01644         _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
+01645         M[0] = (T)(2/widthOfViewVolume);
+01646         M[1] = 0;
+01647         M[2] = 0;
+01648         M[3] = 0;
+01649 
+01650         M[4] = 0;
+01651         M[5] = (T)(2/heightOfViewVolume);
+01652         M[6] = 0;
+01653         M[7] = 0;
+01654 
+01655         M[8] = 0;
+01656         M[9] = 0;
+01657         M[10] = (T)(1/(zNear-zFar));
+01658         M[11] = 0;
+01659 
+01660         M[12] = 0;
+01661         M[13] = 0;
+01662         M[14] = (T)(zNear/(zNear-zFar));
+01663         M[15] = 1;
+01664 
+01665 #if defined ( USE_MATRIX_TEST )
+01666         definitelyIdentityMatrix=false;
+01667 #endif
+01668         return *this;
+01669     }
+01670 
+01671 
+01672     // Builds a right-handed perspective projection matrix.
+01673     template <class T>
+01674     inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveRH(
+01675             f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
+01676     {
+01677         _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
+01678         _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
+01679         _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
+01680         M[0] = (T)(2*zNear/widthOfViewVolume);
+01681         M[1] = 0;
+01682         M[2] = 0;
+01683         M[3] = 0;
+01684 
+01685         M[4] = 0;
+01686         M[5] = (T)(2*zNear/heightOfViewVolume);
+01687         M[6] = 0;
+01688         M[7] = 0;
+01689 
+01690         M[8] = 0;
+01691         M[9] = 0;
+01692         M[10] = (T)(zFar/(zNear-zFar));
+01693         M[11] = -1;
+01694 
+01695         M[12] = 0;
+01696         M[13] = 0;
+01697         M[14] = (T)(zNear*zFar/(zNear-zFar));
+01698         M[15] = 0;
+01699 
+01700 #if defined ( USE_MATRIX_TEST )
+01701         definitelyIdentityMatrix=false;
+01702 #endif
+01703         return *this;
+01704     }
+01705 
+01706 
+01707     // Builds a left-handed perspective projection matrix.
+01708     template <class T>
+01709     inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveLH(
+01710             f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
+01711     {
+01712         _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
+01713         _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
+01714         _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
+01715         M[0] = (T)(2*zNear/widthOfViewVolume);
+01716         M[1] = 0;
+01717         M[2] = 0;
+01718         M[3] = 0;
+01719 
+01720         M[4] = 0;
+01721         M[5] = (T)(2*zNear/heightOfViewVolume);
+01722         M[6] = 0;
+01723         M[7] = 0;
+01724 
+01725         M[8] = 0;
+01726         M[9] = 0;
+01727         M[10] = (T)(zFar/(zFar-zNear));
+01728         M[11] = 1;
+01729 
+01730         M[12] = 0;
+01731         M[13] = 0;
+01732         M[14] = (T)(zNear*zFar/(zNear-zFar));
+01733         M[15] = 0;
+01734 #if defined ( USE_MATRIX_TEST )
+01735         definitelyIdentityMatrix=false;
+01736 #endif
+01737         return *this;
+01738     }
+01739 
+01740 
+01741     // Builds a matrix that flattens geometry into a plane.
+01742     template <class T>
+01743     inline CMatrix4<T>& CMatrix4<T>::buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point)
+01744     {
+01745         plane.Normal.normalize();
+01746         const f32 d = plane.Normal.dotProduct(light);
+01747 
+01748         M[ 0] = (T)(-plane.Normal.X * light.X + d);
+01749         M[ 1] = (T)(-plane.Normal.X * light.Y);
+01750         M[ 2] = (T)(-plane.Normal.X * light.Z);
+01751         M[ 3] = (T)(-plane.Normal.X * point);
+01752 
+01753         M[ 4] = (T)(-plane.Normal.Y * light.X);
+01754         M[ 5] = (T)(-plane.Normal.Y * light.Y + d);
+01755         M[ 6] = (T)(-plane.Normal.Y * light.Z);
+01756         M[ 7] = (T)(-plane.Normal.Y * point);
+01757 
+01758         M[ 8] = (T)(-plane.Normal.Z * light.X);
+01759         M[ 9] = (T)(-plane.Normal.Z * light.Y);
+01760         M[10] = (T)(-plane.Normal.Z * light.Z + d);
+01761         M[11] = (T)(-plane.Normal.Z * point);
+01762 
+01763         M[12] = (T)(-plane.D * light.X);
+01764         M[13] = (T)(-plane.D * light.Y);
+01765         M[14] = (T)(-plane.D * light.Z);
+01766         M[15] = (T)(-plane.D * point + d);
+01767 #if defined ( USE_MATRIX_TEST )
+01768         definitelyIdentityMatrix=false;
+01769 #endif
+01770         return *this;
+01771     }
+01772 
+01773     // Builds a left-handed look-at matrix.
+01774     template <class T>
+01775     inline CMatrix4<T>& CMatrix4<T>::buildCameraLookAtMatrixLH(
+01776                 const vector3df& position,
+01777                 const vector3df& target,
+01778                 const vector3df& upVector)
+01779     {
+01780         vector3df zaxis = target - position;
+01781         zaxis.normalize();
+01782 
+01783         vector3df xaxis = upVector.crossProduct(zaxis);
+01784         xaxis.normalize();
+01785 
+01786         vector3df yaxis = zaxis.crossProduct(xaxis);
+01787 
+01788         M[0] = (T)xaxis.X;
+01789         M[1] = (T)yaxis.X;
+01790         M[2] = (T)zaxis.X;
+01791         M[3] = 0;
+01792 
+01793         M[4] = (T)xaxis.Y;
+01794         M[5] = (T)yaxis.Y;
+01795         M[6] = (T)zaxis.Y;
+01796         M[7] = 0;
+01797 
+01798         M[8] = (T)xaxis.Z;
+01799         M[9] = (T)yaxis.Z;
+01800         M[10] = (T)zaxis.Z;
+01801         M[11] = 0;
+01802 
+01803         M[12] = (T)-xaxis.dotProduct(position);
+01804         M[13] = (T)-yaxis.dotProduct(position);
+01805         M[14] = (T)-zaxis.dotProduct(position);
+01806         M[15] = 1;
+01807 #if defined ( USE_MATRIX_TEST )
+01808         definitelyIdentityMatrix=false;
+01809 #endif
+01810         return *this;
+01811     }
+01812 
+01813 
+01814     // Builds a right-handed look-at matrix.
+01815     template <class T>
+01816     inline CMatrix4<T>& CMatrix4<T>::buildCameraLookAtMatrixRH(
+01817                 const vector3df& position,
+01818                 const vector3df& target,
+01819                 const vector3df& upVector)
+01820     {
+01821         vector3df zaxis = position - target;
+01822         zaxis.normalize();
+01823 
+01824         vector3df xaxis = upVector.crossProduct(zaxis);
+01825         xaxis.normalize();
+01826 
+01827         vector3df yaxis = zaxis.crossProduct(xaxis);
+01828 
+01829         M[0] = (T)xaxis.X;
+01830         M[1] = (T)yaxis.X;
+01831         M[2] = (T)zaxis.X;
+01832         M[3] = 0;
+01833 
+01834         M[4] = (T)xaxis.Y;
+01835         M[5] = (T)yaxis.Y;
+01836         M[6] = (T)zaxis.Y;
+01837         M[7] = 0;
+01838 
+01839         M[8] = (T)xaxis.Z;
+01840         M[9] = (T)yaxis.Z;
+01841         M[10] = (T)zaxis.Z;
+01842         M[11] = 0;
+01843 
+01844         M[12] = (T)-xaxis.dotProduct(position);
+01845         M[13] = (T)-yaxis.dotProduct(position);
+01846         M[14] = (T)-zaxis.dotProduct(position);
+01847         M[15] = 1;
+01848 #if defined ( USE_MATRIX_TEST )
+01849         definitelyIdentityMatrix=false;
+01850 #endif
+01851         return *this;
+01852     }
+01853 
+01854 
+01855     // creates a new matrix as interpolated matrix from this and the passed one.
+01856     template <class T>
+01857     inline CMatrix4<T> CMatrix4<T>::interpolate(const core::CMatrix4<T>& b, f32 time) const
+01858     {
+01859         CMatrix4<T> mat ( EM4CONST_NOTHING );
+01860 
+01861         for (u32 i=0; i < 16; i += 4)
+01862         {
+01863             mat.M[i+0] = (T)(M[i+0] + ( b.M[i+0] - M[i+0] ) * time);
+01864             mat.M[i+1] = (T)(M[i+1] + ( b.M[i+1] - M[i+1] ) * time);
+01865             mat.M[i+2] = (T)(M[i+2] + ( b.M[i+2] - M[i+2] ) * time);
+01866             mat.M[i+3] = (T)(M[i+3] + ( b.M[i+3] - M[i+3] ) * time);
+01867         }
+01868         return mat;
+01869     }
+01870 
+01871 
+01872     // returns transposed matrix
+01873     template <class T>
+01874     inline CMatrix4<T> CMatrix4<T>::getTransposed() const
+01875     {
+01876         CMatrix4<T> t ( EM4CONST_NOTHING );
+01877         getTransposed ( t );
+01878         return t;
+01879     }
+01880 
+01881 
+01882     // returns transposed matrix
+01883     template <class T>
+01884     inline void CMatrix4<T>::getTransposed( CMatrix4<T>& o ) const
+01885     {
+01886         o[ 0] = M[ 0];
+01887         o[ 1] = M[ 4];
+01888         o[ 2] = M[ 8];
+01889         o[ 3] = M[12];
+01890 
+01891         o[ 4] = M[ 1];
+01892         o[ 5] = M[ 5];
+01893         o[ 6] = M[ 9];
+01894         o[ 7] = M[13];
+01895 
+01896         o[ 8] = M[ 2];
+01897         o[ 9] = M[ 6];
+01898         o[10] = M[10];
+01899         o[11] = M[14];
+01900 
+01901         o[12] = M[ 3];
+01902         o[13] = M[ 7];
+01903         o[14] = M[11];
+01904         o[15] = M[15];
+01905 #if defined ( USE_MATRIX_TEST )
+01906         o.definitelyIdentityMatrix=definitelyIdentityMatrix;
+01907 #endif
+01908     }
+01909 
+01910 
+01911     // used to scale <-1,-1><1,1> to viewport
+01912     template <class T>
+01913     inline CMatrix4<T>& CMatrix4<T>::buildNDCToDCMatrix( const core::rect<s32>& viewport, f32 zScale)
+01914     {
+01915         const f32 scaleX = (viewport.getWidth() - 0.75f ) * 0.5f;
+01916         const f32 scaleY = -(viewport.getHeight() - 0.75f ) * 0.5f;
+01917 
+01918         const f32 dx = -0.5f + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) * 0.5f );
+01919         const f32 dy = -0.5f + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) * 0.5f );
+01920 
+01921         makeIdentity();
+01922         M[12] = (T)dx;
+01923         M[13] = (T)dy;
+01924         return setScale(core::vector3d<T>((T)scaleX, (T)scaleY, (T)zScale));
+01925     }
+01926 
+01928 
+01933     template <class T>
+01934     inline CMatrix4<T>& CMatrix4<T>::buildRotateFromTo(const core::vector3df& from, const core::vector3df& to)
+01935     {
+01936         // unit vectors
+01937         core::vector3df f(from);
+01938         core::vector3df t(to);
+01939         f.normalize();
+01940         t.normalize();
+01941 
+01942         // axis multiplication by sin
+01943         core::vector3df vs(t.crossProduct(f));
+01944 
+01945         // axis of rotation
+01946         core::vector3df v(vs);
+01947         v.normalize();
+01948 
+01949         // cosinus angle
+01950         T ca = f.dotProduct(t);
+01951 
+01952         core::vector3df vt(v * (1 - ca));
+01953 
+01954         M[0] = vt.X * v.X + ca;
+01955         M[5] = vt.Y * v.Y + ca;
+01956         M[10] = vt.Z * v.Z + ca;
+01957 
+01958         vt.X *= v.Y;
+01959         vt.Z *= v.X;
+01960         vt.Y *= v.Z;
+01961 
+01962         M[1] = vt.X - vs.Z;
+01963         M[2] = vt.Z + vs.Y;
+01964         M[3] = 0;
+01965 
+01966         M[4] = vt.X + vs.Z;
+01967         M[6] = vt.Y - vs.X;
+01968         M[7] = 0;
+01969 
+01970         M[8] = vt.Z - vs.Y;
+01971         M[9] = vt.Y + vs.X;
+01972         M[11] = 0;
+01973 
+01974         M[12] = 0;
+01975         M[13] = 0;
+01976         M[14] = 0;
+01977         M[15] = 1;
+01978 
+01979         return *this;
+01980     }
+01981 
+01983 
+01989     template <class T>
+01990     inline void CMatrix4<T>::buildAxisAlignedBillboard(
+01991                 const core::vector3df& camPos,
+01992                 const core::vector3df& center,
+01993                 const core::vector3df& translation,
+01994                 const core::vector3df& axis,
+01995                 const core::vector3df& from)
+01996     {
+01997         // axis of rotation
+01998         core::vector3df up = axis;
+01999         up.normalize();
+02000         const core::vector3df forward = (camPos - center).normalize();
+02001         const core::vector3df right = up.crossProduct(forward).normalize();
+02002 
+02003         // correct look vector
+02004         const core::vector3df look = right.crossProduct(up);
+02005 
+02006         // rotate from to
+02007         // axis multiplication by sin
+02008         const core::vector3df vs = look.crossProduct(from);
+02009 
+02010         // cosinus angle
+02011         const f32 ca = from.dotProduct(look);
+02012 
+02013         core::vector3df vt(up * (1.f - ca));
+02014 
+02015         M[0] = static_cast<T>(vt.X * up.X + ca);
+02016         M[5] = static_cast<T>(vt.Y * up.Y + ca);
+02017         M[10] = static_cast<T>(vt.Z * up.Z + ca);
+02018 
+02019         vt.X *= up.Y;
+02020         vt.Z *= up.X;
+02021         vt.Y *= up.Z;
+02022 
+02023         M[1] = static_cast<T>(vt.X - vs.Z);
+02024         M[2] = static_cast<T>(vt.Z + vs.Y);
+02025         M[3] = 0;
+02026 
+02027         M[4] = static_cast<T>(vt.X + vs.Z);
+02028         M[6] = static_cast<T>(vt.Y - vs.X);
+02029         M[7] = 0;
+02030 
+02031         M[8] = static_cast<T>(vt.Z - vs.Y);
+02032         M[9] = static_cast<T>(vt.Y + vs.X);
+02033         M[11] = 0;
+02034 
+02035         setRotationCenter(center, translation);
+02036     }
+02037 
+02038 
+02040     template <class T>
+02041     inline void CMatrix4<T>::setRotationCenter(const core::vector3df& center, const core::vector3df& translation)
+02042     {
+02043         M[12] = -M[0]*center.X - M[4]*center.Y - M[8]*center.Z + (center.X - translation.X );
+02044         M[13] = -M[1]*center.X - M[5]*center.Y - M[9]*center.Z + (center.Y - translation.Y );
+02045         M[14] = -M[2]*center.X - M[6]*center.Y - M[10]*center.Z + (center.Z - translation.Z );
+02046         M[15] = (T) 1.0;
+02047 #if defined ( USE_MATRIX_TEST )
+02048         definitelyIdentityMatrix=false;
+02049 #endif
+02050     }
+02051 
+02064     template <class T>
+02065     inline CMatrix4<T>& CMatrix4<T>::buildTextureTransform( f32 rotateRad,
+02066             const core::vector2df &rotatecenter,
+02067             const core::vector2df &translate,
+02068             const core::vector2df &scale)
+02069     {
+02070         const f32 c = cosf(rotateRad);
+02071         const f32 s = sinf(rotateRad);
+02072 
+02073         M[0] = (T)(c * scale.X);
+02074         M[1] = (T)(s * scale.Y);
+02075         M[2] = 0;
+02076         M[3] = 0;
+02077 
+02078         M[4] = (T)(-s * scale.X);
+02079         M[5] = (T)(c * scale.Y);
+02080         M[6] = 0;
+02081         M[7] = 0;
+02082 
+02083         M[8] = (T)(c * scale.X * rotatecenter.X + -s * rotatecenter.Y + translate.X);
+02084         M[9] = (T)(s * scale.Y * rotatecenter.X +  c * rotatecenter.Y + translate.Y);
+02085         M[10] = 1;
+02086         M[11] = 0;
+02087 
+02088         M[12] = 0;
+02089         M[13] = 0;
+02090         M[14] = 0;
+02091         M[15] = 1;
+02092 #if defined ( USE_MATRIX_TEST )
+02093         definitelyIdentityMatrix=false;
+02094 #endif
+02095         return *this;
+02096     }
+02097 
+02098 
+02099     // rotate about z axis, center ( 0.5, 0.5 )
+02100     template <class T>
+02101     inline CMatrix4<T>& CMatrix4<T>::setTextureRotationCenter( f32 rotateRad )
+02102     {
+02103         const f32 c = cosf(rotateRad);
+02104         const f32 s = sinf(rotateRad);
+02105         M[0] = (T)c;
+02106         M[1] = (T)s;
+02107 
+02108         M[4] = (T)-s;
+02109         M[5] = (T)c;
+02110 
+02111         M[8] = (T)(0.5f * ( s - c) + 0.5f);
+02112         M[9] = (T)(-0.5f * ( s + c) + 0.5f);
+02113 
+02114 #if defined ( USE_MATRIX_TEST )
+02115         definitelyIdentityMatrix = definitelyIdentityMatrix && (rotateRad==0.0f);
+02116 #endif
+02117         return *this;
+02118     }
+02119 
+02120 
+02121     template <class T>
+02122     inline CMatrix4<T>& CMatrix4<T>::setTextureTranslate ( f32 x, f32 y )
+02123     {
+02124         M[8] = (T)x;
+02125         M[9] = (T)y;
+02126 
+02127 #if defined ( USE_MATRIX_TEST )
+02128         definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f);
+02129 #endif
+02130         return *this;
+02131     }
+02132 
+02133 
+02134     template <class T>
+02135     inline CMatrix4<T>& CMatrix4<T>::setTextureTranslateTransposed ( f32 x, f32 y )
+02136     {
+02137         M[2] = (T)x;
+02138         M[6] = (T)y;
+02139 
+02140 #if defined ( USE_MATRIX_TEST )
+02141         definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f) ;
+02142 #endif
+02143         return *this;
+02144     }
+02145 
+02146     template <class T>
+02147     inline CMatrix4<T>& CMatrix4<T>::setTextureScale ( f32 sx, f32 sy )
+02148     {
+02149         M[0] = (T)sx;
+02150         M[5] = (T)sy;
+02151 #if defined ( USE_MATRIX_TEST )
+02152         definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
+02153 #endif
+02154         return *this;
+02155     }
+02156 
+02157 
+02158     template <class T>
+02159     inline CMatrix4<T>& CMatrix4<T>::setTextureScaleCenter( f32 sx, f32 sy )
+02160     {
+02161         M[0] = (T)sx;
+02162         M[5] = (T)sy;
+02163         M[8] = (T)(0.5f - 0.5f * sx);
+02164         M[9] = (T)(0.5f - 0.5f * sy);
+02165 
+02166 #if defined ( USE_MATRIX_TEST )
+02167         definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
+02168 #endif
+02169         return *this;
+02170     }
+02171 
+02172 
+02173     // sets all matrix data members at once
+02174     template <class T>
+02175     inline CMatrix4<T>& CMatrix4<T>::setM(const T* data)
+02176     {
+02177         memcpy(M,data, 16*sizeof(T));
+02178 
+02179 #if defined ( USE_MATRIX_TEST )
+02180         definitelyIdentityMatrix=false;
+02181 #endif
+02182         return *this;
+02183     }
+02184 
+02185 
+02186     // sets if the matrix is definitely identity matrix
+02187     template <class T>
+02188     inline void CMatrix4<T>::setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix)
+02189     {
+02190 #if defined ( USE_MATRIX_TEST )
+02191         definitelyIdentityMatrix = isDefinitelyIdentityMatrix;
+02192 #endif
+02193     }
+02194 
+02195 
+02196     // gets if the matrix is definitely identity matrix
+02197     template <class T>
+02198     inline bool CMatrix4<T>::getDefinitelyIdentityMatrix() const
+02199     {
+02200 #if defined ( USE_MATRIX_TEST )
+02201         return definitelyIdentityMatrix;
+02202 #else
+02203         return false;
+02204 #endif
+02205     }
+02206 
+02207 
+02209     template <class T>
+02210     inline bool CMatrix4<T>::equals(const core::CMatrix4<T>& other, const T tolerance) const
+02211     {
+02212 #if defined ( USE_MATRIX_TEST )
+02213         if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
+02214             return true;
+02215 #endif
+02216         for (s32 i = 0; i < 16; ++i)
+02217             if (!core::equals(M[i],other.M[i], tolerance))
+02218                 return false;
+02219 
+02220         return true;
+02221     }
+02222 
+02223 
+02224     // Multiply by scalar.
+02225     template <class T>
+02226     inline CMatrix4<T> operator*(const T scalar, const CMatrix4<T>& mat)
+02227     {
+02228         return mat*scalar;
+02229     }
+02230 
+02231 
+02233     typedef CMatrix4<f32> matrix4;
+02234 
+02236     IRRLICHT_API extern const matrix4 IdentityMatrix;
+02237 
+02238 } // end namespace core
+02239 } // end namespace irr
+02240 
+02241 #endif
+02242 
+
+
+ + + + + -- cgit v1.1