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