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