00001
00002
00003
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
00017
00018
00019
00020
00021
00022
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
00346
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
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
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
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
00651
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
00686
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
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
00798
00799
00800
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
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
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
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
00997
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
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029 #if defined ( USE_MATRIX_TEST )
01030 definitelyIdentityMatrix=true;
01031 #endif
01032 return true;
01033 }
01034
01035
01036
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
01062
01063
01064
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
01183 transformVect(member, plane.getMemberPoint());
01184
01185
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
01204 template <class T>
01205 _IRR_DEPRECATED_ inline void CMatrix4<T>::transformBox(core::aabbox3d<f32>& box) const
01206 {
01207 #if defined ( USE_MATRIX_TEST )
01208 if (isIdentity())
01209 return;
01210 #endif
01211
01212 transformVect(box.MinEdge);
01213 transformVect(box.MaxEdge);
01214 box.repair();
01215 }
01216
01218 template <class T>
01219 inline void CMatrix4<T>::transformBoxEx(core::aabbox3d<f32>& box) const
01220 {
01221 #if defined ( USE_MATRIX_TEST )
01222 if (isIdentity())
01223 return;
01224 #endif
01225
01226 const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z};
01227 const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z};
01228
01229 f32 Bmin[3];
01230 f32 Bmax[3];
01231
01232 Bmin[0] = Bmax[0] = M[12];
01233 Bmin[1] = Bmax[1] = M[13];
01234 Bmin[2] = Bmax[2] = M[14];
01235
01236 const CMatrix4<T> &m = *this;
01237
01238 for (u32 i = 0; i < 3; ++i)
01239 {
01240 for (u32 j = 0; j < 3; ++j)
01241 {
01242 const f32 a = m(j,i) * Amin[j];
01243 const f32 b = m(j,i) * Amax[j];
01244
01245 if (a < b)
01246 {
01247 Bmin[i] += a;
01248 Bmax[i] += b;
01249 }
01250 else
01251 {
01252 Bmin[i] += b;
01253 Bmax[i] += a;
01254 }
01255 }
01256 }
01257
01258 box.MinEdge.X = Bmin[0];
01259 box.MinEdge.Y = Bmin[1];
01260 box.MinEdge.Z = Bmin[2];
01261
01262 box.MaxEdge.X = Bmax[0];
01263 box.MaxEdge.Y = Bmax[1];
01264 box.MaxEdge.Z = Bmax[2];
01265 }
01266
01267
01269 template <class T>
01270 inline void CMatrix4<T>::multiplyWith1x4Matrix(T* matrix) const
01271 {
01272
01273
01274
01275
01276
01277
01278
01279 T mat[4];
01280 mat[0] = matrix[0];
01281 mat[1] = matrix[1];
01282 mat[2] = matrix[2];
01283 mat[3] = matrix[3];
01284
01285 matrix[0] = M[0]*mat[0] + M[4]*mat[1] + M[8]*mat[2] + M[12]*mat[3];
01286 matrix[1] = M[1]*mat[0] + M[5]*mat[1] + M[9]*mat[2] + M[13]*mat[3];
01287 matrix[2] = M[2]*mat[0] + M[6]*mat[1] + M[10]*mat[2] + M[14]*mat[3];
01288 matrix[3] = M[3]*mat[0] + M[7]*mat[1] + M[11]*mat[2] + M[15]*mat[3];
01289 }
01290
01291 template <class T>
01292 inline void CMatrix4<T>::inverseTranslateVect( vector3df& vect ) const
01293 {
01294 vect.X = vect.X-M[12];
01295 vect.Y = vect.Y-M[13];
01296 vect.Z = vect.Z-M[14];
01297 }
01298
01299 template <class T>
01300 inline void CMatrix4<T>::translateVect( vector3df& vect ) const
01301 {
01302 vect.X = vect.X+M[12];
01303 vect.Y = vect.Y+M[13];
01304 vect.Z = vect.Z+M[14];
01305 }
01306
01307
01308 template <class T>
01309 inline bool CMatrix4<T>::getInverse(CMatrix4<T>& out) const
01310 {
01314
01315 #if defined ( USE_MATRIX_TEST )
01316 if ( this->isIdentity() )
01317 {
01318 out=*this;
01319 return true;
01320 }
01321 #endif
01322 const CMatrix4<T> &m = *this;
01323
01324 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)) -
01325 (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
01326 (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)) +
01327 (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) -
01328 (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
01329 (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0));
01330
01331 if( core::iszero ( d, FLT_MIN ) )
01332 return false;
01333
01334 d = core::reciprocal ( d );
01335
01336 out(0, 0) = d * (m(1, 1) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) +
01337 m(1, 2) * (m(2, 3) * m(3, 1) - m(2, 1) * m(3, 3)) +
01338 m(1, 3) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)));
01339 out(0, 1) = d * (m(2, 1) * (m(0, 2) * m(3, 3) - m(0, 3) * m(3, 2)) +
01340 m(2, 2) * (m(0, 3) * m(3, 1) - m(0, 1) * m(3, 3)) +
01341 m(2, 3) * (m(0, 1) * m(3, 2) - m(0, 2) * m(3, 1)));
01342 out(0, 2) = d * (m(3, 1) * (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) +
01343 m(3, 2) * (m(0, 3) * m(1, 1) - m(0, 1) * m(1, 3)) +
01344 m(3, 3) * (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)));
01345 out(0, 3) = d * (m(0, 1) * (m(1, 3) * m(2, 2) - m(1, 2) * m(2, 3)) +
01346 m(0, 2) * (m(1, 1) * m(2, 3) - m(1, 3) * m(2, 1)) +
01347 m(0, 3) * (m(1, 2) * m(2, 1) - m(1, 1) * m(2, 2)));
01348 out(1, 0) = d * (m(1, 2) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) +
01349 m(1, 3) * (m(2, 2) * m(3, 0) - m(2, 0) * m(3, 2)) +
01350 m(1, 0) * (m(2, 3) * m(3, 2) - m(2, 2) * m(3, 3)));
01351 out(1, 1) = d * (m(2, 2) * (m(0, 0) * m(3, 3) - m(0, 3) * m(3, 0)) +
01352 m(2, 3) * (m(0, 2) * m(3, 0) - m(0, 0) * m(3, 2)) +
01353 m(2, 0) * (m(0, 3) * m(3, 2) - m(0, 2) * m(3, 3)));
01354 out(1, 2) = d * (m(3, 2) * (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) +
01355 m(3, 3) * (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2)) +
01356 m(3, 0) * (m(0, 3) * m(1, 2) - m(0, 2) * m(1, 3)));
01357 out(1, 3) = d * (m(0, 2) * (m(1, 3) * m(2, 0) - m(1, 0) * m(2, 3)) +
01358 m(0, 3) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
01359 m(0, 0) * (m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2)));
01360 out(2, 0) = d * (m(1, 3) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)) +
01361 m(1, 0) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
01362 m(1, 1) * (m(2, 3) * m(3, 0) - m(2, 0) * m(3, 3)));
01363 out(2, 1) = d * (m(2, 3) * (m(0, 0) * m(3, 1) - m(0, 1) * m(3, 0)) +
01364 m(2, 0) * (m(0, 1) * m(3, 3) - m(0, 3) * m(3, 1)) +
01365 m(2, 1) * (m(0, 3) * m(3, 0) - m(0, 0) * m(3, 3)));
01366 out(2, 2) = d * (m(3, 3) * (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) +
01367 m(3, 0) * (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) +
01368 m(3, 1) * (m(0, 3) * m(1, 0) - m(0, 0) * m(1, 3)));
01369 out(2, 3) = d * (m(0, 3) * (m(1, 1) * m(2, 0) - m(1, 0) * m(2, 1)) +
01370 m(0, 0) * (m(1, 3) * m(2, 1) - m(1, 1) * m(2, 3)) +
01371 m(0, 1) * (m(1, 0) * m(2, 3) - m(1, 3) * m(2, 0)));
01372 out(3, 0) = d * (m(1, 0) * (m(2, 2) * m(3, 1) - m(2, 1) * m(3, 2)) +
01373 m(1, 1) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
01374 m(1, 2) * (m(2, 1) * m(3, 0) - m(2, 0) * m(3, 1)));
01375 out(3, 1) = d * (m(2, 0) * (m(0, 2) * m(3, 1) - m(0, 1) * m(3, 2)) +
01376 m(2, 1) * (m(0, 0) * m(3, 2) - m(0, 2) * m(3, 0)) +
01377 m(2, 2) * (m(0, 1) * m(3, 0) - m(0, 0) * m(3, 1)));
01378 out(3, 2) = d * (m(3, 0) * (m(0, 2) * m(1, 1) - m(0, 1) * m(1, 2)) +
01379 m(3, 1) * (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) +
01380 m(3, 2) * (m(0, 1) * m(1, 0) - m(0, 0) * m(1, 1)));
01381 out(3, 3) = d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) +
01382 m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) +
01383 m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0)));
01384
01385 #if defined ( USE_MATRIX_TEST )
01386 out.definitelyIdentityMatrix = definitelyIdentityMatrix;
01387 #endif
01388 return true;
01389 }
01390
01391
01394 template <class T>
01395 inline bool CMatrix4<T>::getInversePrimitive ( CMatrix4<T>& out ) const
01396 {
01397 out.M[0 ] = M[0];
01398 out.M[1 ] = M[4];
01399 out.M[2 ] = M[8];
01400 out.M[3 ] = 0;
01401
01402 out.M[4 ] = M[1];
01403 out.M[5 ] = M[5];
01404 out.M[6 ] = M[9];
01405 out.M[7 ] = 0;
01406
01407 out.M[8 ] = M[2];
01408 out.M[9 ] = M[6];
01409 out.M[10] = M[10];
01410 out.M[11] = 0;
01411
01412 out.M[12] = (T)-(M[12]*M[0] + M[13]*M[1] + M[14]*M[2]);
01413 out.M[13] = (T)-(M[12]*M[4] + M[13]*M[5] + M[14]*M[6]);
01414 out.M[14] = (T)-(M[12]*M[8] + M[13]*M[9] + M[14]*M[10]);
01415 out.M[15] = 1;
01416
01417 #if defined ( USE_MATRIX_TEST )
01418 out.definitelyIdentityMatrix = definitelyIdentityMatrix;
01419 #endif
01420 return true;
01421 }
01422
01425 template <class T>
01426 inline bool CMatrix4<T>::makeInverse()
01427 {
01428 #if defined ( USE_MATRIX_TEST )
01429 if (definitelyIdentityMatrix)
01430 return true;
01431 #endif
01432 CMatrix4<T> temp ( EM4CONST_NOTHING );
01433
01434 if (getInverse(temp))
01435 {
01436 *this = temp;
01437 return true;
01438 }
01439
01440 return false;
01441 }
01442
01443
01444 template <class T>
01445 inline CMatrix4<T>& CMatrix4<T>::operator=(const CMatrix4<T> &other)
01446 {
01447 if (this==&other)
01448 return *this;
01449 memcpy(M, other.M, 16*sizeof(T));
01450 #if defined ( USE_MATRIX_TEST )
01451 definitelyIdentityMatrix=other.definitelyIdentityMatrix;
01452 #endif
01453 return *this;
01454 }
01455
01456
01457 template <class T>
01458 inline CMatrix4<T>& CMatrix4<T>::operator=(const T& scalar)
01459 {
01460 for (s32 i = 0; i < 16; ++i)
01461 M[i]=scalar;
01462
01463 #if defined ( USE_MATRIX_TEST )
01464 definitelyIdentityMatrix=false;
01465 #endif
01466 return *this;
01467 }
01468
01469
01470 template <class T>
01471 inline bool CMatrix4<T>::operator==(const CMatrix4<T> &other) const
01472 {
01473 #if defined ( USE_MATRIX_TEST )
01474 if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
01475 return true;
01476 #endif
01477 for (s32 i = 0; i < 16; ++i)
01478 if (M[i] != other.M[i])
01479 return false;
01480
01481 return true;
01482 }
01483
01484
01485 template <class T>
01486 inline bool CMatrix4<T>::operator!=(const CMatrix4<T> &other) const
01487 {
01488 return !(*this == other);
01489 }
01490
01491
01492
01493 template <class T>
01494 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovRH(
01495 f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
01496 {
01497 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
01498 _IRR_DEBUG_BREAK_IF(aspectRatio==0.f);
01499 const T w = static_cast<T>(h / aspectRatio);
01500
01501 _IRR_DEBUG_BREAK_IF(zNear==zFar);
01502 M[0] = w;
01503 M[1] = 0;
01504 M[2] = 0;
01505 M[3] = 0;
01506
01507 M[4] = 0;
01508 M[5] = (T)h;
01509 M[6] = 0;
01510 M[7] = 0;
01511
01512 M[8] = 0;
01513 M[9] = 0;
01514 M[10] = (T)(zFar/(zNear-zFar));
01515
01516 M[11] = -1;
01517
01518 M[12] = 0;
01519 M[13] = 0;
01520 M[14] = (T)(zNear*zFar/(zNear-zFar));
01521
01522 M[15] = 0;
01523
01524 #if defined ( USE_MATRIX_TEST )
01525 definitelyIdentityMatrix=false;
01526 #endif
01527 return *this;
01528 }
01529
01530
01531
01532 template <class T>
01533 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovLH(
01534 f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
01535 {
01536 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
01537 _IRR_DEBUG_BREAK_IF(aspectRatio==0.f);
01538 const T w = static_cast<T>(h / aspectRatio);
01539
01540 _IRR_DEBUG_BREAK_IF(zNear==zFar);
01541 M[0] = w;
01542 M[1] = 0;
01543 M[2] = 0;
01544 M[3] = 0;
01545
01546 M[4] = 0;
01547 M[5] = (T)h;
01548 M[6] = 0;
01549 M[7] = 0;
01550
01551 M[8] = 0;
01552 M[9] = 0;
01553 M[10] = (T)(zFar/(zFar-zNear));
01554 M[11] = 1;
01555
01556 M[12] = 0;
01557 M[13] = 0;
01558 M[14] = (T)(-zNear*zFar/(zFar-zNear));
01559 M[15] = 0;
01560
01561 #if defined ( USE_MATRIX_TEST )
01562 definitelyIdentityMatrix=false;
01563 #endif
01564 return *this;
01565 }
01566
01567
01568
01569 template <class T>
01570 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovInfinityLH(
01571 f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon)
01572 {
01573 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
01574 _IRR_DEBUG_BREAK_IF(aspectRatio==0.f);
01575 const T w = static_cast<T>(h / aspectRatio);
01576
01577 M[0] = w;
01578 M[1] = 0;
01579 M[2] = 0;
01580 M[3] = 0;
01581
01582 M[4] = 0;
01583 M[5] = (T)h;
01584 M[6] = 0;
01585 M[7] = 0;
01586
01587 M[8] = 0;
01588 M[9] = 0;
01589 M[10] = (T)(1.f-epsilon);
01590 M[11] = 1;
01591
01592 M[12] = 0;
01593 M[13] = 0;
01594 M[14] = (T)(zNear*(epsilon-1.f));
01595 M[15] = 0;
01596
01597 #if defined ( USE_MATRIX_TEST )
01598 definitelyIdentityMatrix=false;
01599 #endif
01600 return *this;
01601 }
01602
01603
01604
01605 template <class T>
01606 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoLH(
01607 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
01608 {
01609 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f);
01610 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f);
01611 _IRR_DEBUG_BREAK_IF(zNear==zFar);
01612 M[0] = (T)(2/widthOfViewVolume);
01613 M[1] = 0;
01614 M[2] = 0;
01615 M[3] = 0;
01616
01617 M[4] = 0;
01618 M[5] = (T)(2/heightOfViewVolume);
01619 M[6] = 0;
01620 M[7] = 0;
01621
01622 M[8] = 0;
01623 M[9] = 0;
01624 M[10] = (T)(1/(zFar-zNear));
01625 M[11] = 0;
01626
01627 M[12] = 0;
01628 M[13] = 0;
01629 M[14] = (T)(zNear/(zNear-zFar));
01630 M[15] = 1;
01631
01632 #if defined ( USE_MATRIX_TEST )
01633 definitelyIdentityMatrix=false;
01634 #endif
01635 return *this;
01636 }
01637
01638
01639
01640 template <class T>
01641 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoRH(
01642 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
01643 {
01644 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f);
01645 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f);
01646 _IRR_DEBUG_BREAK_IF(zNear==zFar);
01647 M[0] = (T)(2/widthOfViewVolume);
01648 M[1] = 0;
01649 M[2] = 0;
01650 M[3] = 0;
01651
01652 M[4] = 0;
01653 M[5] = (T)(2/heightOfViewVolume);
01654 M[6] = 0;
01655 M[7] = 0;
01656
01657 M[8] = 0;
01658 M[9] = 0;
01659 M[10] = (T)(1/(zNear-zFar));
01660 M[11] = 0;
01661
01662 M[12] = 0;
01663 M[13] = 0;
01664 M[14] = (T)(zNear/(zNear-zFar));
01665 M[15] = 1;
01666
01667 #if defined ( USE_MATRIX_TEST )
01668 definitelyIdentityMatrix=false;
01669 #endif
01670 return *this;
01671 }
01672
01673
01674
01675 template <class T>
01676 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveRH(
01677 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
01678 {
01679 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f);
01680 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f);
01681 _IRR_DEBUG_BREAK_IF(zNear==zFar);
01682 M[0] = (T)(2*zNear/widthOfViewVolume);
01683 M[1] = 0;
01684 M[2] = 0;
01685 M[3] = 0;
01686
01687 M[4] = 0;
01688 M[5] = (T)(2*zNear/heightOfViewVolume);
01689 M[6] = 0;
01690 M[7] = 0;
01691
01692 M[8] = 0;
01693 M[9] = 0;
01694 M[10] = (T)(zFar/(zNear-zFar));
01695 M[11] = -1;
01696
01697 M[12] = 0;
01698 M[13] = 0;
01699 M[14] = (T)(zNear*zFar/(zNear-zFar));
01700 M[15] = 0;
01701
01702 #if defined ( USE_MATRIX_TEST )
01703 definitelyIdentityMatrix=false;
01704 #endif
01705 return *this;
01706 }
01707
01708
01709
01710 template <class T>
01711 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveLH(
01712 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
01713 {
01714 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f);
01715 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f);
01716 _IRR_DEBUG_BREAK_IF(zNear==zFar);
01717 M[0] = (T)(2*zNear/widthOfViewVolume);
01718 M[1] = 0;
01719 M[2] = 0;
01720 M[3] = 0;
01721
01722 M[4] = 0;
01723 M[5] = (T)(2*zNear/heightOfViewVolume);
01724 M[6] = 0;
01725 M[7] = 0;
01726
01727 M[8] = 0;
01728 M[9] = 0;
01729 M[10] = (T)(zFar/(zFar-zNear));
01730 M[11] = 1;
01731
01732 M[12] = 0;
01733 M[13] = 0;
01734 M[14] = (T)(zNear*zFar/(zNear-zFar));
01735 M[15] = 0;
01736 #if defined ( USE_MATRIX_TEST )
01737 definitelyIdentityMatrix=false;
01738 #endif
01739 return *this;
01740 }
01741
01742
01743
01744 template <class T>
01745 inline CMatrix4<T>& CMatrix4<T>::buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point)
01746 {
01747 plane.Normal.normalize();
01748 const f32 d = plane.Normal.dotProduct(light);
01749
01750 M[ 0] = (T)(-plane.Normal.X * light.X + d);
01751 M[ 1] = (T)(-plane.Normal.X * light.Y);
01752 M[ 2] = (T)(-plane.Normal.X * light.Z);
01753 M[ 3] = (T)(-plane.Normal.X * point);
01754
01755 M[ 4] = (T)(-plane.Normal.Y * light.X);
01756 M[ 5] = (T)(-plane.Normal.Y * light.Y + d);
01757 M[ 6] = (T)(-plane.Normal.Y * light.Z);
01758 M[ 7] = (T)(-plane.Normal.Y * point);
01759
01760 M[ 8] = (T)(-plane.Normal.Z * light.X);
01761 M[ 9] = (T)(-plane.Normal.Z * light.Y);
01762 M[10] = (T)(-plane.Normal.Z * light.Z + d);
01763 M[11] = (T)(-plane.Normal.Z * point);
01764
01765 M[12] = (T)(-plane.D * light.X);
01766 M[13] = (T)(-plane.D * light.Y);
01767 M[14] = (T)(-plane.D * light.Z);
01768 M[15] = (T)(-plane.D * point + d);
01769 #if defined ( USE_MATRIX_TEST )
01770 definitelyIdentityMatrix=false;
01771 #endif
01772 return *this;
01773 }
01774
01775
01776 template <class T>
01777 inline CMatrix4<T>& CMatrix4<T>::buildCameraLookAtMatrixLH(
01778 const vector3df& position,
01779 const vector3df& target,
01780 const vector3df& upVector)
01781 {
01782 vector3df zaxis = target - position;
01783 zaxis.normalize();
01784
01785 vector3df xaxis = upVector.crossProduct(zaxis);
01786 xaxis.normalize();
01787
01788 vector3df yaxis = zaxis.crossProduct(xaxis);
01789
01790 M[0] = (T)xaxis.X;
01791 M[1] = (T)yaxis.X;
01792 M[2] = (T)zaxis.X;
01793 M[3] = 0;
01794
01795 M[4] = (T)xaxis.Y;
01796 M[5] = (T)yaxis.Y;
01797 M[6] = (T)zaxis.Y;
01798 M[7] = 0;
01799
01800 M[8] = (T)xaxis.Z;
01801 M[9] = (T)yaxis.Z;
01802 M[10] = (T)zaxis.Z;
01803 M[11] = 0;
01804
01805 M[12] = (T)-xaxis.dotProduct(position);
01806 M[13] = (T)-yaxis.dotProduct(position);
01807 M[14] = (T)-zaxis.dotProduct(position);
01808 M[15] = 1;
01809 #if defined ( USE_MATRIX_TEST )
01810 definitelyIdentityMatrix=false;
01811 #endif
01812 return *this;
01813 }
01814
01815
01816
01817 template <class T>
01818 inline CMatrix4<T>& CMatrix4<T>::buildCameraLookAtMatrixRH(
01819 const vector3df& position,
01820 const vector3df& target,
01821 const vector3df& upVector)
01822 {
01823 vector3df zaxis = position - target;
01824 zaxis.normalize();
01825
01826 vector3df xaxis = upVector.crossProduct(zaxis);
01827 xaxis.normalize();
01828
01829 vector3df yaxis = zaxis.crossProduct(xaxis);
01830
01831 M[0] = (T)xaxis.X;
01832 M[1] = (T)yaxis.X;
01833 M[2] = (T)zaxis.X;
01834 M[3] = 0;
01835
01836 M[4] = (T)xaxis.Y;
01837 M[5] = (T)yaxis.Y;
01838 M[6] = (T)zaxis.Y;
01839 M[7] = 0;
01840
01841 M[8] = (T)xaxis.Z;
01842 M[9] = (T)yaxis.Z;
01843 M[10] = (T)zaxis.Z;
01844 M[11] = 0;
01845
01846 M[12] = (T)-xaxis.dotProduct(position);
01847 M[13] = (T)-yaxis.dotProduct(position);
01848 M[14] = (T)-zaxis.dotProduct(position);
01849 M[15] = 1;
01850 #if defined ( USE_MATRIX_TEST )
01851 definitelyIdentityMatrix=false;
01852 #endif
01853 return *this;
01854 }
01855
01856
01857
01858 template <class T>
01859 inline CMatrix4<T> CMatrix4<T>::interpolate(const core::CMatrix4<T>& b, f32 time) const
01860 {
01861 CMatrix4<T> mat ( EM4CONST_NOTHING );
01862
01863 for (u32 i=0; i < 16; i += 4)
01864 {
01865 mat.M[i+0] = (T)(M[i+0] + ( b.M[i+0] - M[i+0] ) * time);
01866 mat.M[i+1] = (T)(M[i+1] + ( b.M[i+1] - M[i+1] ) * time);
01867 mat.M[i+2] = (T)(M[i+2] + ( b.M[i+2] - M[i+2] ) * time);
01868 mat.M[i+3] = (T)(M[i+3] + ( b.M[i+3] - M[i+3] ) * time);
01869 }
01870 return mat;
01871 }
01872
01873
01874
01875 template <class T>
01876 inline CMatrix4<T> CMatrix4<T>::getTransposed() const
01877 {
01878 CMatrix4<T> t ( EM4CONST_NOTHING );
01879 getTransposed ( t );
01880 return t;
01881 }
01882
01883
01884
01885 template <class T>
01886 inline void CMatrix4<T>::getTransposed( CMatrix4<T>& o ) const
01887 {
01888 o[ 0] = M[ 0];
01889 o[ 1] = M[ 4];
01890 o[ 2] = M[ 8];
01891 o[ 3] = M[12];
01892
01893 o[ 4] = M[ 1];
01894 o[ 5] = M[ 5];
01895 o[ 6] = M[ 9];
01896 o[ 7] = M[13];
01897
01898 o[ 8] = M[ 2];
01899 o[ 9] = M[ 6];
01900 o[10] = M[10];
01901 o[11] = M[14];
01902
01903 o[12] = M[ 3];
01904 o[13] = M[ 7];
01905 o[14] = M[11];
01906 o[15] = M[15];
01907 #if defined ( USE_MATRIX_TEST )
01908 o.definitelyIdentityMatrix=definitelyIdentityMatrix;
01909 #endif
01910 }
01911
01912
01913
01914 template <class T>
01915 inline CMatrix4<T>& CMatrix4<T>::buildNDCToDCMatrix( const core::rect<s32>& viewport, f32 zScale)
01916 {
01917 const f32 scaleX = (viewport.getWidth() - 0.75f ) * 0.5f;
01918 const f32 scaleY = -(viewport.getHeight() - 0.75f ) * 0.5f;
01919
01920 const f32 dx = -0.5f + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) * 0.5f );
01921 const f32 dy = -0.5f + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) * 0.5f );
01922
01923 makeIdentity();
01924 M[12] = (T)dx;
01925 M[13] = (T)dy;
01926 return setScale(core::vector3d<T>((T)scaleX, (T)scaleY, (T)zScale));
01927 }
01928
01930
01935 template <class T>
01936 inline CMatrix4<T>& CMatrix4<T>::buildRotateFromTo(const core::vector3df& from, const core::vector3df& to)
01937 {
01938
01939 core::vector3df f(from);
01940 core::vector3df t(to);
01941 f.normalize();
01942 t.normalize();
01943
01944
01945 core::vector3df vs(t.crossProduct(f));
01946
01947
01948 core::vector3df v(vs);
01949 v.normalize();
01950
01951
01952 T ca = f.dotProduct(t);
01953
01954 core::vector3df vt(v * (1 - ca));
01955
01956 M[0] = vt.X * v.X + ca;
01957 M[5] = vt.Y * v.Y + ca;
01958 M[10] = vt.Z * v.Z + ca;
01959
01960 vt.X *= v.Y;
01961 vt.Z *= v.X;
01962 vt.Y *= v.Z;
01963
01964 M[1] = vt.X - vs.Z;
01965 M[2] = vt.Z + vs.Y;
01966 M[3] = 0;
01967
01968 M[4] = vt.X + vs.Z;
01969 M[6] = vt.Y - vs.X;
01970 M[7] = 0;
01971
01972 M[8] = vt.Z - vs.Y;
01973 M[9] = vt.Y + vs.X;
01974 M[11] = 0;
01975
01976 M[12] = 0;
01977 M[13] = 0;
01978 M[14] = 0;
01979 M[15] = 1;
01980
01981 return *this;
01982 }
01983
01985
01991 template <class T>
01992 inline void CMatrix4<T>::buildAxisAlignedBillboard(
01993 const core::vector3df& camPos,
01994 const core::vector3df& center,
01995 const core::vector3df& translation,
01996 const core::vector3df& axis,
01997 const core::vector3df& from)
01998 {
01999
02000 core::vector3df up = axis;
02001 up.normalize();
02002 const core::vector3df forward = (camPos - center).normalize();
02003 const core::vector3df right = up.crossProduct(forward).normalize();
02004
02005
02006 const core::vector3df look = right.crossProduct(up);
02007
02008
02009
02010 const core::vector3df vs = look.crossProduct(from);
02011
02012
02013 const f32 ca = from.dotProduct(look);
02014
02015 core::vector3df vt(up * (1.f - ca));
02016
02017 M[0] = static_cast<T>(vt.X * up.X + ca);
02018 M[5] = static_cast<T>(vt.Y * up.Y + ca);
02019 M[10] = static_cast<T>(vt.Z * up.Z + ca);
02020
02021 vt.X *= up.Y;
02022 vt.Z *= up.X;
02023 vt.Y *= up.Z;
02024
02025 M[1] = static_cast<T>(vt.X - vs.Z);
02026 M[2] = static_cast<T>(vt.Z + vs.Y);
02027 M[3] = 0;
02028
02029 M[4] = static_cast<T>(vt.X + vs.Z);
02030 M[6] = static_cast<T>(vt.Y - vs.X);
02031 M[7] = 0;
02032
02033 M[8] = static_cast<T>(vt.Z - vs.Y);
02034 M[9] = static_cast<T>(vt.Y + vs.X);
02035 M[11] = 0;
02036
02037 setRotationCenter(center, translation);
02038 }
02039
02040
02042 template <class T>
02043 inline void CMatrix4<T>::setRotationCenter(const core::vector3df& center, const core::vector3df& translation)
02044 {
02045 M[12] = -M[0]*center.X - M[4]*center.Y - M[8]*center.Z + (center.X - translation.X );
02046 M[13] = -M[1]*center.X - M[5]*center.Y - M[9]*center.Z + (center.Y - translation.Y );
02047 M[14] = -M[2]*center.X - M[6]*center.Y - M[10]*center.Z + (center.Z - translation.Z );
02048 M[15] = (T) 1.0;
02049 #if defined ( USE_MATRIX_TEST )
02050 definitelyIdentityMatrix=false;
02051 #endif
02052 }
02053
02066 template <class T>
02067 inline CMatrix4<T>& CMatrix4<T>::buildTextureTransform( f32 rotateRad,
02068 const core::vector2df &rotatecenter,
02069 const core::vector2df &translate,
02070 const core::vector2df &scale)
02071 {
02072 const f32 c = cosf(rotateRad);
02073 const f32 s = sinf(rotateRad);
02074
02075 M[0] = (T)(c * scale.X);
02076 M[1] = (T)(s * scale.Y);
02077 M[2] = 0;
02078 M[3] = 0;
02079
02080 M[4] = (T)(-s * scale.X);
02081 M[5] = (T)(c * scale.Y);
02082 M[6] = 0;
02083 M[7] = 0;
02084
02085 M[8] = (T)(c * scale.X * rotatecenter.X + -s * rotatecenter.Y + translate.X);
02086 M[9] = (T)(s * scale.Y * rotatecenter.X + c * rotatecenter.Y + translate.Y);
02087 M[10] = 1;
02088 M[11] = 0;
02089
02090 M[12] = 0;
02091 M[13] = 0;
02092 M[14] = 0;
02093 M[15] = 1;
02094 #if defined ( USE_MATRIX_TEST )
02095 definitelyIdentityMatrix=false;
02096 #endif
02097 return *this;
02098 }
02099
02100
02101
02102 template <class T>
02103 inline CMatrix4<T>& CMatrix4<T>::setTextureRotationCenter( f32 rotateRad )
02104 {
02105 const f32 c = cosf(rotateRad);
02106 const f32 s = sinf(rotateRad);
02107 M[0] = (T)c;
02108 M[1] = (T)s;
02109
02110 M[4] = (T)-s;
02111 M[5] = (T)c;
02112
02113 M[8] = (T)(0.5f * ( s - c) + 0.5f);
02114 M[9] = (T)(-0.5f * ( s + c) + 0.5f);
02115
02116 #if defined ( USE_MATRIX_TEST )
02117 definitelyIdentityMatrix = definitelyIdentityMatrix && (rotateRad==0.0f);
02118 #endif
02119 return *this;
02120 }
02121
02122
02123 template <class T>
02124 inline CMatrix4<T>& CMatrix4<T>::setTextureTranslate ( f32 x, f32 y )
02125 {
02126 M[8] = (T)x;
02127 M[9] = (T)y;
02128
02129 #if defined ( USE_MATRIX_TEST )
02130 definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f);
02131 #endif
02132 return *this;
02133 }
02134
02135
02136 template <class T>
02137 inline CMatrix4<T>& CMatrix4<T>::setTextureTranslateTransposed ( f32 x, f32 y )
02138 {
02139 M[2] = (T)x;
02140 M[6] = (T)y;
02141
02142 #if defined ( USE_MATRIX_TEST )
02143 definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f) ;
02144 #endif
02145 return *this;
02146 }
02147
02148 template <class T>
02149 inline CMatrix4<T>& CMatrix4<T>::setTextureScale ( f32 sx, f32 sy )
02150 {
02151 M[0] = (T)sx;
02152 M[5] = (T)sy;
02153 #if defined ( USE_MATRIX_TEST )
02154 definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
02155 #endif
02156 return *this;
02157 }
02158
02159
02160 template <class T>
02161 inline CMatrix4<T>& CMatrix4<T>::setTextureScaleCenter( f32 sx, f32 sy )
02162 {
02163 M[0] = (T)sx;
02164 M[5] = (T)sy;
02165 M[8] = (T)(0.5f - 0.5f * sx);
02166 M[9] = (T)(0.5f - 0.5f * sy);
02167
02168 #if defined ( USE_MATRIX_TEST )
02169 definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
02170 #endif
02171 return *this;
02172 }
02173
02174
02175
02176 template <class T>
02177 inline CMatrix4<T>& CMatrix4<T>::setM(const T* data)
02178 {
02179 memcpy(M,data, 16*sizeof(T));
02180
02181 #if defined ( USE_MATRIX_TEST )
02182 definitelyIdentityMatrix=false;
02183 #endif
02184 return *this;
02185 }
02186
02187
02188
02189 template <class T>
02190 inline void CMatrix4<T>::setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix)
02191 {
02192 #if defined ( USE_MATRIX_TEST )
02193 definitelyIdentityMatrix = isDefinitelyIdentityMatrix;
02194 #endif
02195 }
02196
02197
02198
02199 template <class T>
02200 inline bool CMatrix4<T>::getDefinitelyIdentityMatrix() const
02201 {
02202 #if defined ( USE_MATRIX_TEST )
02203 return definitelyIdentityMatrix;
02204 #else
02205 return false;
02206 #endif
02207 }
02208
02209
02211 template <class T>
02212 inline bool CMatrix4<T>::equals(const core::CMatrix4<T>& other, const T tolerance) const
02213 {
02214 #if defined ( USE_MATRIX_TEST )
02215 if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
02216 return true;
02217 #endif
02218 for (s32 i = 0; i < 16; ++i)
02219 if (!core::equals(M[i],other.M[i], tolerance))
02220 return false;
02221
02222 return true;
02223 }
02224
02225
02226
02227 template <class T>
02228 inline CMatrix4<T> operator*(const T scalar, const CMatrix4<T>& mat)
02229 {
02230 return mat*scalar;
02231 }
02232
02233
02235 typedef CMatrix4<f32> matrix4;
02236
02238 IRRLICHT_API extern const matrix4 IdentityMatrix;
02239
02240 }
02241 }
02242
02243 #endif
02244