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 Documentation © 2003-2010 by Nikolaus Gebhardt. Generated on Sun Oct 24 12:41:57 2010 by Doxygen (1.6.2)