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