Home | Namespaces | Hierarchy | Alphabetical List | Class list | Files | Namespace Members | Class members | File members | Tutorials

matrix4.h

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

The Irrlicht Engine
The Irrlicht Engine Documentation © 2003-2009 by Nikolaus Gebhardt. Generated on Sun Jan 10 09:24:04 2010 by Doxygen (1.5.6)