Skylicht Engine
Loading...
Searching...
No Matches
matrix4.h
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4
5#ifndef __IRR_MATRIX_H_INCLUDED__
6#define __IRR_MATRIX_H_INCLUDED__
7
8#include "irrMath.h"
9#include "vector3d.h"
10#include "vector2d.h"
11#include "plane3d.h"
12#include "aabbox3d.h"
13#include "rect.h"
14#include "irrString.h"
15
16// enable this to keep track of changes to the matrix
17// and make simpler identity check for seldomly changing matrices
18// otherwise identity check will always compare the elements
19//#define USE_MATRIX_TEST
20
21// this is only for debugging purposes
22//#define USE_MATRIX_TEST_DEBUG
23
24#if defined( USE_MATRIX_TEST_DEBUG )
25
26struct MatrixTest
27{
28 MatrixTest () : ID(0), Calls(0) {}
29 char buf[256];
30 int Calls;
31 int ID;
32};
33static MatrixTest MTest;
34
35#endif
36
37namespace irr
38{
39namespace core
40{
41
43
44 template <class T>
46 {
47 public:
48
51 {
52 EM4CONST_NOTHING = 0,
53 EM4CONST_COPY,
54 EM4CONST_IDENTITY,
55 EM4CONST_TRANSPOSED,
56 EM4CONST_INVERSE,
57 EM4CONST_INVERSE_TRANSPOSED
58 };
59
61
62 CMatrix4( eConstructor constructor = EM4CONST_IDENTITY );
64
66 CMatrix4(const CMatrix4<T>& other, eConstructor constructor = EM4CONST_COPY);
67
69 T& operator()(const s32 row, const s32 col)
70 {
71#if defined ( USE_MATRIX_TEST )
72 definitelyIdentityMatrix=false;
73#endif
74 return M[ (row << 2) + col ];
75 }
76
78 const T& operator()(const s32 row, const s32 col) const { return M[ (row << 2) + col]; }
79
81 T& operator[](u32 index)
82 {
83#if defined ( USE_MATRIX_TEST )
84 definitelyIdentityMatrix=false;
85#endif
86 return M[index];
87 }
88
90 const T& operator[](u32 index) const { return M[index]; }
91
93 inline CMatrix4<T>& operator=(const CMatrix4<T> &other);
94
96 inline CMatrix4<T>& operator=(const T& scalar);
97
99 const T* pointer() const { return M; }
100 T* pointer()
101 {
102#if defined ( USE_MATRIX_TEST )
103 definitelyIdentityMatrix=false;
104#endif
105 return M;
106 }
107
109 bool operator==(const CMatrix4<T> &other) const;
110
112 bool operator!=(const CMatrix4<T> &other) const;
113
115 CMatrix4<T> operator+(const CMatrix4<T>& other) const;
116
119
121 CMatrix4<T> operator-(const CMatrix4<T>& other) const;
122
125
127
128 inline CMatrix4<T>& setbyproduct(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
129
131
133 CMatrix4<T>& setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
134
136
137 CMatrix4<T> operator*(const CMatrix4<T>& other) const;
138
140
142
144 CMatrix4<T> operator*(const T& scalar) const;
145
147 CMatrix4<T>& operator*=(const T& scalar);
148
151
153 inline bool isIdentity() const;
154
156 inline bool isOrthogonal() const;
157
160
162 CMatrix4<T>& setTranslation( const vector3d<T>& translation );
163
166
169
171 inline CMatrix4<T>& setRotationRadians( const vector3d<T>& rotation );
172
175
177
179
181
183
185
187
189
190 inline CMatrix4<T>& setRotationAxisRadians(const T& angle, const vector3d<T>& axis);
191
194
196 CMatrix4<T>& setScale( const T scale ) { return setScale(core::vector3d<T>(scale,scale,scale)); }
197
200
202 void inverseTranslateVect( vector3df& vect ) const;
203
205 void inverseRotateVect( vector3df& vect ) const;
206
208 void rotateVect( vector3df& vect ) const;
209
211 void rotateVect(core::vector3df& out, const core::vector3df& in) const;
212
214 void rotateVect(T *out,const core::vector3df &in) const;
215
217 void transformVect( vector3df& vect) const;
218
220 void transformVect( vector3df& out, const vector3df& in ) const;
221
223 void transformVect(T *out,const core::vector3df &in) const;
224
226 void transformVec3(T *out, const T * in) const;
227
229 void translateVect( vector3df& vect ) const;
230
233
236
238
241
243
246
248 void multiplyWith1x4Matrix(T* matrix) const;
249
251
253
254
256
257 bool getInversePrimitive ( CMatrix4<T>& out ) const;
258
260
262 bool getInverse(CMatrix4<T>& out) const;
263
265 CMatrix4<T>& buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
266
268 CMatrix4<T>& buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
269
271 CMatrix4<T>& buildProjectionMatrixPerspectiveFovInfinityLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon=0);
272
274 CMatrix4<T>& buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
275
277 CMatrix4<T>& buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
278
280 CMatrix4<T>& buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
281
283 CMatrix4<T>& buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
284
287 const vector3df& position,
288 const vector3df& target,
289 const vector3df& upVector);
290
293 const vector3df& position,
294 const vector3df& target,
295 const vector3df& upVector);
296
298
303
305
307
309
312
315
317 inline void getTransposed( CMatrix4<T>& dest ) const;
318
320
324
326
329 void setRotationCenter(const core::vector3df& center, const core::vector3df& translate);
330
332
339 const core::vector3df& center,
340 const core::vector3df& translation,
341 const core::vector3df& axis,
342 const core::vector3df& from);
343
344 /*
345 construct 2D Texture transformations
346 rotate about center, scale, and transform.
347 */
350 const core::vector2df &rotatecenter,
351 const core::vector2df &translate,
352 const core::vector2df &scale);
353
355
360
362
367
369
374
376
381
383
388
390 CMatrix4<T>& setM(const T* data);
391
393 void setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix);
394
397
399 bool equals(const core::CMatrix4<T>& other, const T tolerance=(T)ROUNDING_ERROR_f64) const;
400
401 private:
403 T M[16];
404#if defined ( USE_MATRIX_TEST )
406 mutable u32 definitelyIdentityMatrix;
407#endif
408#if defined ( USE_MATRIX_TEST_DEBUG )
409 u32 id;
410 mutable u32 calls;
411#endif
412
413 };
414
415 // Default constructor
416 template <class T>
418#if defined ( USE_MATRIX_TEST )
419 : definitelyIdentityMatrix(BIT_UNTESTED)
420#endif
421#if defined ( USE_MATRIX_TEST_DEBUG )
422 ,id ( MTest.ID++), calls ( 0 )
423#endif
424 {
425 switch ( constructor )
426 {
427 case EM4CONST_NOTHING:
428 case EM4CONST_COPY:
429 break;
430 case EM4CONST_IDENTITY:
431 case EM4CONST_INVERSE:
432 default:
433 makeIdentity();
434 break;
435 }
436 }
437
438 // Copy constructor
439 template <class T>
440 inline CMatrix4<T>::CMatrix4( const CMatrix4<T>& other, eConstructor constructor)
441#if defined ( USE_MATRIX_TEST )
442 : definitelyIdentityMatrix(BIT_UNTESTED)
443#endif
444#if defined ( USE_MATRIX_TEST_DEBUG )
445 ,id ( MTest.ID++), calls ( 0 )
446#endif
447 {
448 switch ( constructor )
449 {
450 case EM4CONST_IDENTITY:
451 makeIdentity();
452 break;
453 case EM4CONST_NOTHING:
454 break;
455 case EM4CONST_COPY:
456 *this = other;
457 break;
458 case EM4CONST_TRANSPOSED:
459 other.getTransposed(*this);
460 break;
461 case EM4CONST_INVERSE:
462 if (!other.getInverse(*this))
463 memset(M, 0, 16*sizeof(T));
464 break;
465 case EM4CONST_INVERSE_TRANSPOSED:
466 if (!other.getInverse(*this))
467 memset(M, 0, 16*sizeof(T));
468 else
469 *this=getTransposed();
470 break;
471 }
472 }
473
475 template <class T>
477 {
478 CMatrix4<T> temp ( EM4CONST_NOTHING );
479
480 temp[0] = M[0]+other[0];
481 temp[1] = M[1]+other[1];
482 temp[2] = M[2]+other[2];
483 temp[3] = M[3]+other[3];
484 temp[4] = M[4]+other[4];
485 temp[5] = M[5]+other[5];
486 temp[6] = M[6]+other[6];
487 temp[7] = M[7]+other[7];
488 temp[8] = M[8]+other[8];
489 temp[9] = M[9]+other[9];
490 temp[10] = M[10]+other[10];
491 temp[11] = M[11]+other[11];
492 temp[12] = M[12]+other[12];
493 temp[13] = M[13]+other[13];
494 temp[14] = M[14]+other[14];
495 temp[15] = M[15]+other[15];
496
497 return temp;
498 }
499
501 template <class T>
503 {
504 M[0]+=other[0];
505 M[1]+=other[1];
506 M[2]+=other[2];
507 M[3]+=other[3];
508 M[4]+=other[4];
509 M[5]+=other[5];
510 M[6]+=other[6];
511 M[7]+=other[7];
512 M[8]+=other[8];
513 M[9]+=other[9];
514 M[10]+=other[10];
515 M[11]+=other[11];
516 M[12]+=other[12];
517 M[13]+=other[13];
518 M[14]+=other[14];
519 M[15]+=other[15];
520
521 return *this;
522 }
523
525 template <class T>
527 {
528 CMatrix4<T> temp ( EM4CONST_NOTHING );
529
530 temp[0] = M[0]-other[0];
531 temp[1] = M[1]-other[1];
532 temp[2] = M[2]-other[2];
533 temp[3] = M[3]-other[3];
534 temp[4] = M[4]-other[4];
535 temp[5] = M[5]-other[5];
536 temp[6] = M[6]-other[6];
537 temp[7] = M[7]-other[7];
538 temp[8] = M[8]-other[8];
539 temp[9] = M[9]-other[9];
540 temp[10] = M[10]-other[10];
541 temp[11] = M[11]-other[11];
542 temp[12] = M[12]-other[12];
543 temp[13] = M[13]-other[13];
544 temp[14] = M[14]-other[14];
545 temp[15] = M[15]-other[15];
546
547 return temp;
548 }
549
551 template <class T>
553 {
554 M[0]-=other[0];
555 M[1]-=other[1];
556 M[2]-=other[2];
557 M[3]-=other[3];
558 M[4]-=other[4];
559 M[5]-=other[5];
560 M[6]-=other[6];
561 M[7]-=other[7];
562 M[8]-=other[8];
563 M[9]-=other[9];
564 M[10]-=other[10];
565 M[11]-=other[11];
566 M[12]-=other[12];
567 M[13]-=other[13];
568 M[14]-=other[14];
569 M[15]-=other[15];
570
571 return *this;
572 }
573
575 template <class T>
576 inline CMatrix4<T> CMatrix4<T>::operator*(const T& scalar) const
577 {
578 CMatrix4<T> temp ( EM4CONST_NOTHING );
579
580 temp[0] = M[0]*scalar;
581 temp[1] = M[1]*scalar;
582 temp[2] = M[2]*scalar;
583 temp[3] = M[3]*scalar;
584 temp[4] = M[4]*scalar;
585 temp[5] = M[5]*scalar;
586 temp[6] = M[6]*scalar;
587 temp[7] = M[7]*scalar;
588 temp[8] = M[8]*scalar;
589 temp[9] = M[9]*scalar;
590 temp[10] = M[10]*scalar;
591 temp[11] = M[11]*scalar;
592 temp[12] = M[12]*scalar;
593 temp[13] = M[13]*scalar;
594 temp[14] = M[14]*scalar;
595 temp[15] = M[15]*scalar;
596
597 return temp;
598 }
599
601 template <class T>
602 inline CMatrix4<T>& CMatrix4<T>::operator*=(const T& scalar)
603 {
604 M[0]*=scalar;
605 M[1]*=scalar;
606 M[2]*=scalar;
607 M[3]*=scalar;
608 M[4]*=scalar;
609 M[5]*=scalar;
610 M[6]*=scalar;
611 M[7]*=scalar;
612 M[8]*=scalar;
613 M[9]*=scalar;
614 M[10]*=scalar;
615 M[11]*=scalar;
616 M[12]*=scalar;
617 M[13]*=scalar;
618 M[14]*=scalar;
619 M[15]*=scalar;
620
621 return *this;
622 }
623
625 template <class T>
627 {
628#if defined ( USE_MATRIX_TEST )
629 // do checks on your own in order to avoid copy creation
630 if ( !other.isIdentity() )
631 {
632 if ( this->isIdentity() )
633 {
634 return (*this = other);
635 }
636 else
637 {
638 CMatrix4<T> temp ( *this );
639 return setbyproduct_nocheck( temp, other );
640 }
641 }
642 return *this;
643#else
644 CMatrix4<T> temp ( *this );
645 return setbyproduct_nocheck( temp, other );
646#endif
647 }
648
650 // set this matrix to the product of two other matrices
651 // goal is to reduce stack use and copy
652 template <class T>
654 {
655 const T *m1 = other_a.M;
656 const T *m2 = other_b.M;
657
658 M[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
659 M[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
660 M[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
661 M[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
662
663 M[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
664 M[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
665 M[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
666 M[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
667
668 M[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
669 M[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
670 M[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
671 M[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
672
673 M[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
674 M[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
675 M[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
676 M[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
677#if defined ( USE_MATRIX_TEST )
678 definitelyIdentityMatrix=false;
679#endif
680 return *this;
681 }
682
683
685 // set this matrix to the product of two other matrices
686 // goal is to reduce stack use and copy
687 template <class T>
688 inline CMatrix4<T>& CMatrix4<T>::setbyproduct(const CMatrix4<T>& other_a, const CMatrix4<T>& other_b )
689 {
690#if defined ( USE_MATRIX_TEST )
691 if ( other_a.isIdentity () )
692 return (*this = other_b);
693 else
694 if ( other_b.isIdentity () )
695 return (*this = other_a);
696 else
697 return setbyproduct_nocheck(other_a,other_b);
698#else
699 return setbyproduct_nocheck(other_a,other_b);
700#endif
701 }
702
704 template <class T>
705 inline CMatrix4<T> CMatrix4<T>::operator*(const CMatrix4<T>& matrix2) const
706 {
707#if defined ( USE_MATRIX_TEST )
708 // Testing purpose..
709 if ( this->isIdentity() )
710 return m2;
711 if ( m2.isIdentity() )
712 return *this;
713#endif
714
715 CMatrix4<T> ret ( EM4CONST_NOTHING );
716
717 const T *m1 = M;
718 const T *m2 = matrix2.M;
719 T *m3 = ret.M;
720
721 m3[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
722 m3[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
723 m3[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
724 m3[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
725
726 m3[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
727 m3[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
728 m3[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
729 m3[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
730
731 m3[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
732 m3[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
733 m3[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
734 m3[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
735
736 m3[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
737 m3[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
738 m3[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
739 m3[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
740
741 return ret;
742 }
743
744
745
746 template <class T>
748 {
749 return vector3d<T>(M[12], M[13], M[14]);
750 }
751
752
753 template <class T>
755 {
756 M[12] = translation.X;
757 M[13] = translation.Y;
758 M[14] = translation.Z;
759#if defined ( USE_MATRIX_TEST )
760 definitelyIdentityMatrix=false;
761#endif
762 return *this;
763 }
764
765 template <class T>
767 {
768 M[12] = -translation.X;
769 M[13] = -translation.Y;
770 M[14] = -translation.Z;
771#if defined ( USE_MATRIX_TEST )
772 definitelyIdentityMatrix=false;
773#endif
774 return *this;
775 }
776
777 template <class T>
779 {
780 M[0] = scale.X;
781 M[5] = scale.Y;
782 M[10] = scale.Z;
783#if defined ( USE_MATRIX_TEST )
784 definitelyIdentityMatrix=false;
785#endif
786 return *this;
787 }
788
790
797 template <class T>
799 {
800 // See http://www.robertblum.com/articles/2005/02/14/decomposing-matrices
801
802 // Deal with the 0 rotation case first
803 // Prior to Irrlicht 1.6, we always returned this value.
804 if(core::iszero(M[1]) && core::iszero(M[2]) &&
805 core::iszero(M[4]) && core::iszero(M[6]) &&
806 core::iszero(M[8]) && core::iszero(M[9]))
807 return vector3d<T>(M[0], M[5], M[10]);
808
809 // We have to do the full calculation.
810 return vector3d<T>(sqrtf(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]),
811 sqrtf(M[4] * M[4] + M[5] * M[5] + M[6] * M[6]),
812 sqrtf(M[8] * M[8] + M[9] * M[9] + M[10] * M[10]));
813 }
814
815 template <class T>
817 {
818 return setRotationRadians( rotation * core::DEGTORAD );
819 }
820
821 template <class T>
823 {
824 return setInverseRotationRadians( rotation * core::DEGTORAD );
825 }
826
827 template <class T>
829 {
830 const f64 cr = cos( rotation.X );
831 const f64 sr = sin( rotation.X );
832 const f64 cp = cos( rotation.Y );
833 const f64 sp = sin( rotation.Y );
834 const f64 cy = cos( rotation.Z );
835 const f64 sy = sin( rotation.Z );
836
837 M[0] = (T)( cp*cy );
838 M[1] = (T)( cp*sy );
839 M[2] = (T)( -sp );
840
841 const f64 srsp = sr*sp;
842 const f64 crsp = cr*sp;
843
844 M[4] = (T)( srsp*cy-cr*sy );
845 M[5] = (T)( srsp*sy+cr*cy );
846 M[6] = (T)( sr*cp );
847
848 M[8] = (T)( crsp*cy+sr*sy );
849 M[9] = (T)( crsp*sy-sr*cy );
850 M[10] = (T)( cr*cp );
851#if defined ( USE_MATRIX_TEST )
852 definitelyIdentityMatrix=false;
853#endif
854 return *this;
855 }
856
857
859
862 template <class T>
864 {
865 const CMatrix4<T> &mat = *this;
866 core::vector3d<T> scale = getScale();
867 // we need to check for negative scale on to axes, which would bring up wrong results
868 if (scale.Y<0 && scale.Z<0)
869 {
870 scale.Y =-scale.Y;
871 scale.Z =-scale.Z;
872 }
873 else if (scale.X<0 && scale.Z<0)
874 {
875 scale.X =-scale.X;
876 scale.Z =-scale.Z;
877 }
878 else if (scale.X<0 && scale.Y<0)
879 {
880 scale.X =-scale.X;
881 scale.Y =-scale.Y;
882 }
883 const core::vector3d<f64> invScale(core::reciprocal(scale.X),core::reciprocal(scale.Y),core::reciprocal(scale.Z));
884
885 f64 Y = -asin(core::clamp(mat[2]*invScale.X, -1.0, 1.0));
886 const f64 C = cos(Y);
887 Y *= RADTODEG64;
888
889 f64 rotx, roty, X, Z;
890
891 if (!core::iszero(C))
892 {
893 const f64 invC = core::reciprocal(C);
894 rotx = mat[10] * invC * invScale.Z;
895 roty = mat[6] * invC * invScale.Y;
896 X = atan2( roty, rotx ) * RADTODEG64;
897 rotx = mat[0] * invC * invScale.X;
898 roty = mat[1] * invC * invScale.X;
899 Z = atan2( roty, rotx ) * RADTODEG64;
900 }
901 else
902 {
903 X = 0.0;
904 rotx = mat[5] * invScale.Y;
905 roty = -mat[4] * invScale.Y;
906 Z = atan2( roty, rotx ) * RADTODEG64;
907 }
908
909 // fix values that get below zero
910 if (X < 0.0) X += 360.0;
911 if (Y < 0.0) Y += 360.0;
912 if (Z < 0.0) Z += 360.0;
913
914 return vector3d<T>((T)X,(T)Y,(T)Z);
915 }
916
917
919 template <class T>
921 {
922 f64 cr = cos( rotation.X );
923 f64 sr = sin( rotation.X );
924 f64 cp = cos( rotation.Y );
925 f64 sp = sin( rotation.Y );
926 f64 cy = cos( rotation.Z );
927 f64 sy = sin( rotation.Z );
928
929 M[0] = (T)( cp*cy );
930 M[4] = (T)( cp*sy );
931 M[8] = (T)( -sp );
932
933 f64 srsp = sr*sp;
934 f64 crsp = cr*sp;
935
936 M[1] = (T)( srsp*cy-cr*sy );
937 M[5] = (T)( srsp*sy+cr*cy );
938 M[9] = (T)( sr*cp );
939
940 M[2] = (T)( crsp*cy+sr*sy );
941 M[6] = (T)( crsp*sy-sr*cy );
942 M[10] = (T)( cr*cp );
943#if defined ( USE_MATRIX_TEST )
944 definitelyIdentityMatrix=false;
945#endif
946 return *this;
947 }
948
950 template <class T>
951 inline CMatrix4<T>& CMatrix4<T>::setRotationAxisRadians( const T& angle, const vector3d<T>& axis )
952 {
953 const f64 c = cos(angle);
954 const f64 s = sin(angle);
955 const f64 t = 1.0 - c;
956
957 const f64 tx = t * axis.X;
958 const f64 ty = t * axis.Y;
959 const f64 tz = t * axis.Z;
960
961 const f64 sx = s * axis.X;
962 const f64 sy = s * axis.Y;
963 const f64 sz = s * axis.Z;
964
965 M[0] = (T)(tx * axis.X + c);
966 M[1] = (T)(tx * axis.Y + sz);
967 M[2] = (T)(tx * axis.Z - sy);
968
969 M[4] = (T)(ty * axis.X - sz);
970 M[5] = (T)(ty * axis.Y + c);
971 M[6] = (T)(ty * axis.Z + sx);
972
973 M[8] = (T)(tz * axis.X + sy);
974 M[9] = (T)(tz * axis.Y - sx);
975 M[10] = (T)(tz * axis.Z + c);
976
977#if defined ( USE_MATRIX_TEST )
978 definitelyIdentityMatrix=false;
979#endif
980 return *this;
981 }
982
983
986 template <class T>
988 {
989 memset(M, 0, 16*sizeof(T));
990 M[0] = M[5] = M[10] = M[15] = (T)1;
991#if defined ( USE_MATRIX_TEST )
992 definitelyIdentityMatrix=true;
993#endif
994 return *this;
995 }
996
997
998 /*
999 check identity with epsilon
1000 solve floating range problems..
1001 */
1002 template <class T>
1003 inline bool CMatrix4<T>::isIdentity() const
1004 {
1005#if defined ( USE_MATRIX_TEST )
1006 if (definitelyIdentityMatrix)
1007 return true;
1008#endif
1009 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 ))
1010 return false;
1011
1012 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 ))
1013 return false;
1014
1015 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 ))
1016 return false;
1017
1018 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 ))
1019 return false;
1020/*
1021 if (!core::equals( M[ 0], (T)1 ) ||
1022 !core::equals( M[ 5], (T)1 ) ||
1023 !core::equals( M[10], (T)1 ) ||
1024 !core::equals( M[15], (T)1 ))
1025 return false;
1026
1027 for (s32 i=0; i<4; ++i)
1028 for (s32 j=0; j<4; ++j)
1029 if ((j != i) && (!iszero((*this)(i,j))))
1030 return false;
1031*/
1032#if defined ( USE_MATRIX_TEST )
1033 definitelyIdentityMatrix=true;
1034#endif
1035 return true;
1036 }
1037
1038
1039 /* Check orthogonality of matrix. */
1040 template <class T>
1041 inline bool CMatrix4<T>::isOrthogonal() const
1042 {
1043 T dp=M[0] * M[4 ] + M[1] * M[5 ] + M[2 ] * M[6 ] + M[3 ] * M[7 ];
1044 if (!iszero(dp))
1045 return false;
1046 dp = M[0] * M[8 ] + M[1] * M[9 ] + M[2 ] * M[10] + M[3 ] * M[11];
1047 if (!iszero(dp))
1048 return false;
1049 dp = M[0] * M[12] + M[1] * M[13] + M[2 ] * M[14] + M[3 ] * M[15];
1050 if (!iszero(dp))
1051 return false;
1052 dp = M[4] * M[8 ] + M[5] * M[9 ] + M[6 ] * M[10] + M[7 ] * M[11];
1053 if (!iszero(dp))
1054 return false;
1055 dp = M[4] * M[12] + M[5] * M[13] + M[6 ] * M[14] + M[7 ] * M[15];
1056 if (!iszero(dp))
1057 return false;
1058 dp = M[8] * M[12] + M[9] * M[13] + M[10] * M[14] + M[11] * M[15];
1059 return (iszero(dp));
1060 }
1061
1062
1063 /*
1064 doesn't solve floating range problems..
1065 but takes care on +/- 0 on translation because we are changing it..
1066 reducing floating point branches
1067 but it needs the floats in memory..
1068 */
1069 template <class T>
1071 {
1072#if defined ( USE_MATRIX_TEST )
1073 if (definitelyIdentityMatrix)
1074 return true;
1075#endif
1076 if(IR(M[0])!=F32_VALUE_1) return false;
1077 if(IR(M[1])!=0) return false;
1078 if(IR(M[2])!=0) return false;
1079 if(IR(M[3])!=0) return false;
1080
1081 if(IR(M[4])!=0) return false;
1082 if(IR(M[5])!=F32_VALUE_1) return false;
1083 if(IR(M[6])!=0) return false;
1084 if(IR(M[7])!=0) return false;
1085
1086 if(IR(M[8])!=0) return false;
1087 if(IR(M[9])!=0) return false;
1088 if(IR(M[10])!=F32_VALUE_1) return false;
1089 if(IR(M[11])!=0) return false;
1090
1091 if(IR(M[12])!=0) return false;
1092 if(IR(M[13])!=0) return false;
1093 if(IR(M[13])!=0) return false;
1094 if(IR(M[15])!=F32_VALUE_1) return false;
1095
1096#if defined ( USE_MATRIX_TEST )
1097 definitelyIdentityMatrix=true;
1098#endif
1099 return true;
1100 }
1101
1102
1103 template <class T>
1104 inline void CMatrix4<T>::rotateVect( vector3df& vect ) const
1105 {
1106 vector3df tmp = vect;
1107 vect.X = tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8];
1108 vect.Y = tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9];
1109 vect.Z = tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10];
1110 }
1111
1113 template <class T>
1115 {
1116 out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
1117 out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
1118 out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
1119 }
1120
1122 template <class T>
1123 inline void CMatrix4<T>::rotateVect(T *out, const core::vector3df& in) const
1124 {
1125 out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
1126 out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
1127 out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
1128 }
1129
1130 template <class T>
1132 {
1133 vector3df tmp = vect;
1134 vect.X = tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2];
1135 vect.Y = tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6];
1136 vect.Z = tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10];
1137 }
1138
1139 template <class T>
1140 inline void CMatrix4<T>::transformVect( vector3df& vect) const
1141 {
1142 f32 vector[3];
1143
1144 vector[0] = vect.X*M[0] + vect.Y*M[4] + vect.Z*M[8] + M[12];
1145 vector[1] = vect.X*M[1] + vect.Y*M[5] + vect.Z*M[9] + M[13];
1146 vector[2] = vect.X*M[2] + vect.Y*M[6] + vect.Z*M[10] + M[14];
1147
1148 vect.X = vector[0];
1149 vect.Y = vector[1];
1150 vect.Z = vector[2];
1151 }
1152
1153 template <class T>
1154 inline void CMatrix4<T>::transformVect( vector3df& out, const vector3df& in) const
1155 {
1156 out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
1157 out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
1158 out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
1159 }
1160
1161
1162 template <class T>
1163 inline void CMatrix4<T>::transformVect(T *out, const core::vector3df &in) const
1164 {
1165 out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
1166 out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
1167 out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
1168 out[3] = in.X*M[3] + in.Y*M[7] + in.Z*M[11] + M[15];
1169 }
1170
1171 template <class T>
1172 inline void CMatrix4<T>::transformVec3(T *out, const T * in) const
1173 {
1174 out[0] = in[0]*M[0] + in[1]*M[4] + in[2]*M[8] + M[12];
1175 out[1] = in[0]*M[1] + in[1]*M[5] + in[2]*M[9] + M[13];
1176 out[2] = in[0]*M[2] + in[1]*M[6] + in[2]*M[10] + M[14];
1177 }
1178
1179
1181 template <class T>
1183 {
1184 vector3df member;
1185 // Transform the plane member point, i.e. rotate, translate and scale it.
1186 transformVect(member, plane.getMemberPoint());
1187
1188 // Transform the normal by the transposed inverse of the matrix
1189 CMatrix4<T> transposedInverse(*this, EM4CONST_INVERSE_TRANSPOSED);
1190 vector3df normal = plane.Normal;
1191 transposedInverse.transformVect(normal);
1192
1193 plane.setPlane(member, normal);
1194 }
1195
1197 template <class T>
1199 {
1200 out = in;
1201 transformPlane( out );
1202 }
1203
1205 template <class T>
1207 {
1208#if defined ( USE_MATRIX_TEST )
1209 if (isIdentity())
1210 return;
1211#endif
1212
1215 box.repair();
1216 }
1217
1219 template <class T>
1221 {
1222#if defined ( USE_MATRIX_TEST )
1223 if (isIdentity())
1224 return;
1225#endif
1226
1227 const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z};
1228 const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z};
1229
1230 f32 Bmin[3];
1231 f32 Bmax[3];
1232
1233 Bmin[0] = Bmax[0] = M[12];
1234 Bmin[1] = Bmax[1] = M[13];
1235 Bmin[2] = Bmax[2] = M[14];
1236
1237 for (u32 i = 0; i < 3; ++i)
1238 {
1239 for (u32 j = 0; j < 3; ++j)
1240 {
1241 float t = M[(j << 2) + i];
1242
1243 const f32 a = t * Amin[j];
1244 const f32 b = t * Amax[j];
1245
1246 if (a < b)
1247 {
1248 Bmin[i] += a;
1249 Bmax[i] += b;
1250 }
1251 else
1252 {
1253 Bmin[i] += b;
1254 Bmax[i] += a;
1255 }
1256 }
1257 }
1258
1259 box.MinEdge.X = Bmin[0];
1260 box.MinEdge.Y = Bmin[1];
1261 box.MinEdge.Z = Bmin[2];
1262
1263 box.MaxEdge.X = Bmax[0];
1264 box.MaxEdge.Y = Bmax[1];
1265 box.MaxEdge.Z = Bmax[2];
1266 }
1267
1268
1270 template <class T>
1271 inline void CMatrix4<T>::multiplyWith1x4Matrix(T* matrix) const
1272 {
1273 /*
1274 0 1 2 3
1275 4 5 6 7
1276 8 9 10 11
1277 12 13 14 15
1278 */
1279
1280 T mat[4];
1281 mat[0] = matrix[0];
1282 mat[1] = matrix[1];
1283 mat[2] = matrix[2];
1284 mat[3] = matrix[3];
1285
1286 matrix[0] = M[0]*mat[0] + M[4]*mat[1] + M[8]*mat[2] + M[12]*mat[3];
1287 matrix[1] = M[1]*mat[0] + M[5]*mat[1] + M[9]*mat[2] + M[13]*mat[3];
1288 matrix[2] = M[2]*mat[0] + M[6]*mat[1] + M[10]*mat[2] + M[14]*mat[3];
1289 matrix[3] = M[3]*mat[0] + M[7]*mat[1] + M[11]*mat[2] + M[15]*mat[3];
1290 }
1291
1292 template <class T>
1294 {
1295 vect.X = vect.X-M[12];
1296 vect.Y = vect.Y-M[13];
1297 vect.Z = vect.Z-M[14];
1298 }
1299
1300 template <class T>
1301 inline void CMatrix4<T>::translateVect( vector3df& vect ) const
1302 {
1303 vect.X = vect.X+M[12];
1304 vect.Y = vect.Y+M[13];
1305 vect.Z = vect.Z+M[14];
1306 }
1307
1308
1309 template <class T>
1310 inline bool CMatrix4<T>::getInverse(CMatrix4<T>& out) const
1311 {
1315
1316#if defined ( USE_MATRIX_TEST )
1317 if ( this->isIdentity() )
1318 {
1319 out=*this;
1320 return true;
1321 }
1322#endif
1323 //const CMatrix4<T> &m = *this;
1324 #define m(x,y) M[(x << 2) + y]
1325 #define out(x,y) out.M[(x << 2) + y]
1326
1327 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)) -
1328 (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
1329 (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)) +
1330 (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) -
1331 (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
1332 (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0));
1333
1334 if( core::iszero ( d, FLT_MIN ) )
1335 return false;
1336
1337 d = core::reciprocal ( d );
1338
1339 out(0, 0) = d * (m(1, 1) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) +
1340 m(1, 2) * (m(2, 3) * m(3, 1) - m(2, 1) * m(3, 3)) +
1341 m(1, 3) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)));
1342 out(0, 1) = d * (m(2, 1) * (m(0, 2) * m(3, 3) - m(0, 3) * m(3, 2)) +
1343 m(2, 2) * (m(0, 3) * m(3, 1) - m(0, 1) * m(3, 3)) +
1344 m(2, 3) * (m(0, 1) * m(3, 2) - m(0, 2) * m(3, 1)));
1345 out(0, 2) = d * (m(3, 1) * (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) +
1346 m(3, 2) * (m(0, 3) * m(1, 1) - m(0, 1) * m(1, 3)) +
1347 m(3, 3) * (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)));
1348 out(0, 3) = d * (m(0, 1) * (m(1, 3) * m(2, 2) - m(1, 2) * m(2, 3)) +
1349 m(0, 2) * (m(1, 1) * m(2, 3) - m(1, 3) * m(2, 1)) +
1350 m(0, 3) * (m(1, 2) * m(2, 1) - m(1, 1) * m(2, 2)));
1351 out(1, 0) = d * (m(1, 2) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) +
1352 m(1, 3) * (m(2, 2) * m(3, 0) - m(2, 0) * m(3, 2)) +
1353 m(1, 0) * (m(2, 3) * m(3, 2) - m(2, 2) * m(3, 3)));
1354 out(1, 1) = d * (m(2, 2) * (m(0, 0) * m(3, 3) - m(0, 3) * m(3, 0)) +
1355 m(2, 3) * (m(0, 2) * m(3, 0) - m(0, 0) * m(3, 2)) +
1356 m(2, 0) * (m(0, 3) * m(3, 2) - m(0, 2) * m(3, 3)));
1357 out(1, 2) = d * (m(3, 2) * (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) +
1358 m(3, 3) * (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2)) +
1359 m(3, 0) * (m(0, 3) * m(1, 2) - m(0, 2) * m(1, 3)));
1360 out(1, 3) = d * (m(0, 2) * (m(1, 3) * m(2, 0) - m(1, 0) * m(2, 3)) +
1361 m(0, 3) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
1362 m(0, 0) * (m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2)));
1363 out(2, 0) = d * (m(1, 3) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)) +
1364 m(1, 0) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
1365 m(1, 1) * (m(2, 3) * m(3, 0) - m(2, 0) * m(3, 3)));
1366 out(2, 1) = d * (m(2, 3) * (m(0, 0) * m(3, 1) - m(0, 1) * m(3, 0)) +
1367 m(2, 0) * (m(0, 1) * m(3, 3) - m(0, 3) * m(3, 1)) +
1368 m(2, 1) * (m(0, 3) * m(3, 0) - m(0, 0) * m(3, 3)));
1369 out(2, 2) = d * (m(3, 3) * (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) +
1370 m(3, 0) * (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) +
1371 m(3, 1) * (m(0, 3) * m(1, 0) - m(0, 0) * m(1, 3)));
1372 out(2, 3) = d * (m(0, 3) * (m(1, 1) * m(2, 0) - m(1, 0) * m(2, 1)) +
1373 m(0, 0) * (m(1, 3) * m(2, 1) - m(1, 1) * m(2, 3)) +
1374 m(0, 1) * (m(1, 0) * m(2, 3) - m(1, 3) * m(2, 0)));
1375 out(3, 0) = d * (m(1, 0) * (m(2, 2) * m(3, 1) - m(2, 1) * m(3, 2)) +
1376 m(1, 1) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
1377 m(1, 2) * (m(2, 1) * m(3, 0) - m(2, 0) * m(3, 1)));
1378 out(3, 1) = d * (m(2, 0) * (m(0, 2) * m(3, 1) - m(0, 1) * m(3, 2)) +
1379 m(2, 1) * (m(0, 0) * m(3, 2) - m(0, 2) * m(3, 0)) +
1380 m(2, 2) * (m(0, 1) * m(3, 0) - m(0, 0) * m(3, 1)));
1381 out(3, 2) = d * (m(3, 0) * (m(0, 2) * m(1, 1) - m(0, 1) * m(1, 2)) +
1382 m(3, 1) * (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) +
1383 m(3, 2) * (m(0, 1) * m(1, 0) - m(0, 0) * m(1, 1)));
1384 out(3, 3) = d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) +
1385 m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) +
1386 m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0)));
1387
1388 #undef m
1389 #undef out
1390
1391#if defined ( USE_MATRIX_TEST )
1392 out.definitelyIdentityMatrix = definitelyIdentityMatrix;
1393#endif
1394 return true;
1395 }
1396
1397
1400 template <class T>
1402 {
1403 out.M[0 ] = M[0];
1404 out.M[1 ] = M[4];
1405 out.M[2 ] = M[8];
1406 out.M[3 ] = 0;
1407
1408 out.M[4 ] = M[1];
1409 out.M[5 ] = M[5];
1410 out.M[6 ] = M[9];
1411 out.M[7 ] = 0;
1412
1413 out.M[8 ] = M[2];
1414 out.M[9 ] = M[6];
1415 out.M[10] = M[10];
1416 out.M[11] = 0;
1417
1418 out.M[12] = (T)-(M[12]*M[0] + M[13]*M[1] + M[14]*M[2]);
1419 out.M[13] = (T)-(M[12]*M[4] + M[13]*M[5] + M[14]*M[6]);
1420 out.M[14] = (T)-(M[12]*M[8] + M[13]*M[9] + M[14]*M[10]);
1421 out.M[15] = 1;
1422
1423#if defined ( USE_MATRIX_TEST )
1424 out.definitelyIdentityMatrix = definitelyIdentityMatrix;
1425#endif
1426 return true;
1427 }
1428
1431 template <class T>
1433 {
1434#if defined ( USE_MATRIX_TEST )
1435 if (definitelyIdentityMatrix)
1436 return true;
1437#endif
1438 CMatrix4<T> temp ( EM4CONST_NOTHING );
1439
1440 if (getInverse(temp))
1441 {
1442 *this = temp;
1443 return true;
1444 }
1445
1446 return false;
1447 }
1448
1449
1450 template <class T>
1452 {
1453 if (this==&other)
1454 return *this;
1455 memcpy(M, other.M, 16*sizeof(T));
1456#if defined ( USE_MATRIX_TEST )
1457 definitelyIdentityMatrix=other.definitelyIdentityMatrix;
1458#endif
1459 return *this;
1460 }
1461
1462
1463 template <class T>
1464 inline CMatrix4<T>& CMatrix4<T>::operator=(const T& scalar)
1465 {
1466 for (s32 i = 0; i < 16; ++i)
1467 M[i]=scalar;
1468
1469#if defined ( USE_MATRIX_TEST )
1470 definitelyIdentityMatrix=false;
1471#endif
1472 return *this;
1473 }
1474
1475
1476 template <class T>
1477 inline bool CMatrix4<T>::operator==(const CMatrix4<T> &other) const
1478 {
1479#if defined ( USE_MATRIX_TEST )
1480 if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
1481 return true;
1482#endif
1483 for (s32 i = 0; i < 16; ++i)
1484 if (M[i] != other.M[i])
1485 return false;
1486
1487 return true;
1488 }
1489
1490
1491 template <class T>
1492 inline bool CMatrix4<T>::operator!=(const CMatrix4<T> &other) const
1493 {
1494 return !(*this == other);
1495 }
1496
1497
1498 // Builds a right-handed perspective projection matrix based on a field of view
1499 template <class T>
1501 f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
1502 {
1503 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
1504 _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
1505 const T w = static_cast<T>(h / aspectRatio);
1506
1507 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1508 M[0] = w;
1509 M[1] = 0;
1510 M[2] = 0;
1511 M[3] = 0;
1512
1513 M[4] = 0;
1514 M[5] = (T)h;
1515 M[6] = 0;
1516 M[7] = 0;
1517
1518 M[8] = 0;
1519 M[9] = 0;
1520 M[10] = (T)(zFar/(zNear-zFar)); // DirectX version
1521// M[10] = (T)(zFar+zNear/(zNear-zFar)); // OpenGL version
1522 M[11] = -1;
1523
1524 M[12] = 0;
1525 M[13] = 0;
1526 M[14] = (T)(zNear*zFar/(zNear-zFar)); // DirectX version
1527// M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar)); // OpenGL version
1528 M[15] = 0;
1529
1530#if defined ( USE_MATRIX_TEST )
1531 definitelyIdentityMatrix=false;
1532#endif
1533 return *this;
1534 }
1535
1536
1537 // Builds a left-handed perspective projection matrix based on a field of view
1538 template <class T>
1540 f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
1541 {
1542 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
1543 _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
1544 const T w = static_cast<T>(h / aspectRatio);
1545
1546 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1547 M[0] = w;
1548 M[1] = 0;
1549 M[2] = 0;
1550 M[3] = 0;
1551
1552 M[4] = 0;
1553 M[5] = (T)h;
1554 M[6] = 0;
1555 M[7] = 0;
1556
1557 M[8] = 0;
1558 M[9] = 0;
1559 M[10] = (T)(zFar/(zFar-zNear));
1560 M[11] = 1;
1561
1562 M[12] = 0;
1563 M[13] = 0;
1564 M[14] = (T)(-zNear*zFar/(zFar-zNear));
1565 M[15] = 0;
1566
1567#if defined ( USE_MATRIX_TEST )
1568 definitelyIdentityMatrix=false;
1569#endif
1570 return *this;
1571 }
1572
1573
1574 // Builds a left-handed perspective projection matrix based on a field of view, with far plane culling at infinity
1575 template <class T>
1577 f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon)
1578 {
1579 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
1580 _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
1581 const T w = static_cast<T>(h / aspectRatio);
1582
1583 M[0] = w;
1584 M[1] = 0;
1585 M[2] = 0;
1586 M[3] = 0;
1587
1588 M[4] = 0;
1589 M[5] = (T)h;
1590 M[6] = 0;
1591 M[7] = 0;
1592
1593 M[8] = 0;
1594 M[9] = 0;
1595 M[10] = (T)(1.f-epsilon);
1596 M[11] = 1;
1597
1598 M[12] = 0;
1599 M[13] = 0;
1600 M[14] = (T)(zNear*(epsilon-1.f));
1601 M[15] = 0;
1602
1603#if defined ( USE_MATRIX_TEST )
1604 definitelyIdentityMatrix=false;
1605#endif
1606 return *this;
1607 }
1608
1609
1610 // Builds a left-handed orthogonal projection matrix.
1611 template <class T>
1613 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
1614 {
1615 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1616 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1617 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1618 M[0] = (T)(2/widthOfViewVolume);
1619 M[1] = 0;
1620 M[2] = 0;
1621 M[3] = 0;
1622
1623 M[4] = 0;
1624 M[5] = (T)(2/heightOfViewVolume);
1625 M[6] = 0;
1626 M[7] = 0;
1627
1628 M[8] = 0;
1629 M[9] = 0;
1630 M[10] = (T)(1/(zFar-zNear));
1631 M[11] = 0;
1632
1633 M[12] = 0;
1634 M[13] = 0;
1635 M[14] = (T)(zNear/(zNear-zFar));
1636 M[15] = 1;
1637
1638#if defined ( USE_MATRIX_TEST )
1639 definitelyIdentityMatrix=false;
1640#endif
1641 return *this;
1642 }
1643
1644
1645 // Builds a right-handed orthogonal projection matrix.
1646 template <class T>
1648 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
1649 {
1650 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1651 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1652 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1653 M[0] = (T)(2/widthOfViewVolume);
1654 M[1] = 0;
1655 M[2] = 0;
1656 M[3] = 0;
1657
1658 M[4] = 0;
1659 M[5] = (T)(2/heightOfViewVolume);
1660 M[6] = 0;
1661 M[7] = 0;
1662
1663 M[8] = 0;
1664 M[9] = 0;
1665 M[10] = (T)(1/(zNear-zFar));
1666 M[11] = 0;
1667
1668 M[12] = 0;
1669 M[13] = 0;
1670 M[14] = (T)(zNear/(zNear-zFar));
1671 M[15] = 1;
1672
1673#if defined ( USE_MATRIX_TEST )
1674 definitelyIdentityMatrix=false;
1675#endif
1676 return *this;
1677 }
1678
1679
1680 // Builds a right-handed perspective projection matrix.
1681 template <class T>
1683 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
1684 {
1685 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1686 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1687 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1688 M[0] = (T)(2*zNear/widthOfViewVolume);
1689 M[1] = 0;
1690 M[2] = 0;
1691 M[3] = 0;
1692
1693 M[4] = 0;
1694 M[5] = (T)(2*zNear/heightOfViewVolume);
1695 M[6] = 0;
1696 M[7] = 0;
1697
1698 M[8] = 0;
1699 M[9] = 0;
1700 M[10] = (T)(zFar/(zNear-zFar));
1701 M[11] = -1;
1702
1703 M[12] = 0;
1704 M[13] = 0;
1705 M[14] = (T)(zNear*zFar/(zNear-zFar));
1706 M[15] = 0;
1707
1708#if defined ( USE_MATRIX_TEST )
1709 definitelyIdentityMatrix=false;
1710#endif
1711 return *this;
1712 }
1713
1714
1715 // Builds a left-handed perspective projection matrix.
1716 template <class T>
1718 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
1719 {
1720 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1721 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1722 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1723 M[0] = (T)(2*zNear/widthOfViewVolume);
1724 M[1] = 0;
1725 M[2] = 0;
1726 M[3] = 0;
1727
1728 M[4] = 0;
1729 M[5] = (T)(2*zNear/heightOfViewVolume);
1730 M[6] = 0;
1731 M[7] = 0;
1732
1733 M[8] = 0;
1734 M[9] = 0;
1735 M[10] = (T)(zFar/(zFar-zNear));
1736 M[11] = 1;
1737
1738 M[12] = 0;
1739 M[13] = 0;
1740 M[14] = (T)(zNear*zFar/(zNear-zFar));
1741 M[15] = 0;
1742#if defined ( USE_MATRIX_TEST )
1743 definitelyIdentityMatrix=false;
1744#endif
1745 return *this;
1746 }
1747
1748
1749 // Builds a matrix that flattens geometry into a plane.
1750 template <class T>
1752 {
1753 plane.Normal.normalize();
1754 const f32 d = plane.Normal.dotProduct(light);
1755
1756 M[ 0] = (T)(-plane.Normal.X * light.X + d);
1757 M[ 1] = (T)(-plane.Normal.X * light.Y);
1758 M[ 2] = (T)(-plane.Normal.X * light.Z);
1759 M[ 3] = (T)(-plane.Normal.X * point);
1760
1761 M[ 4] = (T)(-plane.Normal.Y * light.X);
1762 M[ 5] = (T)(-plane.Normal.Y * light.Y + d);
1763 M[ 6] = (T)(-plane.Normal.Y * light.Z);
1764 M[ 7] = (T)(-plane.Normal.Y * point);
1765
1766 M[ 8] = (T)(-plane.Normal.Z * light.X);
1767 M[ 9] = (T)(-plane.Normal.Z * light.Y);
1768 M[10] = (T)(-plane.Normal.Z * light.Z + d);
1769 M[11] = (T)(-plane.Normal.Z * point);
1770
1771 M[12] = (T)(-plane.D * light.X);
1772 M[13] = (T)(-plane.D * light.Y);
1773 M[14] = (T)(-plane.D * light.Z);
1774 M[15] = (T)(-plane.D * point + d);
1775#if defined ( USE_MATRIX_TEST )
1776 definitelyIdentityMatrix=false;
1777#endif
1778 return *this;
1779 }
1780
1781 // Builds a left-handed look-at matrix.
1782 template <class T>
1784 const vector3df& position,
1785 const vector3df& target,
1786 const vector3df& upVector)
1787 {
1788 vector3df zaxis = target - position;
1789 zaxis.normalize();
1790
1791 vector3df xaxis = upVector.crossProduct(zaxis);
1792 xaxis.normalize();
1793
1794 vector3df yaxis = zaxis.crossProduct(xaxis);
1795
1796 M[0] = (T)xaxis.X;
1797 M[1] = (T)yaxis.X;
1798 M[2] = (T)zaxis.X;
1799 M[3] = 0;
1800
1801 M[4] = (T)xaxis.Y;
1802 M[5] = (T)yaxis.Y;
1803 M[6] = (T)zaxis.Y;
1804 M[7] = 0;
1805
1806 M[8] = (T)xaxis.Z;
1807 M[9] = (T)yaxis.Z;
1808 M[10] = (T)zaxis.Z;
1809 M[11] = 0;
1810
1811 M[12] = (T)-xaxis.dotProduct(position);
1812 M[13] = (T)-yaxis.dotProduct(position);
1813 M[14] = (T)-zaxis.dotProduct(position);
1814 M[15] = 1;
1815#if defined ( USE_MATRIX_TEST )
1816 definitelyIdentityMatrix=false;
1817#endif
1818 return *this;
1819 }
1820
1821
1822 // Builds a right-handed look-at matrix.
1823 template <class T>
1825 const vector3df& position,
1826 const vector3df& target,
1827 const vector3df& upVector)
1828 {
1829 vector3df zaxis = position - target;
1830 zaxis.normalize();
1831
1832 vector3df xaxis = upVector.crossProduct(zaxis);
1833 xaxis.normalize();
1834
1835 vector3df yaxis = zaxis.crossProduct(xaxis);
1836
1837 M[0] = (T)xaxis.X;
1838 M[1] = (T)yaxis.X;
1839 M[2] = (T)zaxis.X;
1840 M[3] = 0;
1841
1842 M[4] = (T)xaxis.Y;
1843 M[5] = (T)yaxis.Y;
1844 M[6] = (T)zaxis.Y;
1845 M[7] = 0;
1846
1847 M[8] = (T)xaxis.Z;
1848 M[9] = (T)yaxis.Z;
1849 M[10] = (T)zaxis.Z;
1850 M[11] = 0;
1851
1852 M[12] = (T)-xaxis.dotProduct(position);
1853 M[13] = (T)-yaxis.dotProduct(position);
1854 M[14] = (T)-zaxis.dotProduct(position);
1855 M[15] = 1;
1856#if defined ( USE_MATRIX_TEST )
1857 definitelyIdentityMatrix=false;
1858#endif
1859 return *this;
1860 }
1861
1862
1863 // creates a new matrix as interpolated matrix from this and the passed one.
1864 template <class T>
1866 {
1867 CMatrix4<T> mat ( EM4CONST_NOTHING );
1868
1869 for (u32 i=0; i < 16; i += 4)
1870 {
1871 mat.M[i+0] = (T)(M[i+0] + ( b.M[i+0] - M[i+0] ) * time);
1872 mat.M[i+1] = (T)(M[i+1] + ( b.M[i+1] - M[i+1] ) * time);
1873 mat.M[i+2] = (T)(M[i+2] + ( b.M[i+2] - M[i+2] ) * time);
1874 mat.M[i+3] = (T)(M[i+3] + ( b.M[i+3] - M[i+3] ) * time);
1875 }
1876 return mat;
1877 }
1878
1879
1880 // returns transposed matrix
1881 template <class T>
1883 {
1884 CMatrix4<T> t ( EM4CONST_NOTHING );
1885 getTransposed ( t );
1886 return t;
1887 }
1888
1889
1890 // returns transposed matrix
1891 template <class T>
1893 {
1894 o[ 0] = M[ 0];
1895 o[ 1] = M[ 4];
1896 o[ 2] = M[ 8];
1897 o[ 3] = M[12];
1898
1899 o[ 4] = M[ 1];
1900 o[ 5] = M[ 5];
1901 o[ 6] = M[ 9];
1902 o[ 7] = M[13];
1903
1904 o[ 8] = M[ 2];
1905 o[ 9] = M[ 6];
1906 o[10] = M[10];
1907 o[11] = M[14];
1908
1909 o[12] = M[ 3];
1910 o[13] = M[ 7];
1911 o[14] = M[11];
1912 o[15] = M[15];
1913#if defined ( USE_MATRIX_TEST )
1914 o.definitelyIdentityMatrix=definitelyIdentityMatrix;
1915#endif
1916 }
1917
1918
1919 // used to scale <-1,-1><1,1> to viewport
1920 template <class T>
1922 {
1923 const f32 scaleX = (viewport.getWidth() - 0.75f ) * 0.5f;
1924 const f32 scaleY = -(viewport.getHeight() - 0.75f ) * 0.5f;
1925
1926 const f32 dx = -0.5f + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) * 0.5f );
1927 const f32 dy = -0.5f + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) * 0.5f );
1928
1929 makeIdentity();
1930 M[12] = (T)dx;
1931 M[13] = (T)dy;
1932 return setScale(core::vector3d<T>((T)scaleX, (T)scaleY, (T)zScale));
1933 }
1934
1936
1941 template <class T>
1943 {
1944 // unit vectors
1945 core::vector3df f(from);
1946 core::vector3df t(to);
1947 f.normalize();
1948 t.normalize();
1949
1950 // axis multiplication by sin
1952
1953 // axis of rotation
1954 core::vector3df v(vs);
1955 v.normalize();
1956
1957 // cosinus angle
1958 T ca = f.dotProduct(t);
1959
1960 core::vector3df vt(v * (1 - ca));
1961
1962 M[0] = vt.X * v.X + ca;
1963 M[5] = vt.Y * v.Y + ca;
1964 M[10] = vt.Z * v.Z + ca;
1965
1966 vt.X *= v.Y;
1967 vt.Z *= v.X;
1968 vt.Y *= v.Z;
1969
1970 M[1] = vt.X - vs.Z;
1971 M[2] = vt.Z + vs.Y;
1972 M[3] = 0;
1973
1974 M[4] = vt.X + vs.Z;
1975 M[6] = vt.Y - vs.X;
1976 M[7] = 0;
1977
1978 M[8] = vt.Z - vs.Y;
1979 M[9] = vt.Y + vs.X;
1980 M[11] = 0;
1981
1982 M[12] = 0;
1983 M[13] = 0;
1984 M[14] = 0;
1985 M[15] = 1;
1986
1987 return *this;
1988 }
1989
1991
1997 template <class T>
1999 const core::vector3df& camPos,
2000 const core::vector3df& center,
2001 const core::vector3df& translation,
2002 const core::vector3df& axis,
2003 const core::vector3df& from)
2004 {
2005 // axis of rotation
2006 core::vector3df up = axis;
2007 up.normalize();
2008 const core::vector3df forward = (camPos - center).normalize();
2009 const core::vector3df right = up.crossProduct(forward).normalize();
2010
2011 // correct look vector
2012 const core::vector3df look = right.crossProduct(up);
2013
2014 // rotate from to
2015 // axis multiplication by sin
2016 const core::vector3df vs = look.crossProduct(from);
2017
2018 // cosinus angle
2019 const f32 ca = from.dotProduct(look);
2020
2021 core::vector3df vt(up * (1.f - ca));
2022
2023 M[0] = static_cast<T>(vt.X * up.X + ca);
2024 M[5] = static_cast<T>(vt.Y * up.Y + ca);
2025 M[10] = static_cast<T>(vt.Z * up.Z + ca);
2026
2027 vt.X *= up.Y;
2028 vt.Z *= up.X;
2029 vt.Y *= up.Z;
2030
2031 M[1] = static_cast<T>(vt.X - vs.Z);
2032 M[2] = static_cast<T>(vt.Z + vs.Y);
2033 M[3] = 0;
2034
2035 M[4] = static_cast<T>(vt.X + vs.Z);
2036 M[6] = static_cast<T>(vt.Y - vs.X);
2037 M[7] = 0;
2038
2039 M[8] = static_cast<T>(vt.Z - vs.Y);
2040 M[9] = static_cast<T>(vt.Y + vs.X);
2041 M[11] = 0;
2042
2043 setRotationCenter(center, translation);
2044 }
2045
2046
2048 template <class T>
2049 inline void CMatrix4<T>::setRotationCenter(const core::vector3df& center, const core::vector3df& translation)
2050 {
2051 M[12] = -M[0]*center.X - M[4]*center.Y - M[8]*center.Z + (center.X - translation.X );
2052 M[13] = -M[1]*center.X - M[5]*center.Y - M[9]*center.Z + (center.Y - translation.Y );
2053 M[14] = -M[2]*center.X - M[6]*center.Y - M[10]*center.Z + (center.Z - translation.Z );
2054 M[15] = (T) 1.0;
2055#if defined ( USE_MATRIX_TEST )
2056 definitelyIdentityMatrix=false;
2057#endif
2058 }
2059
2070
2071
2072 template <class T>
2074 const core::vector2df &rotatecenter,
2075 const core::vector2df &translate,
2076 const core::vector2df &scale)
2077 {
2078 const f32 c = cosf(rotateRad);
2079 const f32 s = sinf(rotateRad);
2080
2081 M[0] = (T)(c * scale.X);
2082 M[1] = (T)(s * scale.Y);
2083 M[2] = 0;
2084 M[3] = 0;
2085
2086 M[4] = (T)(-s * scale.X);
2087 M[5] = (T)(c * scale.Y);
2088 M[6] = 0;
2089 M[7] = 0;
2090
2091 M[8] = (T)(c * scale.X * rotatecenter.X + -s * rotatecenter.Y + translate.X);
2092 M[9] = (T)(s * scale.Y * rotatecenter.X + c * rotatecenter.Y + translate.Y);
2093 M[10] = 1;
2094 M[11] = 0;
2095
2096 M[12] = 0;
2097 M[13] = 0;
2098 M[14] = 0;
2099 M[15] = 1;
2100#if defined ( USE_MATRIX_TEST )
2101 definitelyIdentityMatrix=false;
2102#endif
2103 return *this;
2104 }
2105
2106
2107 // rotate about z axis, center ( 0.5, 0.5 )
2108 template <class T>
2110 {
2111 const f32 c = cosf(rotateRad);
2112 const f32 s = sinf(rotateRad);
2113 M[0] = (T)c;
2114 M[1] = (T)s;
2115
2116 M[4] = (T)-s;
2117 M[5] = (T)c;
2118
2119 M[8] = (T)(0.5f * ( s - c) + 0.5f);
2120 M[9] = (T)(-0.5f * ( s + c) + 0.5f);
2121
2122#if defined ( USE_MATRIX_TEST )
2123 definitelyIdentityMatrix = definitelyIdentityMatrix && (rotateRad==0.0f);
2124#endif
2125 return *this;
2126 }
2127
2128
2129 template <class T>
2131 {
2132 M[8] = (T)x;
2133 M[9] = (T)y;
2134
2135#if defined ( USE_MATRIX_TEST )
2136 definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f);
2137#endif
2138 return *this;
2139 }
2140
2141
2142 template <class T>
2144 {
2145 M[2] = (T)x;
2146 M[6] = (T)y;
2147
2148#if defined ( USE_MATRIX_TEST )
2149 definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f) ;
2150#endif
2151 return *this;
2152 }
2153
2154 template <class T>
2156 {
2157 M[0] = (T)sx;
2158 M[5] = (T)sy;
2159#if defined ( USE_MATRIX_TEST )
2160 definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
2161#endif
2162 return *this;
2163 }
2164
2165
2166 template <class T>
2168 {
2169 M[0] = (T)sx;
2170 M[5] = (T)sy;
2171 M[8] = (T)(0.5f - 0.5f * sx);
2172 M[9] = (T)(0.5f - 0.5f * sy);
2173
2174#if defined ( USE_MATRIX_TEST )
2175 definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
2176#endif
2177 return *this;
2178 }
2179
2180
2181 // sets all matrix data members at once
2182 template <class T>
2183 inline CMatrix4<T>& CMatrix4<T>::setM(const T* data)
2184 {
2185 memcpy(M,data, 16*sizeof(T));
2186
2187#if defined ( USE_MATRIX_TEST )
2188 definitelyIdentityMatrix=false;
2189#endif
2190 return *this;
2191 }
2192
2193
2194 // sets if the matrix is definitely identity matrix
2195 template <class T>
2196 inline void CMatrix4<T>::setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix)
2197 {
2198#if defined ( USE_MATRIX_TEST )
2199 definitelyIdentityMatrix = isDefinitelyIdentityMatrix;
2200#endif
2201 }
2202
2203
2204 // gets if the matrix is definitely identity matrix
2205 template <class T>
2207 {
2208#if defined ( USE_MATRIX_TEST )
2209 return definitelyIdentityMatrix;
2210#else
2211 return false;
2212#endif
2213 }
2214
2215
2217 template <class T>
2218 inline bool CMatrix4<T>::equals(const core::CMatrix4<T>& other, const T tolerance) const
2219 {
2220#if defined ( USE_MATRIX_TEST )
2221 if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
2222 return true;
2223#endif
2224 for (s32 i = 0; i < 16; ++i)
2225 if (!core::equals(M[i],other.M[i], tolerance))
2226 return false;
2227
2228 return true;
2229 }
2230
2231
2232 // Multiply by scalar.
2233 template <class T>
2234 inline CMatrix4<T> operator*(const T scalar, const CMatrix4<T>& mat)
2235 {
2236 return mat*scalar;
2237 }
2238
2239
2242
2244 IRRLICHT_API extern const matrix4 IdentityMatrix;
2245
2246} // end namespace core
2247} // end namespace irr
2248
2249#endif
2250
4x4 matrix. Mostly used as transformation matrix for 3d calculations.
Definition matrix4.h:46
bool isIdentity() const
Returns true if the matrix is the identity matrix.
Definition matrix4.h:1003
CMatrix4< T > & setRotationRadians(const vector3d< T > &rotation)
Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
Definition matrix4.h:828
CMatrix4< T > & setScale(const T scale)
Set Scale.
Definition matrix4.h:196
T & operator()(const s32 row, const s32 col)
Simple operator for directly accessing every element of the matrix.
Definition matrix4.h:69
CMatrix4< T > operator*(const T &scalar) const
Multiply by scalar.
Definition matrix4.h:576
T & operator[](u32 index)
Simple operator for linearly accessing every element of the matrix.
Definition matrix4.h:81
CMatrix4< T > & buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
Builds a left-handed perspective projection matrix based on a field of view.
Definition matrix4.h:1539
CMatrix4< T > & setInverseRotationRadians(const vector3d< T > &rotation)
Make an inverted rotation matrix from Euler angles.
Definition matrix4.h:920
void transformVect(T *out, const core::vector3df &in) const
An alternate transform vector method, writing into an array of 4 floats.
Definition matrix4.h:1163
void multiplyWith1x4Matrix(T *matrix) const
Multiplies this matrix by a 1x4 matrix.
Definition matrix4.h:1271
void getTransposed(CMatrix4< T > &dest) const
Gets transposed matrix.
Definition matrix4.h:1892
CMatrix4< T > & operator-=(const CMatrix4< T > &other)
Subtract another matrix.
Definition matrix4.h:552
CMatrix4< T > & setInverseTranslation(const vector3d< T > &translation)
Set the inverse translation of the current matrix. Will erase any previous values.
Definition matrix4.h:766
core::vector3d< T > getScale() const
Get Scale.
Definition matrix4.h:798
const T & operator[](u32 index) const
Simple operator for linearly accessing every element of the matrix.
Definition matrix4.h:90
CMatrix4< T > & setTextureTranslate(f32 x, f32 y)
Set texture transformation translation.
Definition matrix4.h:2130
CMatrix4< T > & setRotationAxisRadians(const T &angle, const vector3d< T > &axis)
Make a rotation matrix from angle and axis, assuming left handed rotation.
Definition matrix4.h:951
void transformBoxEx(core::aabbox3d< f32 > &box) const
Transforms a axis aligned bounding box.
Definition matrix4.h:1220
bool getInverse(CMatrix4< T > &out) const
Gets the inversed matrix of this one.
Definition matrix4.h:1310
CMatrix4< T > interpolate(const core::CMatrix4< T > &b, f32 time) const
Creates a new matrix as interpolated matrix from two other ones.
Definition matrix4.h:1865
CMatrix4< T > & buildProjectionMatrixPerspectiveFovInfinityLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon=0)
Builds a left-handed perspective projection matrix based on a field of view, with far plane at infini...
Definition matrix4.h:1576
bool makeInverse()
Calculates inverse of matrix. Slow.
Definition matrix4.h:1432
CMatrix4< T > & setTextureRotationCenter(f32 radAngle)
Set texture transformation rotation.
Definition matrix4.h:2109
void rotateVect(vector3df &vect) const
Rotate a vector by the rotation part of this matrix.
Definition matrix4.h:1104
CMatrix4< T > & makeIdentity()
Set matrix to identity.
Definition matrix4.h:987
CMatrix4< T > & setScale(const vector3d< T > &scale)
Set Scale.
Definition matrix4.h:778
CMatrix4< T > & operator=(const CMatrix4< T > &other)
Sets this matrix equal to the other matrix.
Definition matrix4.h:1451
CMatrix4< T > & buildRotateFromTo(const core::vector3df &from, const core::vector3df &to)
Builds a matrix that rotates from one vector to another.
Definition matrix4.h:1942
void transformBox(core::aabbox3d< f32 > &box) const
Transforms a axis aligned bounding box.
Definition matrix4.h:1206
void transformVect(vector3df &out, const vector3df &in) const
Transforms input vector by this matrix and stores result in output vector.
Definition matrix4.h:1154
void transformVect(vector3df &vect) const
Transforms the vector by this matrix.
Definition matrix4.h:1140
CMatrix4< T > & setbyproduct_nocheck(const CMatrix4< T > &other_a, const CMatrix4< T > &other_b)
Set this matrix to the product of two matrices.
Definition matrix4.h:653
vector3d< T > getTranslation() const
Gets the current translation.
Definition matrix4.h:747
CMatrix4< T > & buildShadowMatrix(const core::vector3df &light, core::plane3df plane, f32 point=1.0f)
Builds a matrix that flattens geometry into a plane.
Definition matrix4.h:1751
bool operator!=(const CMatrix4< T > &other) const
Returns true if other matrix is not equal to this matrix.
Definition matrix4.h:1492
CMatrix4< T > & buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
Builds a right-handed perspective projection matrix based on a field of view.
Definition matrix4.h:1500
const T & operator()(const s32 row, const s32 col) const
Simple operator for directly accessing every element of the matrix.
Definition matrix4.h:78
CMatrix4< T > & buildCameraLookAtMatrixRH(const vector3df &position, const vector3df &target, const vector3df &upVector)
Builds a right-handed look-at matrix.
Definition matrix4.h:1824
CMatrix4< T > & buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
Builds a right-handed perspective projection matrix.
Definition matrix4.h:1682
const T * pointer() const
Returns pointer to internal array.
Definition matrix4.h:99
bool isOrthogonal() const
Returns true if the matrix is orthogonal.
Definition matrix4.h:1041
CMatrix4< T > getTransposed() const
Gets transposed matrix.
Definition matrix4.h:1882
void inverseTranslateVect(vector3df &vect) const
Translate a vector by the inverse of the translation part of this matrix.
Definition matrix4.h:1293
CMatrix4< T > & buildCameraLookAtMatrixLH(const vector3df &position, const vector3df &target, const vector3df &upVector)
Builds a left-handed look-at matrix.
Definition matrix4.h:1783
eConstructor
Constructor Flags.
Definition matrix4.h:51
CMatrix4< T > & setTextureTranslateTransposed(f32 x, f32 y)
Set texture transformation translation, using a transposed representation.
Definition matrix4.h:2143
void setRotationCenter(const core::vector3df &center, const core::vector3df &translate)
Builds a combined matrix which translates to a center before rotation and translates from origin afte...
Definition matrix4.h:2049
CMatrix4< T > & buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
Builds a left-handed perspective projection matrix.
Definition matrix4.h:1717
CMatrix4< T > & setbyproduct(const CMatrix4< T > &other_a, const CMatrix4< T > &other_b)
set this matrix to the product of two matrices
Definition matrix4.h:688
void setDefinitelyIdentityMatrix(bool isDefinitelyIdentityMatrix)
Sets if the matrix is definitely identity matrix.
Definition matrix4.h:2196
CMatrix4< T > & buildNDCToDCMatrix(const core::rect< s32 > &area, f32 zScale)
Builds a matrix which transforms a normalized Device Coordinate to Device Coordinates.
Definition matrix4.h:1921
CMatrix4< T > & setRotationDegrees(const vector3d< T > &rotation)
Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
Definition matrix4.h:816
void rotateVect(core::vector3df &out, const core::vector3df &in) const
An alternate transform vector method, writing into a second vector.
Definition matrix4.h:1114
CMatrix4< T > & operator=(const T &scalar)
Sets all elements of this matrix to the value.
Definition matrix4.h:1464
void transformPlane(core::plane3d< f32 > &plane) const
Transforms a plane by this matrix.
Definition matrix4.h:1182
bool getInversePrimitive(CMatrix4< T > &out) const
Inverts a primitive matrix which only contains a translation and a rotation.
Definition matrix4.h:1401
CMatrix4< T > operator-(const CMatrix4< T > &other) const
Subtract another matrix.
Definition matrix4.h:526
void transformVec3(T *out, const T *in) const
An alternate transform vector method, reading from and writing to an array of 3 floats.
Definition matrix4.h:1172
void transformPlane(const core::plane3d< f32 > &in, core::plane3d< f32 > &out) const
Transforms a plane by this matrix.
Definition matrix4.h:1198
bool operator==(const CMatrix4< T > &other) const
Returns true if other matrix is equal to this matrix.
Definition matrix4.h:1477
bool equals(const core::CMatrix4< T > &other, const T tolerance=(T) ROUNDING_ERROR_f64) const
Compare two matrices using the equal method.
Definition matrix4.h:2218
CMatrix4< T > & setTranslation(const vector3d< T > &translation)
Set the translation of the current matrix. Will erase any previous values.
Definition matrix4.h:754
void translateVect(vector3df &vect) const
Translate a vector by the translation part of this matrix.
Definition matrix4.h:1301
CMatrix4< T > & operator*=(const CMatrix4< T > &other)
Multiply by another matrix.
Definition matrix4.h:626
CMatrix4< T > operator+(const CMatrix4< T > &other) const
Add another matrix.
Definition matrix4.h:476
CMatrix4(const CMatrix4< T > &other, eConstructor constructor=EM4CONST_COPY)
Copy constructor.
Definition matrix4.h:440
void rotateVect(T *out, const core::vector3df &in) const
An alternate transform vector method, writing into an array of 3 floats.
Definition matrix4.h:1123
void buildAxisAlignedBillboard(const core::vector3df &camPos, const core::vector3df &center, const core::vector3df &translation, const core::vector3df &axis, const core::vector3df &from)
Builds a matrix which rotates a source vector to a look vector over an arbitrary axis.
Definition matrix4.h:1998
core::vector3d< T > getRotationDegrees() const
Returns the rotation, as set by setRotation().
Definition matrix4.h:863
bool isIdentity_integer_base() const
Returns true if the matrix is the identity matrix.
Definition matrix4.h:1070
CMatrix4< T > & setTextureScaleCenter(f32 sx, f32 sy)
Set texture transformation scale, and recenter at (0.5,0.5).
Definition matrix4.h:2167
CMatrix4< T > & buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
Builds a left-handed orthogonal projection matrix.
Definition matrix4.h:1612
CMatrix4< T > & setM(const T *data)
Sets all matrix data members at once.
Definition matrix4.h:2183
CMatrix4< T > & operator*=(const T &scalar)
Multiply by scalar.
Definition matrix4.h:602
CMatrix4< T > & buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
Builds a right-handed orthogonal projection matrix.
Definition matrix4.h:1647
CMatrix4< T > & setTextureScale(f32 sx, f32 sy)
Set texture transformation scale.
Definition matrix4.h:2155
void inverseRotateVect(vector3df &vect) const
Rotate a vector by the inverse of the rotation part of this matrix.
Definition matrix4.h:1131
CMatrix4< T > operator*(const CMatrix4< T > &other) const
Multiply by another matrix.
Definition matrix4.h:705
bool getDefinitelyIdentityMatrix() const
Gets if the matrix is definitely identity matrix.
Definition matrix4.h:2206
CMatrix4(eConstructor constructor=EM4CONST_IDENTITY)
Default constructor.
Definition matrix4.h:417
CMatrix4< T > & operator+=(const CMatrix4< T > &other)
Add another matrix.
Definition matrix4.h:502
CMatrix4< T > & buildTextureTransform(f32 rotateRad, const core::vector2df &rotatecenter, const core::vector2df &translate, const core::vector2df &scale)
Set to a texture transformation matrix with the given parameters.
Definition matrix4.h:2073
CMatrix4< T > & setInverseRotationDegrees(const vector3d< T > &rotation)
Make an inverted rotation matrix from Euler angles.
Definition matrix4.h:822
Axis aligned bounding box in 3d dimensional space.
Definition aabbox3d.h:22
vector3d< T > MaxEdge
The far edge.
Definition aabbox3d.h:347
vector3d< T > MinEdge
The near edge.
Definition aabbox3d.h:344
void repair()
Repairs the box.
Definition aabbox3d.h:180
Template plane class with some intersection testing methods.
Definition plane3d.h:34
vector3d< T > getMemberPoint() const
Gets a member point of the plane.
Definition plane3d.h:155
vector3d< T > Normal
Normal vector of the plane.
Definition plane3d.h:228
T D
Distance from origin.
Definition plane3d.h:231
Rectangle template.
Definition rect.h:27
position2d< T > LowerRightCorner
Lower right corner.
Definition rect.h:267
position2d< T > UpperLeftCorner
Upper left corner.
Definition rect.h:265
T getHeight() const
Get height of rectangle.
Definition rect.h:190
T getWidth() const
Get width of rectangle.
Definition rect.h:184
T X
X coordinate of vector.
Definition vector2d.h:316
T Y
Y coordinate of vector.
Definition vector2d.h:319
3d vector template class with lots of operators and methods.
Definition vector3d.h:23
vector3d< T > crossProduct(const vector3d< T > &p) const
Calculates the cross product with another vector.
Definition vector3d.h:147
T X
X coordinate of the vector.
Definition vector3d.h:408
vector3d< T > & normalize()
Normalizes the vector.
Definition vector3d.h:168
T Z
Z coordinate of the vector.
Definition vector3d.h:414
T dotProduct(const vector3d< T > &other) const
Get the dot product with another vector.
Definition vector3d.h:125
T Y
Y coordinate of the vector.
Definition vector3d.h:411
Basic classes such as vectors, planes, arrays, lists, and so on can be found in this namespace.
Definition aabbox3d.h:15
vector3d< f32 > vector3df
Typedef for a f32 3d vector.
Definition vector3d.h:445
vector2d< f32 > vector2df
Typedef for f32 2d vector.
Definition vector2d.h:323
const f32 DEGTORAD
32bit Constant for converting from degrees to radians
Definition irrMath.h:74
const T clamp(const T &value, const T &low, const T &high)
clamps a value between low and high
Definition irrMath.h:166
CMatrix4< f32 > matrix4
Typedef for f32 matrix.
Definition matrix4.h:2241
bool equals(const f64 a, const f64 b, const f64 tolerance=ROUNDING_ERROR_f64)
returns if a equals b, taking possible rounding errors into account
Definition irrMath.h:185
IRRLICHT_API const matrix4 IdentityMatrix
global const identity matrix
plane3d< f32 > plane3df
Typedef for a f32 3d plane.
Definition plane3d.h:236
const f64 RADTODEG64
64bit constant for converting from radians to degrees
Definition irrMath.h:83
bool iszero(const f64 a, const f64 tolerance=ROUNDING_ERROR_f64)
returns if a equals zero, taking rounding errors into account
Definition irrMath.h:270
u32 IR(f32 x)
Definition irrMath.h:353
Everything in the Irrlicht Engine can be found in this namespace.
Definition Skylicht.h:33
float f32
32 bit floating point variable.
Definition irrTypes.h:104
unsigned int u32
32 bit unsigned variable.
Definition irrTypes.h:58
double f64
64 bit floating point variable.
Definition irrTypes.h:108
signed int s32
32 bit signed variable.
Definition irrTypes.h:66