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

matrix4.h

Go to the documentation of this file.
00001 // Copyright (C) 2002-2008 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 namespace irr
00017 {
00018 namespace core
00019 {
00020 
00022 
00023         template <class T>
00024         class CMatrix4
00025         {
00026                 public:
00027 
00029                         enum eConstructor
00030                         {
00031                                 EM4CONST_NOTHING = 0,
00032                                 EM4CONST_COPY,
00033                                 EM4CONST_IDENTITY,
00034                                 EM4CONST_TRANSPOSED,
00035                                 EM4CONST_INVERSE,
00036                                 EM4CONST_INVERSE_TRANSPOSED
00037                         };
00038 
00040 
00041                         CMatrix4( eConstructor constructor = EM4CONST_IDENTITY );
00043 
00045                         CMatrix4( const CMatrix4<T>& other,eConstructor constructor = EM4CONST_COPY);
00046 
00048                         T& operator()(const s32 row, const s32 col) { definitelyIdentityMatrix=false; return M[ row * 4 + col ]; }
00049 
00051                         const T& operator()(const s32 row, const s32 col) const { return M[row * 4 + col]; }
00052 
00054                         T& operator[](u32 index) { definitelyIdentityMatrix=false; return M[index]; }
00055 
00057                         const T& operator[](u32 index) const { return M[index]; }
00058 
00060                         inline CMatrix4<T>& operator=(const CMatrix4<T> &other);
00061 
00063                         inline CMatrix4<T>& operator=(const T& scalar);
00064 
00066                         const T* pointer() const { return M; }
00067                         T* pointer() { definitelyIdentityMatrix=false; return M; }
00068 
00070                         bool operator==(const CMatrix4<T> &other) const;
00071 
00073                         bool operator!=(const CMatrix4<T> &other) const;
00074 
00076                         CMatrix4<T> operator+(const CMatrix4<T>& other) const;
00077 
00079                         CMatrix4<T>& operator+=(const CMatrix4<T>& other);
00080 
00082                         CMatrix4<T> operator-(const CMatrix4<T>& other) const;
00083 
00085                         CMatrix4<T>& operator-=(const CMatrix4<T>& other);
00086 
00088                         inline CMatrix4<T>& setbyproduct(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
00089 
00091 
00093                         CMatrix4<T>& setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
00094 
00096                         CMatrix4<T> operator*(const CMatrix4<T>& other) const;
00097 
00099                         CMatrix4<T>& operator*=(const CMatrix4<T>& other);
00100 
00102                         CMatrix4<T> operator*(const T& scalar) const;
00103 
00105                         CMatrix4<T>& operator*=(const T& scalar);
00106 
00108                         inline CMatrix4<T>& makeIdentity();
00109 
00111                         inline bool isIdentity() const;
00112 
00114                         bool isIdentity_integer_base () const;
00115 
00117                         CMatrix4<T>& setTranslation( const vector3d<T>& translation );
00118 
00120                         vector3d<T> getTranslation() const;
00121 
00123                         CMatrix4<T>& setInverseTranslation( const vector3d<T>& translation );
00124 
00126                         inline CMatrix4<T>& setRotationRadians( const vector3d<T>& rotation );
00127 
00129                         CMatrix4<T>& setRotationDegrees( const vector3d<T>& rotation );
00130 
00132 
00133                         core::vector3d<T> getRotationDegrees() const;
00134 
00136 
00137                         inline CMatrix4<T>& setInverseRotationRadians( const vector3d<T>& rotation );
00138 
00140 
00141                         CMatrix4<T>& setInverseRotationDegrees( const vector3d<T>& rotation );
00142 
00144                         CMatrix4<T>& setScale( const vector3d<T>& scale );
00145 
00147                         CMatrix4<T>& setScale( const T scale ) { return setScale(core::vector3d<T>(scale,scale,scale)); }
00148 
00150                         core::vector3d<T> getScale() const;
00151 
00153                         void inverseTranslateVect( vector3df& vect ) const;
00154 
00156                         void inverseRotateVect( vector3df& vect ) const;
00157 
00159                         void rotateVect( vector3df& vect ) const;
00160 
00162                         void rotateVect(core::vector3df& out, const core::vector3df& in) const;
00163 
00165                         void rotateVect(T *out,const core::vector3df &in) const;
00166 
00168                         void transformVect( vector3df& vect) const;
00169 
00171                         void transformVect( vector3df& out, const vector3df& in ) const;
00172 
00174                         void transformVect(T *out,const core::vector3df &in) const;
00175 
00177                         void translateVect( vector3df& vect ) const;
00178 
00180                         void transformPlane( core::plane3d<f32> &plane) const;
00181 
00183                         void transformPlane_new( core::plane3d<f32> &plane) const;
00184 
00186                         void transformPlane( const core::plane3d<f32> &in, core::plane3d<f32> &out) const;
00187 
00189 
00191                         void transformBox(core::aabbox3d<f32>& box) const;
00192 
00194 
00196                         void transformBoxEx(core::aabbox3d<f32>& box) const;
00197 
00199                         void multiplyWith1x4Matrix(T* matrix) const;
00200 
00202 
00203                         bool makeInverse();
00204 
00205 
00207 
00208                         bool getInversePrimitive ( CMatrix4<T>& out ) const;
00209 
00211 
00213                         bool getInverse(CMatrix4<T>& out) const;
00214 
00216                         CMatrix4<T>& buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
00217 
00219                         CMatrix4<T>& buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
00220 
00222                         CMatrix4<T>& buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
00223 
00225                         CMatrix4<T>& buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
00226 
00228                         CMatrix4<T>& buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
00229 
00231                         CMatrix4<T>& buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
00232 
00234                         CMatrix4<T>& buildCameraLookAtMatrixLH(
00235                                         const vector3df& position,
00236                                         const vector3df& target,
00237                                         const vector3df& upVector);
00238 
00240                         CMatrix4<T>& buildCameraLookAtMatrixRH(
00241                                         const vector3df& position,
00242                                         const vector3df& target,
00243                                         const vector3df& upVector);
00244 
00246 
00250                         CMatrix4<T>& buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point=1.0f);
00251 
00253 
00254                         CMatrix4<T>& buildNDCToDCMatrix( const core::rect<s32>& area, f32 zScale);
00255 
00257 
00259                         CMatrix4<T> interpolate(const core::CMatrix4<T>& b, f32 time) const;
00260 
00262                         CMatrix4<T> getTransposed() const;
00263 
00265                         inline void getTransposed( CMatrix4<T>& dest ) const;
00266 
00267                         /*
00268                                 construct 2D Texture transformations
00269                                 rotate about center, scale, and transform.
00270                         */
00272                         CMatrix4<T>& buildTextureTransform( f32 rotateRad,
00273                                         const core::vector2df &rotatecenter,
00274                                         const core::vector2df &translate,
00275                                         const core::vector2df &scale);
00276 
00278 
00282                         CMatrix4<T>& setTextureRotationCenter( f32 radAngle );
00283 
00285 
00289                         CMatrix4<T>& setTextureTranslate( f32 x, f32 y );
00290 
00292 
00296                         CMatrix4<T>& setTextureScale( f32 sx, f32 sy );
00297 
00299 
00303                         CMatrix4<T>& setTextureScaleCenter( f32 sx, f32 sy );
00304 
00306                         CMatrix4<T>& setM(const T* data);
00307 
00309                         void setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix);
00310 
00312                         bool getDefinitelyIdentityMatrix() const;
00313 
00314                 private:
00316                         T M[16];
00318                         mutable bool definitelyIdentityMatrix;
00319         };
00320 
00321         // Default constructor
00322         template <class T>
00323         inline CMatrix4<T>::CMatrix4( eConstructor constructor ) : definitelyIdentityMatrix(false)
00324         {
00325                 switch ( constructor )
00326                 {
00327                         case EM4CONST_NOTHING:
00328                         case EM4CONST_COPY:
00329                                 break;
00330                         case EM4CONST_IDENTITY:
00331                         case EM4CONST_INVERSE:
00332                         default:
00333                                 makeIdentity();
00334                                 break;
00335                 }
00336         }
00337 
00338         // Copy constructor
00339         template <class T>
00340         inline CMatrix4<T>::CMatrix4( const CMatrix4<T>& other, eConstructor constructor) : definitelyIdentityMatrix(false)
00341         {
00342                 switch ( constructor )
00343                 {
00344                         case EM4CONST_IDENTITY:
00345                                 makeIdentity();
00346                                 break;
00347                         case EM4CONST_NOTHING:
00348                                 break;
00349                         case EM4CONST_COPY:
00350                                 *this = other;
00351                                 break;
00352                         case EM4CONST_TRANSPOSED:
00353                                 other.getTransposed(*this);
00354                                 break;
00355                         case EM4CONST_INVERSE:
00356                                 if (!other.getInverse(*this))
00357                                         memset(M, 0, 16*sizeof(T));
00358                                 break;
00359                         case EM4CONST_INVERSE_TRANSPOSED:
00360                                 if (!other.getInverse(*this))
00361                                         memset(M, 0, 16*sizeof(T));
00362                                 else
00363                                         *this=getTransposed();
00364                                 break;
00365                 }
00366         }
00367 
00369         template <class T>
00370         inline CMatrix4<T> CMatrix4<T>::operator+(const CMatrix4<T>& other) const
00371         {
00372                 CMatrix4<T> temp ( EM4CONST_NOTHING );
00373 
00374                 temp[0] = M[0]+other[0];
00375                 temp[1] = M[1]+other[1];
00376                 temp[2] = M[2]+other[2];
00377                 temp[3] = M[3]+other[3];
00378                 temp[4] = M[4]+other[4];
00379                 temp[5] = M[5]+other[5];
00380                 temp[6] = M[6]+other[6];
00381                 temp[7] = M[7]+other[7];
00382                 temp[8] = M[8]+other[8];
00383                 temp[9] = M[9]+other[9];
00384                 temp[10] = M[10]+other[10];
00385                 temp[11] = M[11]+other[11];
00386                 temp[12] = M[12]+other[12];
00387                 temp[13] = M[13]+other[13];
00388                 temp[14] = M[14]+other[14];
00389                 temp[15] = M[15]+other[15];
00390 
00391                 return temp;
00392         }
00393 
00395         template <class T>
00396         inline CMatrix4<T>& CMatrix4<T>::operator+=(const CMatrix4<T>& other)
00397         {
00398                 M[0]+=other[0];
00399                 M[1]+=other[1];
00400                 M[2]+=other[2];
00401                 M[3]+=other[3];
00402                 M[4]+=other[4];
00403                 M[5]+=other[5];
00404                 M[6]+=other[6];
00405                 M[7]+=other[7];
00406                 M[8]+=other[8];
00407                 M[9]+=other[9];
00408                 M[10]+=other[10];
00409                 M[11]+=other[11];
00410                 M[12]+=other[12];
00411                 M[13]+=other[13];
00412                 M[14]+=other[14];
00413                 M[15]+=other[15];
00414 
00415                 return *this;
00416         }
00417 
00419         template <class T>
00420         inline CMatrix4<T> CMatrix4<T>::operator-(const CMatrix4<T>& other) const
00421         {
00422                 CMatrix4<T> temp ( EM4CONST_NOTHING );
00423 
00424                 temp[0] = M[0]-other[0];
00425                 temp[1] = M[1]-other[1];
00426                 temp[2] = M[2]-other[2];
00427                 temp[3] = M[3]-other[3];
00428                 temp[4] = M[4]-other[4];
00429                 temp[5] = M[5]-other[5];
00430                 temp[6] = M[6]-other[6];
00431                 temp[7] = M[7]-other[7];
00432                 temp[8] = M[8]-other[8];
00433                 temp[9] = M[9]-other[9];
00434                 temp[10] = M[10]-other[10];
00435                 temp[11] = M[11]-other[11];
00436                 temp[12] = M[12]-other[12];
00437                 temp[13] = M[13]-other[13];
00438                 temp[14] = M[14]-other[14];
00439                 temp[15] = M[15]-other[15];
00440 
00441                 return temp;
00442         }
00443 
00445         template <class T>
00446         inline CMatrix4<T>& CMatrix4<T>::operator-=(const CMatrix4<T>& other)
00447         {
00448                 M[0]-=other[0];
00449                 M[1]-=other[1];
00450                 M[2]-=other[2];
00451                 M[3]-=other[3];
00452                 M[4]-=other[4];
00453                 M[5]-=other[5];
00454                 M[6]-=other[6];
00455                 M[7]-=other[7];
00456                 M[8]-=other[8];
00457                 M[9]-=other[9];
00458                 M[10]-=other[10];
00459                 M[11]-=other[11];
00460                 M[12]-=other[12];
00461                 M[13]-=other[13];
00462                 M[14]-=other[14];
00463                 M[15]-=other[15];
00464 
00465                 return *this;
00466         }
00467 
00469         template <class T>
00470         inline CMatrix4<T> CMatrix4<T>::operator*(const T& scalar) const
00471         {
00472                 CMatrix4<T> temp ( EM4CONST_NOTHING );
00473 
00474                 temp[0] = M[0]*scalar;
00475                 temp[1] = M[1]*scalar;
00476                 temp[2] = M[2]*scalar;
00477                 temp[3] = M[3]*scalar;
00478                 temp[4] = M[4]*scalar;
00479                 temp[5] = M[5]*scalar;
00480                 temp[6] = M[6]*scalar;
00481                 temp[7] = M[7]*scalar;
00482                 temp[8] = M[8]*scalar;
00483                 temp[9] = M[9]*scalar;
00484                 temp[10] = M[10]*scalar;
00485                 temp[11] = M[11]*scalar;
00486                 temp[12] = M[12]*scalar;
00487                 temp[13] = M[13]*scalar;
00488                 temp[14] = M[14]*scalar;
00489                 temp[15] = M[15]*scalar;
00490 
00491                 return temp;
00492         }
00493 
00495         template <class T>
00496         inline CMatrix4<T>& CMatrix4<T>::operator*=(const T& scalar)
00497         {
00498                 M[0]*=scalar;
00499                 M[1]*=scalar;
00500                 M[2]*=scalar;
00501                 M[3]*=scalar;
00502                 M[4]*=scalar;
00503                 M[5]*=scalar;
00504                 M[6]*=scalar;
00505                 M[7]*=scalar;
00506                 M[8]*=scalar;
00507                 M[9]*=scalar;
00508                 M[10]*=scalar;
00509                 M[11]*=scalar;
00510                 M[12]*=scalar;
00511                 M[13]*=scalar;
00512                 M[14]*=scalar;
00513                 M[15]*=scalar;
00514 
00515                 return *this;
00516         }
00517 
00519         template <class T>
00520         inline CMatrix4<T>& CMatrix4<T>::operator*=(const CMatrix4<T>& other)
00521         {
00522                 // do checks on your own in order to avoid copy creation
00523                 if ( !other.isIdentity() )
00524                 {
00525                         if ( this->isIdentity() )
00526                         {
00527                                 return (*this = other);
00528                         }
00529                         else
00530                         {
00531                                 CMatrix4<T> temp ( *this );
00532                                 return setbyproduct_nocheck( temp, other );
00533                         }
00534                 }
00535                 return *this;
00536         }
00537 
00539         // set this matrix to the product of two other matrices
00540         // goal is to reduce stack use and copy
00541         template <class T>
00542         inline CMatrix4<T>& CMatrix4<T>::setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b )
00543         {
00544                 const T *m1 = other_a.M;
00545                 const T *m2 = other_b.M;
00546 
00547                 M[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
00548                 M[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
00549                 M[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
00550                 M[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
00551 
00552                 M[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
00553                 M[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
00554                 M[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
00555                 M[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
00556 
00557                 M[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
00558                 M[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
00559                 M[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
00560                 M[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
00561 
00562                 M[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
00563                 M[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
00564                 M[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
00565                 M[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
00566                 definitelyIdentityMatrix=false;
00567                 return *this;
00568         }
00569 
00570 
00572         // set this matrix to the product of two other matrices
00573         // goal is to reduce stack use and copy
00574         template <class T>
00575         inline CMatrix4<T>& CMatrix4<T>::setbyproduct(const CMatrix4<T>& other_a, const CMatrix4<T>& other_b )
00576         {
00577                 if ( other_a.isIdentity () )
00578                         return (*this = other_b);
00579                 else
00580                 if ( other_b.isIdentity () )
00581                         return (*this = other_a);
00582                 else
00583                         return setbyproduct_nocheck(other_a,other_b);
00584         }
00585 
00587         template <class T>
00588         inline CMatrix4<T> CMatrix4<T>::operator*(const CMatrix4<T>& m2) const
00589         {
00590                 // Testing purpose..
00591                 if ( this->isIdentity() )
00592                         return m2;
00593                 if ( m2.isIdentity() )
00594                         return *this;
00595 
00596                 CMatrix4<T> m3 ( EM4CONST_NOTHING );
00597 
00598                 const T *m1 = M;
00599 
00600                 m3[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
00601                 m3[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
00602                 m3[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
00603                 m3[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
00604 
00605                 m3[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
00606                 m3[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
00607                 m3[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
00608                 m3[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
00609 
00610                 m3[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
00611                 m3[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
00612                 m3[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
00613                 m3[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
00614 
00615                 m3[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
00616                 m3[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
00617                 m3[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
00618                 m3[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
00619                 return m3;
00620         }
00621 
00622 
00623 
00624         template <class T>
00625         inline vector3d<T> CMatrix4<T>::getTranslation() const
00626         {
00627                 return vector3d<T>(M[12], M[13], M[14]);
00628         }
00629 
00630 
00631         template <class T>
00632         inline CMatrix4<T>& CMatrix4<T>::setTranslation( const vector3d<T>& translation )
00633         {
00634                 M[12] = translation.X;
00635                 M[13] = translation.Y;
00636                 M[14] = translation.Z;
00637                 definitelyIdentityMatrix=false;
00638                 return *this;
00639         }
00640 
00641         template <class T>
00642         inline CMatrix4<T>& CMatrix4<T>::setInverseTranslation( const vector3d<T>& translation )
00643         {
00644                 M[12] = -translation.X;
00645                 M[13] = -translation.Y;
00646                 M[14] = -translation.Z;
00647                 definitelyIdentityMatrix=false;
00648                 return *this;
00649         }
00650 
00651         template <class T>
00652         inline CMatrix4<T>& CMatrix4<T>::setScale( const vector3d<T>& scale )
00653         {
00654                 M[0] = scale.X;
00655                 M[5] = scale.Y;
00656                 M[10] = scale.Z;
00657                 definitelyIdentityMatrix=false;
00658                 return *this;
00659         }
00660 
00661         template <class T>
00662         inline vector3d<T> CMatrix4<T>::getScale() const
00663         {
00664                 return vector3d<T>(M[0],M[5],M[10]);
00665         }
00666 
00667         template <class T>
00668         inline CMatrix4<T>& CMatrix4<T>::setRotationDegrees( const vector3d<T>& rotation )
00669         {
00670                 return setRotationRadians( rotation * core::DEGTORAD );
00671         }
00672 
00673         template <class T>
00674         inline CMatrix4<T>& CMatrix4<T>::setInverseRotationDegrees( const vector3d<T>& rotation )
00675         {
00676                 return setInverseRotationRadians( rotation * core::DEGTORAD );
00677         }
00678 
00679         template <class T>
00680         inline CMatrix4<T>& CMatrix4<T>::setRotationRadians( const vector3d<T>& rotation )
00681         {
00682                 const f64 cr = cos( rotation.X );
00683                 const f64 sr = sin( rotation.X );
00684                 const f64 cp = cos( rotation.Y );
00685                 const f64 sp = sin( rotation.Y );
00686                 const f64 cy = cos( rotation.Z );
00687                 const f64 sy = sin( rotation.Z );
00688 
00689                 M[0] = (T)( cp*cy );
00690                 M[1] = (T)( cp*sy );
00691                 M[2] = (T)( -sp );
00692 
00693                 const f64 srsp = sr*sp;
00694                 const f64 crsp = cr*sp;
00695 
00696                 M[4] = (T)( srsp*cy-cr*sy );
00697                 M[5] = (T)( srsp*sy+cr*cy );
00698                 M[6] = (T)( sr*cp );
00699 
00700                 M[8] = (T)( crsp*cy+sr*sy );
00701                 M[9] = (T)( crsp*sy-sr*cy );
00702                 M[10] = (T)( cr*cp );
00703                 definitelyIdentityMatrix=false;
00704                 return *this;
00705         }
00706 
00707 
00710         template <class T>
00711         inline core::vector3d<T> CMatrix4<T>::getRotationDegrees() const
00712         {
00713                 const CMatrix4<T> &mat = *this;
00714 
00715                 f64 Y = -asin(mat(0,2));
00716                 const f64 C = cos(Y);
00717                 Y *= RADTODEG64;
00718 
00719                 f64 rotx, roty, X, Z;
00720 
00721                 if (fabs(C)>ROUNDING_ERROR_64)
00722                 {
00723                         const T invC = (T)(1.0/C);
00724                         rotx = mat(2,2) * invC;
00725                         roty = mat(1,2) * invC;
00726                         X = atan2( roty, rotx ) * RADTODEG64;
00727                         rotx = mat(0,0) * invC;
00728                         roty = mat(0,1) * invC;
00729                         Z = atan2( roty, rotx ) * RADTODEG64;
00730                 }
00731                 else
00732                 {
00733                         X = 0.0;
00734                         rotx = mat(1,1);
00735                         roty = -mat(1,0);
00736                         Z = atan2( roty, rotx ) * RADTODEG64;
00737                 }
00738 
00739                 // fix values that get below zero
00740                 // before it would set (!) values to 360
00741                 // that where above 360:
00742                 if (X < 0.0) X += 360.0;
00743                 if (Y < 0.0) Y += 360.0;
00744                 if (Z < 0.0) Z += 360.0;
00745 
00746                 return vector3d<T>((T)X,(T)Y,(T)Z);
00747         }
00748 
00749 
00750         template <class T>
00751         inline CMatrix4<T>& CMatrix4<T>::setInverseRotationRadians( const vector3d<T>& rotation )
00752         {
00753                 f64 cr = cos( rotation.X );
00754                 f64 sr = sin( rotation.X );
00755                 f64 cp = cos( rotation.Y );
00756                 f64 sp = sin( rotation.Y );
00757                 f64 cy = cos( rotation.Z );
00758                 f64 sy = sin( rotation.Z );
00759 
00760                 M[0] = (T)( cp*cy );
00761                 M[4] = (T)( cp*sy );
00762                 M[8] = (T)( -sp );
00763 
00764                 f64 srsp = sr*sp;
00765                 f64 crsp = cr*sp;
00766 
00767                 M[1] = (T)( srsp*cy-cr*sy );
00768                 M[5] = (T)( srsp*sy+cr*cy );
00769                 M[9] = (T)( sr*cp );
00770 
00771                 M[2] = (T)( crsp*cy+sr*sy );
00772                 M[6] = (T)( crsp*sy-sr*cy );
00773                 M[10] = (T)( cr*cp );
00774                 definitelyIdentityMatrix=false;
00775                 return *this;
00776         }
00777 
00778 
00781         template <class T>
00782         inline CMatrix4<T>& CMatrix4<T>::makeIdentity()
00783         {
00784                 memset(M, 0, 16*sizeof(T));
00785                 M[0] = M[5] = M[10] = M[15] = (T)1;
00786                 definitelyIdentityMatrix=true;
00787                 return *this;
00788         }
00789 
00790 
00791         /*
00792                 check identity with epsilon
00793                 solve floating range problems..
00794         */
00795         template <class T>
00796         inline bool CMatrix4<T>::isIdentity() const
00797         {
00798                 if (definitelyIdentityMatrix)
00799                         return true;
00800                 if (!equals( M[ 0], (T)1 ) ||
00801                                 !equals( M[ 5], (T)1 ) ||
00802                                 !equals( M[10], (T)1 ) ||
00803                                 !equals( M[15], (T)1 ))
00804                         return false;
00805 
00806                 for (s32 i=0; i<4; ++i)
00807                         for (s32 j=0; j<4; ++j)
00808                                 if ((j != i) && (!iszero((*this)(i,j))))
00809                                         return false;
00810 
00811                 definitelyIdentityMatrix=true;
00812                 return true;
00813         }
00814 
00815         /*
00816                 doesn't solve floating range problems..
00817                 but takes care on +/- 0 on translation because we are changing it..
00818                 reducing floating point branches
00819                 but it needs the floats in memory..
00820         */
00821         template <class T>
00822         inline bool CMatrix4<T>::isIdentity_integer_base() const
00823         {
00824                 if (definitelyIdentityMatrix)
00825                         return true;
00826                 if(IR(M[0])!=F32_VALUE_1)       return false;
00827                 if(IR(M[1])!=0)                 return false;
00828                 if(IR(M[2])!=0)                 return false;
00829                 if(IR(M[3])!=0)                 return false;
00830 
00831                 if(IR(M[4])!=0)                 return false;
00832                 if(IR(M[5])!=F32_VALUE_1)       return false;
00833                 if(IR(M[6])!=0)                 return false;
00834                 if(IR(M[7])!=0)                 return false;
00835 
00836                 if(IR(M[8])!=0)                 return false;
00837                 if(IR(M[9])!=0)                 return false;
00838                 if(IR(M[10])!=F32_VALUE_1)      return false;
00839                 if(IR(M[11])!=0)                return false;
00840 
00841                 if(IR(M[12])!=0)                return false;
00842                 if(IR(M[13])!=0)                return false;
00843                 if(IR(M[13])!=0)                return false;
00844                 if(IR(M[15])!=F32_VALUE_1)      return false;
00845                 definitelyIdentityMatrix=true;
00846                 return true;
00847         }
00848 
00849 
00850         template <class T>
00851         inline void CMatrix4<T>::rotateVect( vector3df& vect ) const
00852         {
00853                 vector3df tmp = vect;
00854                 vect.X = tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8];
00855                 vect.Y = tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9];
00856                 vect.Z = tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10];
00857         }
00858 
00860         template <class T>
00861         inline void CMatrix4<T>::rotateVect(core::vector3df& out, const core::vector3df& in) const
00862         {
00863                 out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
00864                 out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
00865                 out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
00866         }
00867 
00869         template <class T>
00870         inline void CMatrix4<T>::rotateVect(T *out, const core::vector3df& in) const
00871         {
00872                 out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
00873                 out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
00874                 out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
00875         }
00876 
00877         template <class T>
00878         inline void CMatrix4<T>::inverseRotateVect( vector3df& vect ) const
00879         {
00880                 vector3df tmp = vect;
00881                 vect.X = tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2];
00882                 vect.Y = tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6];
00883                 vect.Z = tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10];
00884         }
00885 
00886         template <class T>
00887         inline void CMatrix4<T>::transformVect( vector3df& vect) const
00888         {
00889                 f32 vector[3];
00890 
00891                 vector[0] = vect.X*M[0] + vect.Y*M[4] + vect.Z*M[8] + M[12];
00892                 vector[1] = vect.X*M[1] + vect.Y*M[5] + vect.Z*M[9] + M[13];
00893                 vector[2] = vect.X*M[2] + vect.Y*M[6] + vect.Z*M[10] + M[14];
00894 
00895                 vect.X = vector[0];
00896                 vect.Y = vector[1];
00897                 vect.Z = vector[2];
00898         }
00899 
00900         template <class T>
00901         inline void CMatrix4<T>::transformVect( vector3df& out, const vector3df& in) const
00902         {
00903                 out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
00904                 out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
00905                 out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
00906         }
00907 
00908 
00909         template <class T>
00910         inline void CMatrix4<T>::transformVect(T *out, const core::vector3df &in) const
00911         {
00912                 out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
00913                 out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
00914                 out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
00915                 out[3] = in.X*M[3] + in.Y*M[7] + in.Z*M[11] + M[15];
00916         }
00917 
00918 
00920         template <class T>
00921         inline void CMatrix4<T>::transformPlane( core::plane3d<f32> &plane) const
00922         {
00923                 vector3df member;
00924                 transformVect(member, plane.getMemberPoint());
00925 
00926                 vector3df origin(0,0,0);
00927                 transformVect(plane.Normal);
00928                 transformVect(origin);
00929 
00930                 plane.Normal -= origin;
00931                 plane.D = - member.dotProduct(plane.Normal);
00932         }
00933 
00935         template <class T>
00936         inline void CMatrix4<T>::transformPlane_new( core::plane3d<f32> &plane) const
00937         {
00938                 // rotate normal -> rotateVect ( plane.n );
00939                 vector3df n;
00940                 n.X = plane.Normal.X*M[0] + plane.Normal.Y*M[4] + plane.Normal.Z*M[8];
00941                 n.Y = plane.Normal.X*M[1] + plane.Normal.Y*M[5] + plane.Normal.Z*M[9];
00942                 n.Z = plane.Normal.X*M[2] + plane.Normal.Y*M[6] + plane.Normal.Z*M[10];
00943 
00944                 // compute new d. -> getTranslation(). dotproduct ( plane.n )
00945                 plane.D -= M[12] * n.X + M[13] * n.Y + M[14] * n.Z;
00946                 plane.Normal.X = n.X;
00947                 plane.Normal.Y = n.Y;
00948                 plane.Normal.Z = n.Z;
00949         }
00950 
00952         template <class T>
00953         inline void CMatrix4<T>::transformPlane( const core::plane3d<f32> &in, core::plane3d<f32> &out) const
00954         {
00955                 out = in;
00956                 transformPlane( out );
00957         }
00958 
00960         template <class T>
00961         inline void CMatrix4<T>::transformBox(core::aabbox3d<f32>& box) const
00962         {
00963                 if (isIdentity())
00964                         return;
00965 
00966                 transformVect(box.MinEdge);
00967                 transformVect(box.MaxEdge);
00968                 box.repair();
00969         }
00970 
00972         template <class T>
00973         inline void CMatrix4<T>::transformBoxEx(core::aabbox3d<f32>& box) const
00974         {
00975                 const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z};
00976                 const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z};
00977 
00978                 f32 Bmin[3];
00979                 f32 Bmax[3];
00980 
00981                 Bmin[0] = Bmax[0] = M[12];
00982                 Bmin[1] = Bmax[1] = M[13];
00983                 Bmin[2] = Bmax[2] = M[14];
00984 
00985                 const CMatrix4<T> &m = *this;
00986 
00987                 for (u32 i = 0; i < 3; ++i)
00988                 {
00989                         for (u32 j = 0; j < 3; ++j)
00990                         {
00991                                 const f32 a = m(j,i) * Amin[j];
00992                                 const f32 b = m(j,i) * Amax[j];
00993 
00994                                 if (a < b)
00995                                 {
00996                                         Bmin[i] += a;
00997                                         Bmax[i] += b;
00998                                 }
00999                                 else
01000                                 {
01001                                         Bmin[i] += b;
01002                                         Bmax[i] += a;
01003                                 }
01004                         }
01005                 }
01006 
01007                 box.MinEdge.X = Bmin[0];
01008                 box.MinEdge.Y = Bmin[1];
01009                 box.MinEdge.Z = Bmin[2];
01010 
01011                 box.MaxEdge.X = Bmax[0];
01012                 box.MaxEdge.Y = Bmax[1];
01013                 box.MaxEdge.Z = Bmax[2];
01014         }
01015 
01016 
01018         template <class T>
01019         inline void CMatrix4<T>::multiplyWith1x4Matrix(T* matrix) const
01020         {
01021                 /*
01022                 0  1  2  3
01023                 4  5  6  7
01024                 8  9  10 11
01025                 12 13 14 15
01026                 */
01027 
01028                 T mat[4];
01029                 mat[0] = matrix[0];
01030                 mat[1] = matrix[1];
01031                 mat[2] = matrix[2];
01032                 mat[3] = matrix[3];
01033 
01034                 matrix[0] = M[0]*mat[0] + M[4]*mat[1] + M[8]*mat[2] + M[12]*mat[3];
01035                 matrix[1] = M[1]*mat[0] + M[5]*mat[1] + M[9]*mat[2] + M[13]*mat[3];
01036                 matrix[2] = M[2]*mat[0] + M[6]*mat[1] + M[10]*mat[2] + M[14]*mat[3];
01037                 matrix[3] = M[3]*mat[0] + M[7]*mat[1] + M[11]*mat[2] + M[15]*mat[3];
01038         }
01039 
01040         template <class T>
01041         inline void CMatrix4<T>::inverseTranslateVect( vector3df& vect ) const
01042         {
01043                 vect.X = vect.X-M[12];
01044                 vect.Y = vect.Y-M[13];
01045                 vect.Z = vect.Z-M[14];
01046         }
01047 
01048         template <class T>
01049         inline void CMatrix4<T>::translateVect( vector3df& vect ) const
01050         {
01051                 vect.X = vect.X+M[12];
01052                 vect.Y = vect.Y+M[13];
01053                 vect.Z = vect.Z+M[14];
01054         }
01055 
01056 
01057         template <class T>
01058         inline bool CMatrix4<T>::getInverse(CMatrix4<T>& out) const
01059         {
01063 
01064                 if ( this->isIdentity() )
01065                 {
01066                         out=*this;
01067                         return true;
01068                 }
01069 
01070                 const CMatrix4<T> &m = *this;
01071 
01072                 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)) -
01073                         (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
01074                         (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)) +
01075                         (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) -
01076                         (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
01077                         (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0));
01078 
01079                 if( core::iszero ( d ) )
01080                         return false;
01081 
01082                 d = core::reciprocal ( d );
01083 
01084                 out(0, 0) = d * (m(1, 1) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) +
01085                                 m(1, 2) * (m(2, 3) * m(3, 1) - m(2, 1) * m(3, 3)) +
01086                                 m(1, 3) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)));
01087                 out(0, 1) = d * (m(2, 1) * (m(0, 2) * m(3, 3) - m(0, 3) * m(3, 2)) +
01088                                 m(2, 2) * (m(0, 3) * m(3, 1) - m(0, 1) * m(3, 3)) +
01089                                 m(2, 3) * (m(0, 1) * m(3, 2) - m(0, 2) * m(3, 1)));
01090                 out(0, 2) = d * (m(3, 1) * (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) +
01091                                 m(3, 2) * (m(0, 3) * m(1, 1) - m(0, 1) * m(1, 3)) +
01092                                 m(3, 3) * (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)));
01093                 out(0, 3) = d * (m(0, 1) * (m(1, 3) * m(2, 2) - m(1, 2) * m(2, 3)) +
01094                                 m(0, 2) * (m(1, 1) * m(2, 3) - m(1, 3) * m(2, 1)) +
01095                                 m(0, 3) * (m(1, 2) * m(2, 1) - m(1, 1) * m(2, 2)));
01096                 out(1, 0) = d * (m(1, 2) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) +
01097                                 m(1, 3) * (m(2, 2) * m(3, 0) - m(2, 0) * m(3, 2)) +
01098                                 m(1, 0) * (m(2, 3) * m(3, 2) - m(2, 2) * m(3, 3)));
01099                 out(1, 1) = d * (m(2, 2) * (m(0, 0) * m(3, 3) - m(0, 3) * m(3, 0)) +
01100                                 m(2, 3) * (m(0, 2) * m(3, 0) - m(0, 0) * m(3, 2)) +
01101                                 m(2, 0) * (m(0, 3) * m(3, 2) - m(0, 2) * m(3, 3)));
01102                 out(1, 2) = d * (m(3, 2) * (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) +
01103                                 m(3, 3) * (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2)) +
01104                                 m(3, 0) * (m(0, 3) * m(1, 2) - m(0, 2) * m(1, 3)));
01105                 out(1, 3) = d * (m(0, 2) * (m(1, 3) * m(2, 0) - m(1, 0) * m(2, 3)) +
01106                                 m(0, 3) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
01107                                 m(0, 0) * (m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2)));
01108                 out(2, 0) = d * (m(1, 3) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)) +
01109                                 m(1, 0) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
01110                                 m(1, 1) * (m(2, 3) * m(3, 0) - m(2, 0) * m(3, 3)));
01111                 out(2, 1) = d * (m(2, 3) * (m(0, 0) * m(3, 1) - m(0, 1) * m(3, 0)) +
01112                                 m(2, 0) * (m(0, 1) * m(3, 3) - m(0, 3) * m(3, 1)) +
01113                                 m(2, 1) * (m(0, 3) * m(3, 0) - m(0, 0) * m(3, 3)));
01114                 out(2, 2) = d * (m(3, 3) * (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) +
01115                                 m(3, 0) * (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) +
01116                                 m(3, 1) * (m(0, 3) * m(1, 0) - m(0, 0) * m(1, 3)));
01117                 out(2, 3) = d * (m(0, 3) * (m(1, 1) * m(2, 0) - m(1, 0) * m(2, 1)) +
01118                                 m(0, 0) * (m(1, 3) * m(2, 1) - m(1, 1) * m(2, 3)) +
01119                                 m(0, 1) * (m(1, 0) * m(2, 3) - m(1, 3) * m(2, 0)));
01120                 out(3, 0) = d * (m(1, 0) * (m(2, 2) * m(3, 1) - m(2, 1) * m(3, 2)) +
01121                                 m(1, 1) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
01122                                 m(1, 2) * (m(2, 1) * m(3, 0) - m(2, 0) * m(3, 1)));
01123                 out(3, 1) = d * (m(2, 0) * (m(0, 2) * m(3, 1) - m(0, 1) * m(3, 2)) +
01124                                 m(2, 1) * (m(0, 0) * m(3, 2) - m(0, 2) * m(3, 0)) +
01125                                 m(2, 2) * (m(0, 1) * m(3, 0) - m(0, 0) * m(3, 1)));
01126                 out(3, 2) = d * (m(3, 0) * (m(0, 2) * m(1, 1) - m(0, 1) * m(1, 2)) +
01127                                 m(3, 1) * (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) +
01128                                 m(3, 2) * (m(0, 1) * m(1, 0) - m(0, 0) * m(1, 1)));
01129                 out(3, 3) = d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) +
01130                                 m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) +
01131                                 m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0)));
01132                 out.definitelyIdentityMatrix = definitelyIdentityMatrix;
01133                 return true;
01134         }
01135 
01136 
01139         template <class T>
01140         inline bool CMatrix4<T>::getInversePrimitive ( CMatrix4<T>& out ) const
01141         {
01142                 out.M[0 ] = M[0];
01143                 out.M[1 ] = M[4];
01144                 out.M[2 ] = M[8];
01145                 out.M[3 ] = 0;
01146 
01147                 out.M[4 ] = M[1];
01148                 out.M[5 ] = M[5];
01149                 out.M[6 ] = M[9];
01150                 out.M[7 ] = 0;
01151 
01152                 out.M[8 ] = M[2];
01153                 out.M[9 ] = M[6];
01154                 out.M[10] = M[10];
01155                 out.M[11] = 0;
01156 
01157                 out.M[12] = (T)-(M[12]*M[0] + M[13]*M[1] + M[14]*M[2]);
01158                 out.M[13] = (T)-(M[12]*M[4] + M[13]*M[5] + M[14]*M[6]);
01159                 out.M[14] = (T)-(M[12]*M[8] + M[13]*M[9] + M[14]*M[10]);
01160                 out.M[15] = 1;
01161                 out.definitelyIdentityMatrix = definitelyIdentityMatrix;
01162                 return true;
01163         }
01164 
01167         template <class T>
01168         inline bool CMatrix4<T>::makeInverse()
01169         {
01170                 if (definitelyIdentityMatrix)
01171                         return true;
01172 
01173                 CMatrix4<T> temp ( EM4CONST_NOTHING );
01174 
01175                 if (getInverse(temp))
01176                 {
01177                         *this = temp;
01178                         return true;
01179                 }
01180 
01181                 return false;
01182         }
01183 
01184 
01185         template <class T>
01186         inline CMatrix4<T>& CMatrix4<T>::operator=(const CMatrix4<T> &other)
01187         {
01188                 if (this==&other)
01189                         return *this;
01190                 memcpy(M, other.M, 16*sizeof(T));
01191                 definitelyIdentityMatrix=other.definitelyIdentityMatrix;
01192                 return *this;
01193         }
01194 
01195 
01196         template <class T>
01197         inline CMatrix4<T>& CMatrix4<T>::operator=(const T& scalar)
01198         {
01199                 for (s32 i = 0; i < 16; ++i)
01200                         M[i]=scalar;
01201                 definitelyIdentityMatrix=false;
01202                 return *this;
01203         }
01204 
01205 
01206         template <class T>
01207         inline bool CMatrix4<T>::operator==(const CMatrix4<T> &other) const
01208         {
01209                 if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
01210                         return true;
01211                 for (s32 i = 0; i < 16; ++i)
01212                         if (M[i] != other.M[i])
01213                                 return false;
01214 
01215                 return true;
01216         }
01217 
01218 
01219         template <class T>
01220         inline bool CMatrix4<T>::operator!=(const CMatrix4<T> &other) const
01221         {
01222                 return !(*this == other);
01223         }
01224 
01225 
01226         // Builds a right-handed perspective projection matrix based on a field of view
01227         template <class T>
01228         inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovRH(
01229                         f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
01230         {
01231                 const f64 h = 1.0/tan(fieldOfViewRadians/2.0);
01232                 const T w = h / aspectRatio;
01233 
01234                 M[0] = w;
01235                 M[1] = 0;
01236                 M[2] = 0;
01237                 M[3] = 0;
01238 
01239                 M[4] = 0;
01240                 M[5] = (T)h;
01241                 M[6] = 0;
01242                 M[7] = 0;
01243 
01244                 M[8] = 0;
01245                 M[9] = 0;
01246                 M[10] = (T)(zFar/(zNear-zFar)); // DirectX version
01247 //              M[10] = (T)(zFar+zNear/(zNear-zFar)); // OpenGL version
01248                 M[11] = -1;
01249 
01250                 M[12] = 0;
01251                 M[13] = 0;
01252                 M[14] = (T)(zNear*zFar/(zNear-zFar)); // DirectX version
01253 //              M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar)); // OpenGL version
01254                 M[15] = 0;
01255                 definitelyIdentityMatrix=false;
01256                 return *this;
01257         }
01258 
01259 
01260         // Builds a left-handed perspective projection matrix based on a field of view
01261         template <class T>
01262         inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovLH(
01263                         f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
01264         {
01265                 const f64 h = 1.0/tan(fieldOfViewRadians/2.0);
01266                 const T w = (T)(h / aspectRatio);
01267 
01268                 M[0] = w;
01269                 M[1] = 0;
01270                 M[2] = 0;
01271                 M[3] = 0;
01272 
01273                 M[4] = 0;
01274                 M[5] = (T)h;
01275                 M[6] = 0;
01276                 M[7] = 0;
01277 
01278                 M[8] = 0;
01279                 M[9] = 0;
01280                 M[10] = (T)(zFar/(zFar-zNear));
01281                 M[11] = 1;
01282 
01283                 M[12] = 0;
01284                 M[13] = 0;
01285                 M[14] = (T)(-zNear*zFar/(zFar-zNear));
01286                 M[15] = 0;
01287                 definitelyIdentityMatrix=false;
01288                 return *this;
01289         }
01290 
01291 
01292         // Builds a left-handed orthogonal projection matrix.
01293         template <class T>
01294         inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoLH(
01295                         f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
01296         {
01297                 M[0] = (T)(2/widthOfViewVolume);
01298                 M[1] = 0;
01299                 M[2] = 0;
01300                 M[3] = 0;
01301 
01302                 M[4] = 0;
01303                 M[5] = (T)(2/heightOfViewVolume);
01304                 M[6] = 0;
01305                 M[7] = 0;
01306 
01307                 M[8] = 0;
01308                 M[9] = 0;
01309                 M[10] = (T)(1/(zFar-zNear));
01310                 M[11] = 0;
01311 
01312                 M[12] = 0;
01313                 M[13] = 0;
01314                 M[14] = (T)(zNear/(zNear-zFar));
01315                 M[15] = 1;
01316                 definitelyIdentityMatrix=false;
01317                 return *this;
01318         }
01319 
01320 
01321         // Builds a right-handed orthogonal projection matrix.
01322         template <class T>
01323         inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoRH(
01324                         f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
01325         {
01326                 M[0] = (T)(2/widthOfViewVolume);
01327                 M[1] = 0;
01328                 M[2] = 0;
01329                 M[3] = 0;
01330 
01331                 M[4] = 0;
01332                 M[5] = (T)(2/heightOfViewVolume);
01333                 M[6] = 0;
01334                 M[7] = 0;
01335 
01336                 M[8] = 0;
01337                 M[9] = 0;
01338                 M[10] = (T)(1/(zNear-zFar));
01339                 M[11] = 0;
01340 
01341                 M[12] = 0;
01342                 M[13] = 0;
01343                 M[14] = (T)(zNear/(zNear-zFar));
01344                 M[15] = -1;
01345                 definitelyIdentityMatrix=false;
01346                 return *this;
01347         }
01348 
01349 
01350         // Builds a right-handed perspective projection matrix.
01351         template <class T>
01352         inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveRH(
01353                         f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
01354         {
01355                 M[0] = (T)(2*zNear/widthOfViewVolume);
01356                 M[1] = 0;
01357                 M[2] = 0;
01358                 M[3] = 0;
01359 
01360                 M[4] = 0;
01361                 M[5] = (T)(2*zNear/heightOfViewVolume);
01362                 M[6] = 0;
01363                 M[7] = 0;
01364 
01365                 M[8] = 0;
01366                 M[9] = 0;
01367                 M[10] = (T)(zFar/(zNear-zFar));
01368                 M[11] = -1;
01369 
01370                 M[12] = 0;
01371                 M[13] = 0;
01372                 M[14] = (T)(zNear*zFar/(zNear-zFar));
01373                 M[15] = 0;
01374                 definitelyIdentityMatrix=false;
01375                 return *this;
01376         }
01377 
01378 
01379         // Builds a left-handed perspective projection matrix.
01380         template <class T>
01381         inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveLH(
01382                         f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
01383         {
01384                 M[0] = (T)(2*zNear/widthOfViewVolume);
01385                 M[1] = 0;
01386                 M[2] = 0;
01387                 M[3] = 0;
01388 
01389                 M[4] = 0;
01390                 M[5] = (T)(2*zNear/heightOfViewVolume);
01391                 M[6] = 0;
01392                 M[7] = 0;
01393 
01394                 M[8] = 0;
01395                 M[9] = 0;
01396                 M[10] = (T)(zFar/(zFar-zNear));
01397                 M[11] = 1;
01398 
01399                 M[12] = 0;
01400                 M[13] = 0;
01401                 M[14] = (T)(zNear*zFar/(zNear-zFar));
01402                 M[15] = 0;
01403                 definitelyIdentityMatrix=false;
01404                 return *this;
01405         }
01406 
01407 
01408         // Builds a matrix that flattens geometry into a plane.
01409         template <class T>
01410         inline CMatrix4<T>& CMatrix4<T>::buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point)
01411         {
01412                 plane.Normal.normalize();
01413                 const f32 d = plane.Normal.dotProduct(light);
01414 
01415                 M[ 0] = (T)(-plane.Normal.X * light.X + d);
01416                 M[ 1] = (T)(-plane.Normal.X * light.Y);
01417                 M[ 2] = (T)(-plane.Normal.X * light.