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

# matrix4.h

Go to the documentation of this file.

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

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