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

The Irrlicht Engine
The Irrlicht Engine Documentation © 2003-2010 by Nikolaus Gebhardt. Generated on Sun Oct 24 12:41:57 2010 by Doxygen (1.6.2)