Nirtcpp 2.1.0
Nirtcpp is a high-performance c++ graphics engine.
Loading...
Searching...
No Matches
matrix4.hpp
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 nirtcpp/nirtcpp.hpp
4
5#ifndef NIRT_MATRIX_HPP_INCLUDED
6#define NIRT_MATRIX_HPP_INCLUDED
7
8#include <nirtcpp/core/engine/irrMath.hpp>
9#include <nirtcpp/core/engine/vector3d.hpp>
10#include <nirtcpp/core/engine/vector2d.hpp>
11#include <nirtcpp/core/engine/plane3d.hpp>
12#include <nirtcpp/core/engine/aabbox3d.hpp>
13#include <nirtcpp/core/engine/rect.hpp>
14#include <nirtcpp/core/engine/irrString.hpp>
15#include <algorithm>
16#include <math.h>
17
18// enable this to keep track of changes to the matrix
19// and make simpler identity check for seldom changing matrices
20// otherwise identity check will always compare the elements
21//#define USE_MATRIX_TEST
22
23// this is only for debugging purposes
24//#define USE_MATRIX_TEST_DEBUG
25
26#if defined( USE_MATRIX_TEST_DEBUG )
27
28class MatrixTest
29{
30public:
31 MatrixTest () : ID(0), Calls(0) {}
32 char buf[256];
33 int Calls;
34 int ID;
35};
36static MatrixTest MTest;
37
38#endif
39
40namespace nirt
41{
42namespace core
43{
44
46
47 template <typename T>
49 {
50 public:
51
54 {
55 EM4CONST_NOTHING = 0,
56 EM4CONST_COPY,
57 EM4CONST_IDENTITY,
58 EM4CONST_TRANSPOSED,
59 EM4CONST_INVERSE,
60 EM4CONST_INVERSE_TRANSPOSED
61 };
62
64
65 CMatrix4( eConstructor constructor = EM4CONST_IDENTITY );
66
68 CMatrix4(const T& r0c0, const T& r0c1, const T& r0c2, const T& r0c3,
69 const T& r1c0, const T& r1c1, const T& r1c2, const T& r1c3,
70 const T& r2c0, const T& r2c1, const T& r2c2, const T& r2c3,
71 const T& r3c0, const T& r3c1, const T& r3c2, const T& r3c3)
72 {
73 M[0] = r0c0; M[1] = r0c1; M[2] = r0c2; M[3] = r0c3;
74 M[4] = r1c0; M[5] = r1c1; M[6] = r1c2; M[7] = r1c3;
75 M[8] = r2c0; M[9] = r2c1; M[10] = r2c2; M[11] = r2c3;
76 M[12] = r3c0; M[13] = r3c1; M[14] = r3c2; M[15] = r3c3;
77 }
78
80
82 CMatrix4(const CMatrix4<T>& other, eConstructor constructor = EM4CONST_COPY);
83
85 T& operator()(const s32 row, const s32 col)
86 {
87#if defined ( USE_MATRIX_TEST )
89#endif
90 return M[ row * 4 + col ];
91 }
92
94 const T& operator()(const s32 row, const s32 col) const { return M[row * 4 + col]; }
95
98 {
99#if defined ( USE_MATRIX_TEST )
101#endif
102 return M[index];
103 }
104
106 const T& operator[](u32 index) const { return M[index]; }
107
109 {
110#if defined ( USE_MATRIX_TEST )
112#endif
113 return M[row*4+col];
114 }
115
116 const T & operator[](nirt::u32 row, nirt::u32 col) const
117 {
118 return M[row*4+col];
119 }
120
122 inline CMatrix4<T>& operator=(const CMatrix4<T> &other);
123
125 inline CMatrix4<T>& operator=(const T& scalar);
126
128 const T* pointer() const { return M; }
129 T* pointer()
130 {
131#if defined ( USE_MATRIX_TEST )
133#endif
134 return M;
135 }
136
138 bool operator==(const CMatrix4<T> &other) const;
139
141 bool operator!=(const CMatrix4<T> &other) const;
142
144 CMatrix4<T> operator+(const CMatrix4<T>& other) const;
145
147 CMatrix4<T>& operator+=(const CMatrix4<T>& other);
148
150 CMatrix4<T> operator-(const CMatrix4<T>& other) const;
151
153 CMatrix4<T>& operator-=(const CMatrix4<T>& other);
154
156
157 inline CMatrix4<T>& setbyproduct(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
158
160
162 CMatrix4<T>& setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
163
165
166 CMatrix4<T> operator*(const CMatrix4<T>& other) const;
167
169
171 CMatrix4<T>& operator*=(const CMatrix4<T>& other);
172
174 CMatrix4<T> operator*(const T& scalar) const;
175
177 CMatrix4<T>& operator*=(const T& scalar);
178
180 inline CMatrix4<T>& makeIdentity();
181
183 inline bool isIdentity() const;
184
186 inline bool isOrthogonal() const;
187
189 bool isIdentity_integer_base () const;
190
192 CMatrix4<T>& setTranslation( const vector3d<T>& translation );
193
195 vector3d<T> getTranslation() const;
196
198 CMatrix4<T>& setInverseTranslation( const vector3d<T>& translation );
199
201 inline CMatrix4<T>& setRotationRadians( const vector3d<T>& rotation );
202
204 CMatrix4<T>& setRotationDegrees( const vector3d<T>& rotation );
205
207
217 core::vector3d<T> getRotationDegrees(const vector3d<T>& scale) const;
218
220
227
229
230 inline CMatrix4<T>& setInverseRotationRadians( const vector3d<T>& rotation );
231
233
234 inline CMatrix4<T>& setInverseRotationDegrees( const vector3d<T>& rotation );
235
237
238 inline CMatrix4<T>& setRotationAxisRadians(const T& angle, const vector3d<T>& axis);
239
241 CMatrix4<T>& setScale( const vector3d<T>& scale );
242
244 CMatrix4<T>& setScale( const T scale ) { return setScale(core::vector3d<T>(scale,scale,scale)); }
245
248
250 void inverseTranslateVect( vector3df& vect ) const;
251
253 void inverseRotateVect( vector3df& vect ) const;
254
256 void rotateVect( vector3df& vect ) const;
257
259 void rotateVect(core::vector3df& out, const core::vector3df& in) const;
260
262 void rotateVect(T *out,const core::vector3df &in) const;
263
265
266 void transformVect( vector3df& vect) const;
267
269
270 void transformVect( vector3df& out, const vector3df& in ) const;
271
273
275 void transformVect(T *out,const core::vector3df &in) const;
276
278
280 void transformVec3(T *out, const T * in) const;
281
283 void transformVec4(T *out, const T * in) const;
284
286
287 void translateVect( vector3df& vect ) const;
288
291
294
296
299
301
304
306 void multiplyWith1x4Matrix(T* matrix) const;
307
309
310 bool makeInverse();
311
312
314
315 bool getInversePrimitive ( CMatrix4<T>& out ) const;
316
318
320 bool getInverse(CMatrix4<T>& out) const;
321
323 //\param zClipFromZero: Clipping of z can be projected from 0 to w when true (D3D style) and from -w to w when false (OGL style).
325
328
331
334
337
339 //\param zClipFromZero: Clipping of z can be projected from 0 to 1 when true (D3D style) and from -1 to 1 when false (OGL style).
341
344
347 const vector3df& position,
348 const vector3df& target,
349 const vector3df& upVector);
350
353 const vector3df& position,
354 const vector3df& target,
355 const vector3df& upVector);
356
358
363
365
367
369
372
375
377 inline void getTransposed( CMatrix4<T>& dest ) const;
378
380
384
386
390
392
399 const core::vector3df& center,
401 const core::vector3df& axis,
402 const core::vector3df& from);
403
404 /*
405 construct 2D Texture transformations
406 rotate about center, scale, and transform.
407 */
412 const core::vector2df &scale);
413
415
420
422
427
429
431 void getTextureTranslate( f32& x, f32& y ) const;
432
434
439
441
446
448
450 void getTextureScale( f32& sx, f32& sy ) const;
451
453
458
460 CMatrix4<T>& setM(const T* data);
461
464
466 bool getDefinitelyIdentityMatrix() const;
467
469 bool equals(const core::CMatrix4<T>& other, const T tolerance=(T)ROUNDING_ERROR_f64) const;
470
471 private:
473 T M[16];
474#if defined ( USE_MATRIX_TEST )
477#endif
478#if defined ( USE_MATRIX_TEST_DEBUG )
479 u32 id;
480 mutable u32 calls;
481#endif
482
483 }; // class CMatrix4
484
485 // Default constructor
486 template <class T>
488#if defined ( USE_MATRIX_TEST )
490#endif
491#if defined ( USE_MATRIX_TEST_DEBUG )
492 ,id ( MTest.ID++), calls ( 0 )
493#endif
494 {
495 switch ( constructor )
496 {
497 case EM4CONST_NOTHING:
498 case EM4CONST_COPY:
499 break;
500 case EM4CONST_IDENTITY:
501 case EM4CONST_INVERSE:
502 default:
503 makeIdentity();
504 break;
505 }
506 }
507
508 // Copy constructor
509 template <class T>
511#if defined ( USE_MATRIX_TEST )
513#endif
514#if defined ( USE_MATRIX_TEST_DEBUG )
515 ,id ( MTest.ID++), calls ( 0 )
516#endif
517 {
518 switch ( constructor )
519 {
520 case EM4CONST_IDENTITY:
521 makeIdentity();
522 break;
523 case EM4CONST_NOTHING:
524 break;
525 case EM4CONST_COPY:
526 *this = other;
527 break;
528 case EM4CONST_TRANSPOSED:
529 other.getTransposed(*this);
530 break;
531 case EM4CONST_INVERSE:
532 if (!other.getInverse(*this))
533 std::fill_n(M, 16, 0);
534 break;
535 case EM4CONST_INVERSE_TRANSPOSED:
536 if (!other.getInverse(*this))
537 std::fill_n(M, 16, 0);
538 else
539 *this=getTransposed();
540 break;
541 }
542 }
543
545 template <class T>
547 {
548 CMatrix4<T> temp ( EM4CONST_NOTHING );
549
550 temp[0] = M[0]+other[0];
551 temp[1] = M[1]+other[1];
552 temp[2] = M[2]+other[2];
553 temp[3] = M[3]+other[3];
554 temp[4] = M[4]+other[4];
555 temp[5] = M[5]+other[5];
556 temp[6] = M[6]+other[6];
557 temp[7] = M[7]+other[7];
558 temp[8] = M[8]+other[8];
559 temp[9] = M[9]+other[9];
560 temp[10] = M[10]+other[10];
561 temp[11] = M[11]+other[11];
562 temp[12] = M[12]+other[12];
563 temp[13] = M[13]+other[13];
564 temp[14] = M[14]+other[14];
565 temp[15] = M[15]+other[15];
566
567 return temp;
568 }
569
571 template <class T>
573 {
574 M[0]+=other[0];
575 M[1]+=other[1];
576 M[2]+=other[2];
577 M[3]+=other[3];
578 M[4]+=other[4];
579 M[5]+=other[5];
580 M[6]+=other[6];
581 M[7]+=other[7];
582 M[8]+=other[8];
583 M[9]+=other[9];
584 M[10]+=other[10];
585 M[11]+=other[11];
586 M[12]+=other[12];
587 M[13]+=other[13];
588 M[14]+=other[14];
589 M[15]+=other[15];
590
591 return *this;
592 }
593
595 template <class T>
597 {
598 CMatrix4<T> temp ( EM4CONST_NOTHING );
599
600 temp[0] = M[0]-other[0];
601 temp[1] = M[1]-other[1];
602 temp[2] = M[2]-other[2];
603 temp[3] = M[3]-other[3];
604 temp[4] = M[4]-other[4];
605 temp[5] = M[5]-other[5];
606 temp[6] = M[6]-other[6];
607 temp[7] = M[7]-other[7];
608 temp[8] = M[8]-other[8];
609 temp[9] = M[9]-other[9];
610 temp[10] = M[10]-other[10];
611 temp[11] = M[11]-other[11];
612 temp[12] = M[12]-other[12];
613 temp[13] = M[13]-other[13];
614 temp[14] = M[14]-other[14];
615 temp[15] = M[15]-other[15];
616
617 return temp;
618 }
619
621 template <class T>
623 {
624 M[0]-=other[0];
625 M[1]-=other[1];
626 M[2]-=other[2];
627 M[3]-=other[3];
628 M[4]-=other[4];
629 M[5]-=other[5];
630 M[6]-=other[6];
631 M[7]-=other[7];
632 M[8]-=other[8];
633 M[9]-=other[9];
634 M[10]-=other[10];
635 M[11]-=other[11];
636 M[12]-=other[12];
637 M[13]-=other[13];
638 M[14]-=other[14];
639 M[15]-=other[15];
640
641 return *this;
642 }
643
645 template <class T>
647 {
648 CMatrix4<T> temp ( EM4CONST_NOTHING );
649
650 temp[0] = M[0]*scalar;
651 temp[1] = M[1]*scalar;
652 temp[2] = M[2]*scalar;
653 temp[3] = M[3]*scalar;
654 temp[4] = M[4]*scalar;
655 temp[5] = M[5]*scalar;
656 temp[6] = M[6]*scalar;
657 temp[7] = M[7]*scalar;
658 temp[8] = M[8]*scalar;
659 temp[9] = M[9]*scalar;
660 temp[10] = M[10]*scalar;
661 temp[11] = M[11]*scalar;
662 temp[12] = M[12]*scalar;
663 temp[13] = M[13]*scalar;
664 temp[14] = M[14]*scalar;
665 temp[15] = M[15]*scalar;
666
667 return temp;
668 }
669
671 template <class T>
673 {
674 M[0]*=scalar;
675 M[1]*=scalar;
676 M[2]*=scalar;
677 M[3]*=scalar;
678 M[4]*=scalar;
679 M[5]*=scalar;
680 M[6]*=scalar;
681 M[7]*=scalar;
682 M[8]*=scalar;
683 M[9]*=scalar;
684 M[10]*=scalar;
685 M[11]*=scalar;
686 M[12]*=scalar;
687 M[13]*=scalar;
688 M[14]*=scalar;
689 M[15]*=scalar;
690
691 return *this;
692 }
693
695 template <class T>
697 {
698#if defined ( USE_MATRIX_TEST )
699 // do checks on your own in order to avoid copy creation
700 if ( !other.isIdentity() )
701 {
702 if ( this->isIdentity() )
703 {
704 return (*this = other);
705 }
706 else
707 {
708 CMatrix4<T> temp ( *this );
709 return setbyproduct_nocheck( temp, other );
710 }
711 }
712 return *this;
713#else
714 CMatrix4<T> temp ( *this );
715 return setbyproduct_nocheck( temp, other );
716#endif
717 }
718
720 // set this matrix to the product of two other matrices
721 // goal is to reduce stack use and copy
722 template <class T>
724 {
725 const T *m1 = other_a.M;
726 const T *m2 = other_b.M;
727
728 M[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
729 M[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
730 M[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
731 M[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
732
733 M[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
734 M[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
735 M[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
736 M[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
737
738 M[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
739 M[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
740 M[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
741 M[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
742
743 M[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
744 M[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
745 M[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
746 M[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
747#if defined ( USE_MATRIX_TEST )
749#endif
750 return *this;
751 }
752
753
755 // set this matrix to the product of two other matrices
756 // goal is to reduce stack use and copy
757 template <class T>
759 {
760#if defined ( USE_MATRIX_TEST )
761 if ( other_a.isIdentity () )
762 return (*this = other_b);
763 else
764 if ( other_b.isIdentity () )
765 return (*this = other_a);
766 else
767 return setbyproduct_nocheck(other_a,other_b);
768#else
769 return setbyproduct_nocheck(other_a,other_b);
770#endif
771 }
772
774 template <class T>
776 {
777#if defined ( USE_MATRIX_TEST )
778 // Testing purpose..
779 if ( this->isIdentity() )
780 return m2;
781 if ( m2.isIdentity() )
782 return *this;
783#endif
784
785 CMatrix4<T> m3 ( EM4CONST_NOTHING );
786
787 const T *m1 = M;
788
789 m3[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
790 m3[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
791 m3[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
792 m3[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
793
794 m3[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
795 m3[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
796 m3[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
797 m3[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
798
799 m3[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
800 m3[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
801 m3[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
802 m3[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
803
804 m3[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
805 m3[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
806 m3[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
807 m3[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
808 return m3;
809 }
810
811
812
813 template <class T>
815 {
816 return vector3d<T>(M[12], M[13], M[14]);
817 }
818
819
820 template <class T>
822 {
823 M[12] = translation.X;
824 M[13] = translation.Y;
825 M[14] = translation.Z;
826#if defined ( USE_MATRIX_TEST )
828#endif
829 return *this;
830 }
831
832 template <class T>
834 {
835 M[12] = -translation.X;
836 M[13] = -translation.Y;
837 M[14] = -translation.Z;
838#if defined ( USE_MATRIX_TEST )
840#endif
841 return *this;
842 }
843
844 template <class T>
846 {
847 M[0] = scale.X;
848 M[5] = scale.Y;
849 M[10] = scale.Z;
850#if defined ( USE_MATRIX_TEST )
852#endif
853 return *this;
854 }
855
857
862 template <class T>
864 {
865 // See http://www.robertblum.com/articles/2005/02/14/decomposing-matrices
866
867 // Deal with the 0 rotation case first
868 // Prior to Nirtcpp 1.6, we always returned this value.
869 if(core::iszero(M[1]) && core::iszero(M[2]) &&
870 core::iszero(M[4]) && core::iszero(M[6]) &&
871 core::iszero(M[8]) && core::iszero(M[9]))
872 return vector3d<T>(M[0], M[5], M[10]);
873
874 // We have to do the full calculation.
875 return vector3d<T>(sqrtf(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]),
876 sqrtf(M[4] * M[4] + M[5] * M[5] + M[6] * M[6]),
877 sqrtf(M[8] * M[8] + M[9] * M[9] + M[10] * M[10]));
878 }
879
880 template <class T>
882 {
883 return setRotationRadians( rotation * core::DEGTORAD );
884 }
885
886 template <class T>
888 {
889 return setInverseRotationRadians( rotation * core::DEGTORAD );
890 }
891
892 template <class T>
894 {
895 const f64 cr = cos( rotation.X );
896 const f64 sr = sin( rotation.X );
897 const f64 cp = cos( rotation.Y );
898 const f64 sp = sin( rotation.Y );
899 const f64 cy = cos( rotation.Z );
900 const f64 sy = sin( rotation.Z );
901
902 M[0] = (T)( cp*cy );
903 M[1] = (T)( cp*sy );
904 M[2] = (T)( -sp );
905
906 const f64 srsp = sr*sp;
907 const f64 crsp = cr*sp;
908
909 M[4] = (T)( srsp*cy-cr*sy );
910 M[5] = (T)( srsp*sy+cr*cy );
911 M[6] = (T)( sr*cp );
912
913 M[8] = (T)( crsp*cy+sr*sy );
914 M[9] = (T)( crsp*sy-sr*cy );
915 M[10] = (T)( cr*cp );
916#if defined ( USE_MATRIX_TEST )
918#endif
919 return *this;
920 }
921
922
924
928 template <class T>
930 {
931 const CMatrix4<T> &mat = *this;
932 const core::vector3d<f64> scale(core::iszero(scale_.X) ? FLT_MAX : scale_.X , core::iszero(scale_.Y) ? FLT_MAX : scale_.Y, core::iszero(scale_.Z) ? FLT_MAX : scale_.Z);
933 const core::vector3d<f64> invScale(core::reciprocal(scale.X),core::reciprocal(scale.Y),core::reciprocal(scale.Z));
934
935 f64 Y = -asin(core::clamp(mat[2]*invScale.X, -1.0, 1.0));
936 const f64 C = cos(Y);
937 Y *= RADTODEG64;
938
939 f64 rotx, roty, X, Z;
940
941 if (!core::iszero((T)C))
942 {
943 const f64 invC = core::reciprocal(C);
944 rotx = mat[10] * invC * invScale.Z;
945 roty = mat[6] * invC * invScale.Y;
946 X = atan2( roty, rotx ) * RADTODEG64;
947 rotx = mat[0] * invC * invScale.X;
948 roty = mat[1] * invC * invScale.X;
949 Z = atan2( roty, rotx ) * RADTODEG64;
950 }
951 else
952 {
953 X = 0.0;
954 rotx = mat[5] * invScale.Y;
955 roty = -mat[4] * invScale.Y;
956 Z = atan2( roty, rotx ) * RADTODEG64;
957 }
958
959 // fix values that get below zero
960 if (X < 0.0) X += 360.0;
961 if (Y < 0.0) Y += 360.0;
962 if (Z < 0.0) Z += 360.0;
963
964 return vector3d<T>((T)X,(T)Y,(T)Z);
965 }
966
968 template <class T>
970 {
971 // Note: Using getScale() here make it look like it could do matrix decomposition.
972 // It can't! It works (or should work) as long as rotation doesn't flip the handedness
973 // aka scale swapping 1 or 3 axes. (I think we could catch that as well by comparing
974 // crossproduct of first 2 axes to direction of third axis, but TODO)
975 // And maybe it should also offer the solution for the simple calculation
976 // without regarding scaling as Nirtcpp did before 1.7
977 core::vector3d<T> scale(getScale());
978
979 // We assume the matrix uses rotations instead of negative scaling 2 axes.
980 // Otherwise it fails even for some simple cases, like rotating around
981 // 2 axes by 180° which getScale thinks is a negative scaling.
982 if (scale.Y<0 && scale.Z<0)
983 {
984 scale.Y =-scale.Y;
985 scale.Z =-scale.Z;
986 }
987 else if (scale.X<0 && scale.Z<0)
988 {
989 scale.X =-scale.X;
990 scale.Z =-scale.Z;
991 }
992 else if (scale.X<0 && scale.Y<0)
993 {
994 scale.X =-scale.X;
995 scale.Y =-scale.Y;
996 }
997
998 return getRotationDegrees(scale);
999 }
1000
1001
1003 template <class T>
1005 {
1006 f64 cr = cos( rotation.X );
1007 f64 sr = sin( rotation.X );
1008 f64 cp = cos( rotation.Y );
1009 f64 sp = sin( rotation.Y );
1010 f64 cy = cos( rotation.Z );
1011 f64 sy = sin( rotation.Z );
1012
1013 M[0] = (T)( cp*cy );
1014 M[4] = (T)( cp*sy );
1015 M[8] = (T)( -sp );
1016
1017 f64 srsp = sr*sp;
1018 f64 crsp = cr*sp;
1019
1020 M[1] = (T)( srsp*cy-cr*sy );
1021 M[5] = (T)( srsp*sy+cr*cy );
1022 M[9] = (T)( sr*cp );
1023
1024 M[2] = (T)( crsp*cy+sr*sy );
1025 M[6] = (T)( crsp*sy-sr*cy );
1026 M[10] = (T)( cr*cp );
1027#if defined ( USE_MATRIX_TEST )
1029#endif
1030 return *this;
1031 }
1032
1034 template <class T>
1036 {
1037 const f64 c = cos(angle);
1038 const f64 s = sin(angle);
1039 const f64 t = 1.0 - c;
1040
1041 const f64 tx = t * axis.X;
1042 const f64 ty = t * axis.Y;
1043 const f64 tz = t * axis.Z;
1044
1045 const f64 sx = s * axis.X;
1046 const f64 sy = s * axis.Y;
1047 const f64 sz = s * axis.Z;
1048
1049 M[0] = (T)(tx * axis.X + c);
1050 M[1] = (T)(tx * axis.Y + sz);
1051 M[2] = (T)(tx * axis.Z - sy);
1052
1053 M[4] = (T)(ty * axis.X - sz);
1054 M[5] = (T)(ty * axis.Y + c);
1055 M[6] = (T)(ty * axis.Z + sx);
1056
1057 M[8] = (T)(tz * axis.X + sy);
1058 M[9] = (T)(tz * axis.Y - sx);
1059 M[10] = (T)(tz * axis.Z + c);
1060
1061#if defined ( USE_MATRIX_TEST )
1063#endif
1064 return *this;
1065 }
1066
1067
1070 template <class T>
1072 {
1073 std::fill_n(M, 16, 0);
1074 M[0] = M[5] = M[10] = M[15] = (T)1;
1075#if defined ( USE_MATRIX_TEST )
1077#endif
1078 return *this;
1079 }
1080
1081
1082 /*
1083 check identity with epsilon
1084 solve floating range problems..
1085 */
1086 template <class T>
1087 inline bool CMatrix4<T>::isIdentity() const
1088 {
1089#if defined ( USE_MATRIX_TEST )
1091 return true;
1092#endif
1093 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 ))
1094 return false;
1095
1096 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 ))
1097 return false;
1098
1099 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 ))
1100 return false;
1101
1102 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 ))
1103 return false;
1104/*
1105 if (!core::equals( M[ 0], (T)1 ) ||
1106 !core::equals( M[ 5], (T)1 ) ||
1107 !core::equals( M[10], (T)1 ) ||
1108 !core::equals( M[15], (T)1 ))
1109 return false;
1110
1111 for (s32 i=0; i<4; ++i)
1112 for (s32 j=0; j<4; ++j)
1113 if ((j != i) && (!iszero((*this)(i,j))))
1114 return false;
1115*/
1116#if defined ( USE_MATRIX_TEST )
1118#endif
1119 return true;
1120 }
1121
1122
1123 /* Check orthogonality of matrix. */
1124 template <class T>
1125 inline bool CMatrix4<T>::isOrthogonal() const
1126 {
1127 T dp=M[0] * M[4 ] + M[1] * M[5 ] + M[2 ] * M[6 ] + M[3 ] * M[7 ];
1128 if (!iszero(dp))
1129 return false;
1130 dp = M[0] * M[8 ] + M[1] * M[9 ] + M[2 ] * M[10] + M[3 ] * M[11];
1131 if (!iszero(dp))
1132 return false;
1133 dp = M[0] * M[12] + M[1] * M[13] + M[2 ] * M[14] + M[3 ] * M[15];
1134 if (!iszero(dp))
1135 return false;
1136 dp = M[4] * M[8 ] + M[5] * M[9 ] + M[6 ] * M[10] + M[7 ] * M[11];
1137 if (!iszero(dp))
1138 return false;
1139 dp = M[4] * M[12] + M[5] * M[13] + M[6 ] * M[14] + M[7 ] * M[15];
1140 if (!iszero(dp))
1141 return false;
1142 dp = M[8] * M[12] + M[9] * M[13] + M[10] * M[14] + M[11] * M[15];
1143 return (iszero(dp));
1144 }
1145
1146
1147 /*
1148 doesn't solve floating range problems..
1149 but takes care on +/- 0 on translation because we are changing it..
1150 reducing floating point branches
1151 but it needs the floats in memory..
1152 */
1153 template <class T>
1155 {
1156#if defined ( USE_MATRIX_TEST )
1158 return true;
1159#endif
1160 if(IR(M[0])!=F32_VALUE_1) return false;
1161 if(IR(M[1])!=0) return false;
1162 if(IR(M[2])!=0) return false;
1163 if(IR(M[3])!=0) return false;
1164
1165 if(IR(M[4])!=0) return false;
1166 if(IR(M[5])!=F32_VALUE_1) return false;
1167 if(IR(M[6])!=0) return false;
1168 if(IR(M[7])!=0) return false;
1169
1170 if(IR(M[8])!=0) return false;
1171 if(IR(M[9])!=0) return false;
1172 if(IR(M[10])!=F32_VALUE_1) return false;
1173 if(IR(M[11])!=0) return false;
1174
1175 if(IR(M[12])!=0) return false;
1176 if(IR(M[13])!=0) return false;
1177 if(IR(M[13])!=0) return false;
1178 if(IR(M[15])!=F32_VALUE_1) return false;
1179
1180#if defined ( USE_MATRIX_TEST )
1182#endif
1183 return true;
1184 }
1185
1186
1187 template <class T>
1189 {
1190 vector3d<T> tmp(static_cast<T>(vect.X), static_cast<T>(vect.Y), static_cast<T>(vect.Z));
1191 vect.X = static_cast<f32>(tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8]);
1192 vect.Y = static_cast<f32>(tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9]);
1193 vect.Z = static_cast<f32>(tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10]);
1194 }
1195
1197 template <class T>
1199 {
1200 out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
1201 out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
1202 out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
1203 }
1204
1206 template <class T>
1207 inline void CMatrix4<T>::rotateVect(T *out, const core::vector3df& in) const
1208 {
1209 out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
1210 out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
1211 out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
1212 }
1213
1214 template <class T>
1216 {
1217 vector3d<T> tmp(static_cast<T>(vect.X), static_cast<T>(vect.Y), static_cast<T>(vect.Z));
1218 vect.X = static_cast<f32>(tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2]);
1219 vect.Y = static_cast<f32>(tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6]);
1220 vect.Z = static_cast<f32>(tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10]);
1221 }
1222
1223 template <class T>
1225 {
1226 T vector[3];
1227
1228 vector[0] = vect.X*M[0] + vect.Y*M[4] + vect.Z*M[8] + M[12];
1229 vector[1] = vect.X*M[1] + vect.Y*M[5] + vect.Z*M[9] + M[13];
1230 vector[2] = vect.X*M[2] + vect.Y*M[6] + vect.Z*M[10] + M[14];
1231
1232 vect.X = static_cast<f32>(vector[0]);
1233 vect.Y = static_cast<f32>(vector[1]);
1234 vect.Z = static_cast<f32>(vector[2]);
1235 }
1236
1237 template <class T>
1239 {
1240 out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
1241 out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
1242 out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
1243 }
1244
1245
1246 template <class T>
1248 {
1249 out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
1250 out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
1251 out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
1252 out[3] = in.X*M[3] + in.Y*M[7] + in.Z*M[11] + M[15];
1253 }
1254
1255 template <class T>
1256 inline void CMatrix4<T>::transformVec3(T *out, const T * in) const
1257 {
1258 out[0] = in[0]*M[0] + in[1]*M[4] + in[2]*M[8] + M[12];
1259 out[1] = in[0]*M[1] + in[1]*M[5] + in[2]*M[9] + M[13];
1260 out[2] = in[0]*M[2] + in[1]*M[6] + in[2]*M[10] + M[14];
1261 }
1262
1263 template <class T>
1264 inline void CMatrix4<T>::transformVec4(T *out, const T * in) const
1265 {
1266 out[0] = in[0]*M[0] + in[1]*M[4] + in[2]*M[8] + in[3]*M[12];
1267 out[1] = in[0]*M[1] + in[1]*M[5] + in[2]*M[9] + in[3]*M[13];
1268 out[2] = in[0]*M[2] + in[1]*M[6] + in[2]*M[10] + in[3]*M[14];
1269 out[3] = in[0]*M[3] + in[1]*M[7] + in[2]*M[11] + in[3]*M[15];
1270 }
1271
1272
1274 template <class T>
1276 {
1278 // Transform the plane member point, i.e. rotate, translate and scale it.
1279 transformVect(member, plane.getMemberPoint());
1280
1281 // Transform the normal by the transposed inverse of the matrix
1282 CMatrix4<T> transposedInverse(*this, EM4CONST_INVERSE_TRANSPOSED);
1283 vector3df normal = plane.Normal;
1284 transposedInverse.rotateVect(normal);
1285 plane.setPlane(member, normal.normalize());
1286 }
1287
1289 template <class T>
1291 {
1292 out = in;
1293 transformPlane( out );
1294 }
1295
1299 template <class T>
1300 NIRT_DEPRECATED inline void CMatrix4<T>::transformBox(core::aabbox3d<f32>& box) const
1301 {
1302#if defined ( USE_MATRIX_TEST )
1303 if (isIdentity())
1304 return;
1305#endif
1306
1307 transformVect(box.MinEdge);
1308 transformVect(box.MaxEdge);
1309 box.repair();
1310 }
1311
1313 template <class T>
1315 {
1316#if defined ( USE_MATRIX_TEST )
1317 if (isIdentity())
1318 return;
1319#endif
1320
1321 const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z};
1322 const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z};
1323
1324 f32 Bmin[3];
1325 f32 Bmax[3];
1326
1327 Bmin[0] = Bmax[0] = M[12];
1328 Bmin[1] = Bmax[1] = M[13];
1329 Bmin[2] = Bmax[2] = M[14];
1330
1331 const CMatrix4<T> &m = *this;
1332
1333 for (u32 i = 0; i < 3; ++i)
1334 {
1335 for (u32 j = 0; j < 3; ++j)
1336 {
1337 const f32 a = m(j,i) * Amin[j];
1338 const f32 b = m(j,i) * Amax[j];
1339
1340 if (a < b)
1341 {
1342 Bmin[i] += a;
1343 Bmax[i] += b;
1344 }
1345 else
1346 {
1347 Bmin[i] += b;
1348 Bmax[i] += a;
1349 }
1350 }
1351 }
1352
1353 box.MinEdge.X = Bmin[0];
1354 box.MinEdge.Y = Bmin[1];
1355 box.MinEdge.Z = Bmin[2];
1356
1357 box.MaxEdge.X = Bmax[0];
1358 box.MaxEdge.Y = Bmax[1];
1359 box.MaxEdge.Z = Bmax[2];
1360 }
1361
1362
1364 template <class T>
1366 {
1367 /*
1368 0 1 2 3
1369 4 5 6 7
1370 8 9 10 11
1371 12 13 14 15
1372 */
1373
1374 T mat[4];
1375 mat[0] = matrix[0];
1376 mat[1] = matrix[1];
1377 mat[2] = matrix[2];
1378 mat[3] = matrix[3];
1379
1380 matrix[0] = M[0]*mat[0] + M[4]*mat[1] + M[8]*mat[2] + M[12]*mat[3];
1381 matrix[1] = M[1]*mat[0] + M[5]*mat[1] + M[9]*mat[2] + M[13]*mat[3];
1382 matrix[2] = M[2]*mat[0] + M[6]*mat[1] + M[10]*mat[2] + M[14]*mat[3];
1383 matrix[3] = M[3]*mat[0] + M[7]*mat[1] + M[11]*mat[2] + M[15]*mat[3];
1384 }
1385
1386 template <class T>
1388 {
1389 vect.X = vect.X-M[12];
1390 vect.Y = vect.Y-M[13];
1391 vect.Z = vect.Z-M[14];
1392 }
1393
1394 template <class T>
1396 {
1397 vect.X = vect.X+M[12];
1398 vect.Y = vect.Y+M[13];
1399 vect.Z = vect.Z+M[14];
1400 }
1401
1402
1403 template <class T>
1405 {
1409
1410#if defined ( USE_MATRIX_TEST )
1411 if ( this->isIdentity() )
1412 {
1413 out=*this;
1414 return true;
1415 }
1416#endif
1417 const CMatrix4<T> &m = *this;
1418
1419 f32 d = (m[0] * m[5] - m[1] * m[4]) * (m[10] * m[15] - m[11] * m[14]) -
1420 (m[0] * m[6] - m[2] * m[4]) * (m[9] * m[15] - m[11] * m[13]) +
1421 (m[0] * m[7] - m[3] * m[4]) * (m[9] * m[14] - m[10] * m[13]) +
1422 (m[1] * m[6] - m[2] * m[5]) * (m[8] * m[15] - m[11] * m[12]) -
1423 (m[1] * m[7] - m[3] * m[5]) * (m[8] * m[14] - m[10] * m[12]) +
1424 (m[2] * m[7] - m[3] * m[6]) * (m[8] * m[13] - m[9] * m[12]);
1425
1426 if( core::iszero ( d, FLT_MIN ) )
1427 return false;
1428
1429 d = core::reciprocal ( d );
1430
1431 out[0] = d * (m[5] * (m[10] * m[15] - m[11] * m[14]) +
1432 m[6] * (m[11] * m[13] - m[9] * m[15]) +
1433 m[7] * (m[9] * m[14] - m[10] * m[13]));
1434 out[1] = d * (m[9] * (m[2] * m[15] - m[3] * m[14]) +
1435 m[10] * (m[3] * m[13] - m[1] * m[15]) +
1436 m[11] * (m[1] * m[14] - m[2] * m[13]));
1437 out[2] = d * (m[13] * (m[2] * m[7] - m[3] * m[6]) +
1438 m[14] * (m[3] * m[5] - m[1] * m[7]) +
1439 m[15] * (m[1] * m[6] - m[2] * m[5]));
1440 out[3] = d * (m[1] * (m[7] * m[10] - m[6] * m[11]) +
1441 m[2] * (m[5] * m[11] - m[7] * m[9]) +
1442 m[3] * (m[6] * m[9] - m[5] * m[10]));
1443 out[4] = d * (m[6] * (m[8] * m[15] - m[11] * m[12]) +
1444 m[7] * (m[10] * m[12] - m[8] * m[14]) +
1445 m[4] * (m[11] * m[14] - m[10] * m[15]));
1446 out[5] = d * (m[10] * (m[0] * m[15] - m[3] * m[12]) +
1447 m[11] * (m[2] * m[12] - m[0] * m[14]) +
1448 m[8] * (m[3] * m[14] - m[2] * m[15]));
1449 out[6] = d * (m[14] * (m[0] * m[7] - m[3] * m[4]) +
1450 m[15] * (m[2] * m[4] - m[0] * m[6]) +
1451 m[12] * (m[3] * m[6] - m[2] * m[7]));
1452 out[7] = d * (m[2] * (m[7] * m[8] - m[4] * m[11]) +
1453 m[3] * (m[4] * m[10] - m[6] * m[8]) +
1454 m[0] * (m[6] * m[11] - m[7] * m[10]));
1455 out[8] = d * (m[7] * (m[8] * m[13] - m[9] * m[12]) +
1456 m[4] * (m[9] * m[15] - m[11] * m[13]) +
1457 m[5] * (m[11] * m[12] - m[8] * m[15]));
1458 out[9] = d * (m[11] * (m[0] * m[13] - m[1] * m[12]) +
1459 m[8] * (m[1] * m[15] - m[3] * m[13]) +
1460 m[9] * (m[3] * m[12] - m[0] * m[15]));
1461 out[10] = d * (m[15] * (m[0] * m[5] - m[1] * m[4]) +
1462 m[12] * (m[1] * m[7] - m[3] * m[5]) +
1463 m[13] * (m[3] * m[4] - m[0] * m[7]));
1464 out[11] = d * (m[3] * (m[5] * m[8] - m[4] * m[9]) +
1465 m[0] * (m[7] * m[9] - m[5] * m[11]) +
1466 m[1] * (m[4] * m[11] - m[7] * m[8]));
1467 out[12] = d * (m[4] * (m[10] * m[13] - m[9] * m[14]) +
1468 m[5] * (m[8] * m[14] - m[10] * m[12]) +
1469 m[6] * (m[9] * m[12] - m[8] * m[13]));
1470 out[13] = d * (m[8] * (m[2] * m[13] - m[1] * m[14]) +
1471 m[9] * (m[0] * m[14] - m[2] * m[12]) +
1472 m[10] * (m[1] * m[12] - m[0] * m[13]));
1473 out[14] = d * (m[12] * (m[2] * m[5] - m[1] * m[6]) +
1474 m[13] * (m[0] * m[6] - m[2] * m[4]) +
1475 m[14] * (m[1] * m[4] - m[0] * m[5]));
1476 out[15] = d * (m[0] * (m[5] * m[10] - m[6] * m[9]) +
1477 m[1] * (m[6] * m[8] - m[4] * m[10]) +
1478 m[2] * (m[4] * m[9] - m[5] * m[8]));
1479
1480#if defined ( USE_MATRIX_TEST )
1481 out.definitelyIdentityMatrix = definitelyIdentityMatrix;
1482#endif
1483 return true;
1484 }
1485
1486
1489 template <class T>
1491 {
1492 out.M[0 ] = M[0];
1493 out.M[1 ] = M[4];
1494 out.M[2 ] = M[8];
1495 out.M[3 ] = 0;
1496
1497 out.M[4 ] = M[1];
1498 out.M[5 ] = M[5];
1499 out.M[6 ] = M[9];
1500 out.M[7 ] = 0;
1501
1502 out.M[8 ] = M[2];
1503 out.M[9 ] = M[6];
1504 out.M[10] = M[10];
1505 out.M[11] = 0;
1506
1507 out.M[12] = (T)-(M[12]*M[0] + M[13]*M[1] + M[14]*M[2]);
1508 out.M[13] = (T)-(M[12]*M[4] + M[13]*M[5] + M[14]*M[6]);
1509 out.M[14] = (T)-(M[12]*M[8] + M[13]*M[9] + M[14]*M[10]);
1510 out.M[15] = 1;
1511
1512#if defined ( USE_MATRIX_TEST )
1513 out.definitelyIdentityMatrix = definitelyIdentityMatrix;
1514#endif
1515 return true;
1516 }
1517
1520 template <class T>
1522 {
1523#if defined ( USE_MATRIX_TEST )
1525 return true;
1526#endif
1527 CMatrix4<T> temp ( EM4CONST_NOTHING );
1528
1529 if (getInverse(temp))
1530 {
1531 *this = temp;
1532 return true;
1533 }
1534
1535 return false;
1536 }
1537
1538
1539 template <class T>
1541 {
1542 if (this==&other)
1543 return *this;
1544 std::copy_n(other.M, 16, M);
1545#if defined ( USE_MATRIX_TEST )
1546 definitelyIdentityMatrix=other.definitelyIdentityMatrix;
1547#endif
1548 return *this;
1549 }
1550
1551
1552 template <class T>
1554 {
1555 for (s32 i = 0; i < 16; ++i)
1556 M[i]=scalar;
1557
1558#if defined ( USE_MATRIX_TEST )
1560#endif
1561 return *this;
1562 }
1563
1564
1565 template <class T>
1567 {
1568#if defined ( USE_MATRIX_TEST )
1569 if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
1570 return true;
1571#endif
1572 for (s32 i = 0; i < 16; ++i)
1573 if (M[i] != other.M[i])
1574 return false;
1575
1576 return true;
1577 }
1578
1579
1580 template <class T>
1582 {
1583 return !(*this == other);
1584 }
1585
1586
1587 // Builds a right-handed perspective projection matrix based on a field of view
1588 template <class T>
1591 {
1592 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
1593 NIRT_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
1594 const T w = static_cast<T>(h / aspectRatio);
1595
1596 NIRT_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1597 M[0] = w;
1598 M[1] = 0;
1599 M[2] = 0;
1600 M[3] = 0;
1601
1602 M[4] = 0;
1603 M[5] = (T)h;
1604 M[6] = 0;
1605 M[7] = 0;
1606
1607 M[8] = 0;
1608 M[9] = 0;
1609 //M[10]
1610 M[11] = -1;
1611
1612 M[12] = 0;
1613 M[13] = 0;
1614 //M[14]
1615 M[15] = 0;
1616
1617 if ( zClipFromZero ) // DirectX version
1618 {
1619 M[10] = (T)(zFar/(zNear-zFar));
1620 M[14] = (T)(zNear*zFar/(zNear-zFar));
1621 }
1622 else // OpenGL version
1623 {
1624 M[10] = (T)((zFar+zNear)/(zNear-zFar));
1625 M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar));
1626 }
1627
1628#if defined ( USE_MATRIX_TEST )
1630#endif
1631 return *this;
1632 }
1633
1634
1635 // Builds a left-handed perspective projection matrix based on a field of view
1636 template <class T>
1639 {
1640 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
1641 NIRT_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
1642 const T w = static_cast<T>(h / aspectRatio);
1643
1644 NIRT_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1645 M[0] = w;
1646 M[1] = 0;
1647 M[2] = 0;
1648 M[3] = 0;
1649
1650 M[4] = 0;
1651 M[5] = (T)h;
1652 M[6] = 0;
1653 M[7] = 0;
1654
1655 M[8] = 0;
1656 M[9] = 0;
1657 //M[10]
1658 M[11] = 1;
1659
1660 M[12] = 0;
1661 M[13] = 0;
1662 //M[14]
1663 M[15] = 0;
1664
1665 if ( zClipFromZero ) // DirectX version
1666 {
1667 M[10] = (T)(zFar/(zFar-zNear));
1668 M[14] = (T)(-zNear*zFar/(zFar-zNear));
1669 }
1670 else // OpenGL version
1671 {
1672 M[10] = (T)((zFar+zNear)/(zFar-zNear));
1673 M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar));
1674 }
1675
1676#if defined ( USE_MATRIX_TEST )
1678#endif
1679 return *this;
1680 }
1681
1682
1683 // Builds a left-handed perspective projection matrix based on a field of view, with far plane culling at infinity
1684 template <class T>
1687 {
1688 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
1689 NIRT_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
1690 const T w = static_cast<T>(h / aspectRatio);
1691
1692 M[0] = w;
1693 M[1] = 0;
1694 M[2] = 0;
1695 M[3] = 0;
1696
1697 M[4] = 0;
1698 M[5] = (T)h;
1699 M[6] = 0;
1700 M[7] = 0;
1701
1702 M[8] = 0;
1703 M[9] = 0;
1704 M[10] = (T)(1.f-epsilon);
1705 M[11] = 1;
1706
1707 M[12] = 0;
1708 M[13] = 0;
1709 M[14] = (T)(zNear*(epsilon-1.f));
1710 M[15] = 0;
1711
1712#if defined ( USE_MATRIX_TEST )
1714#endif
1715 return *this;
1716 }
1717
1718
1719 // Builds a left-handed orthogonal projection matrix.
1720 template <class T>
1723 {
1724 NIRT_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1725 NIRT_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1726 NIRT_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1727 M[0] = (T)(2/widthOfViewVolume);
1728 M[1] = 0;
1729 M[2] = 0;
1730 M[3] = 0;
1731
1732 M[4] = 0;
1733 M[5] = (T)(2/heightOfViewVolume);
1734 M[6] = 0;
1735 M[7] = 0;
1736
1737 M[8] = 0;
1738 M[9] = 0;
1739 // M[10]
1740 M[11] = 0;
1741
1742 M[12] = 0;
1743 M[13] = 0;
1744 // M[14]
1745 M[15] = 1;
1746
1747 if ( zClipFromZero )
1748 {
1749 M[10] = (T)(1/(zFar-zNear));
1750 M[14] = (T)(zNear/(zNear-zFar));
1751 }
1752 else
1753 {
1754 M[10] = (T)(2/(zFar-zNear));
1755 M[14] = (T)-(zFar+zNear)/(zFar-zNear);
1756 }
1757
1758#if defined ( USE_MATRIX_TEST )
1760#endif
1761 return *this;
1762 }
1763
1764
1765 // Builds a right-handed orthogonal projection matrix.
1766 template <class T>
1769 {
1770 NIRT_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1771 NIRT_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1772 NIRT_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1773 M[0] = (T)(2/widthOfViewVolume);
1774 M[1] = 0;
1775 M[2] = 0;
1776 M[3] = 0;
1777
1778 M[4] = 0;
1779 M[5] = (T)(2/heightOfViewVolume);
1780 M[6] = 0;
1781 M[7] = 0;
1782
1783 M[8] = 0;
1784 M[9] = 0;
1785 // M[10]
1786 M[11] = 0;
1787
1788 M[12] = 0;
1789 M[13] = 0;
1790 // M[14]
1791 M[15] = 1;
1792
1793 if ( zClipFromZero )
1794 {
1795 M[10] = (T)(1/(zNear-zFar));
1796 M[14] = (T)(zNear/(zNear-zFar));
1797 }
1798 else
1799 {
1800 M[10] = (T)(2/(zNear-zFar));
1801 M[14] = (T)-(zFar+zNear)/(zFar-zNear);
1802 }
1803
1804#if defined ( USE_MATRIX_TEST )
1806#endif
1807 return *this;
1808 }
1809
1810
1811 // Builds a right-handed perspective projection matrix.
1812 template <class T>
1815 {
1816 NIRT_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1817 NIRT_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1818 NIRT_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1819 M[0] = (T)(2*zNear/widthOfViewVolume);
1820 M[1] = 0;
1821 M[2] = 0;
1822 M[3] = 0;
1823
1824 M[4] = 0;
1825 M[5] = (T)(2*zNear/heightOfViewVolume);
1826 M[6] = 0;
1827 M[7] = 0;
1828
1829 M[8] = 0;
1830 M[9] = 0;
1831 //M[10]
1832 M[11] = -1;
1833
1834 M[12] = 0;
1835 M[13] = 0;
1836 //M[14]
1837 M[15] = 0;
1838
1839 if ( zClipFromZero ) // DirectX version
1840 {
1841 M[10] = (T)(zFar/(zNear-zFar));
1842 M[14] = (T)(zNear*zFar/(zNear-zFar));
1843 }
1844 else // OpenGL version
1845 {
1846 M[10] = (T)((zFar+zNear)/(zNear-zFar));
1847 M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar));
1848 }
1849
1850#if defined ( USE_MATRIX_TEST )
1852#endif
1853 return *this;
1854 }
1855
1856
1857 // Builds a left-handed perspective projection matrix.
1858 template <class T>
1861 {
1862 NIRT_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1863 NIRT_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1864 NIRT_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1865 M[0] = (T)(2*zNear/widthOfViewVolume);
1866 M[1] = 0;
1867 M[2] = 0;
1868 M[3] = 0;
1869
1870 M[4] = 0;
1871 M[5] = (T)(2*zNear/heightOfViewVolume);
1872 M[6] = 0;
1873 M[7] = 0;
1874
1875 M[8] = 0;
1876 M[9] = 0;
1877 //M[10]
1878 M[11] = 1;
1879
1880 M[12] = 0;
1881 M[13] = 0;
1882 //M[14] = (T)(zNear*zFar/(zNear-zFar));
1883 M[15] = 0;
1884
1885 if ( zClipFromZero ) // DirectX version
1886 {
1887 M[10] = (T)(zFar/(zFar-zNear));
1888 M[14] = (T)(zNear*zFar/(zNear-zFar));
1889 }
1890 else // OpenGL version
1891 {
1892 M[10] = (T)((zFar+zNear)/(zFar-zNear));
1893 M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar));
1894 }
1895
1896#if defined ( USE_MATRIX_TEST )
1898#endif
1899 return *this;
1900 }
1901
1902
1903 // Builds a matrix that flattens geometry into a plane.
1904 template <class T>
1906 {
1907 plane.Normal.normalize();
1908 const f32 d = plane.Normal.dotProduct(light);
1909
1910 M[ 0] = (T)(-plane.Normal.X * light.X + d);
1911 M[ 1] = (T)(-plane.Normal.X * light.Y);
1912 M[ 2] = (T)(-plane.Normal.X * light.Z);
1913 M[ 3] = (T)(-plane.Normal.X * point);
1914
1915 M[ 4] = (T)(-plane.Normal.Y * light.X);
1916 M[ 5] = (T)(-plane.Normal.Y * light.Y + d);
1917 M[ 6] = (T)(-plane.Normal.Y * light.Z);
1918 M[ 7] = (T)(-plane.Normal.Y * point);
1919
1920 M[ 8] = (T)(-plane.Normal.Z * light.X);
1921 M[ 9] = (T)(-plane.Normal.Z * light.Y);
1922 M[10] = (T)(-plane.Normal.Z * light.Z + d);
1923 M[11] = (T)(-plane.Normal.Z * point);
1924
1925 M[12] = (T)(-plane.D * light.X);
1926 M[13] = (T)(-plane.D * light.Y);
1927 M[14] = (T)(-plane.D * light.Z);
1928 M[15] = (T)(-plane.D * point + d);
1929#if defined ( USE_MATRIX_TEST )
1931#endif
1932 return *this;
1933 }
1934
1935 // Builds a left-handed look-at matrix.
1936 template <class T>
1938 const vector3df& position,
1939 const vector3df& target,
1940 const vector3df& upVector)
1941 {
1942 vector3df zaxis = target - position;
1943 zaxis.normalize_z();
1944
1945 vector3df xaxis = normalize_y(upVector).crossProduct(zaxis);
1946 xaxis.normalize_x();
1947
1948 vector3df yaxis = zaxis.crossProduct(xaxis);
1949
1950 M[0] = (T)xaxis.X;
1951 M[1] = (T)yaxis.X;
1952 M[2] = (T)zaxis.X;
1953 M[3] = 0;
1954
1955 M[4] = (T)xaxis.Y;
1956 M[5] = (T)yaxis.Y;
1957 M[6] = (T)zaxis.Y;
1958 M[7] = 0;
1959
1960 M[8] = (T)xaxis.Z;
1961 M[9] = (T)yaxis.Z;
1962 M[10] = (T)zaxis.Z;
1963 M[11] = 0;
1964
1965 M[12] = (T)-xaxis.dotProduct(position);
1966 M[13] = (T)-yaxis.dotProduct(position);
1967 M[14] = (T)-zaxis.dotProduct(position);
1968 M[15] = 1;
1969#if defined ( USE_MATRIX_TEST )
1971#endif
1972 return *this;
1973 }
1974
1975
1976 // Builds a right-handed look-at matrix.
1977 template <class T>
1979 const vector3df& position,
1980 const vector3df& target,
1981 const vector3df& upVector)
1982 {
1983 vector3df zaxis = position - target;
1984 zaxis.normalize();
1985
1986 vector3df xaxis = upVector.crossProduct(zaxis);
1987 xaxis.normalize();
1988
1989 vector3df yaxis = zaxis.crossProduct(xaxis);
1990
1991 M[0] = (T)xaxis.X;
1992 M[1] = (T)yaxis.X;
1993 M[2] = (T)zaxis.X;
1994 M[3] = 0;
1995
1996 M[4] = (T)xaxis.Y;
1997 M[5] = (T)yaxis.Y;
1998 M[6] = (T)zaxis.Y;
1999 M[7] = 0;
2000
2001 M[8] = (T)xaxis.Z;
2002 M[9] = (T)yaxis.Z;
2003 M[10] = (T)zaxis.Z;
2004 M[11] = 0;
2005
2006 M[12] = (T)-xaxis.dotProduct(position);
2007 M[13] = (T)-yaxis.dotProduct(position);
2008 M[14] = (T)-zaxis.dotProduct(position);
2009 M[15] = 1;
2010#if defined ( USE_MATRIX_TEST )
2012#endif
2013 return *this;
2014 }
2015
2016
2017 // creates a new matrix as interpolated matrix from this and the passed one.
2018 template <class T>
2020 {
2021 CMatrix4<T> mat ( EM4CONST_NOTHING );
2022
2023 for (u32 i=0; i < 16; i += 4)
2024 {
2025 mat.M[i+0] = (T)(M[i+0] + ( b.M[i+0] - M[i+0] ) * time);
2026 mat.M[i+1] = (T)(M[i+1] + ( b.M[i+1] - M[i+1] ) * time);
2027 mat.M[i+2] = (T)(M[i+2] + ( b.M[i+2] - M[i+2] ) * time);
2028 mat.M[i+3] = (T)(M[i+3] + ( b.M[i+3] - M[i+3] ) * time);
2029 }
2030 return mat;
2031 }
2032
2033
2034 // returns transposed matrix
2035 template <class T>
2037 {
2038 CMatrix4<T> t ( EM4CONST_NOTHING );
2039 getTransposed ( t );
2040 return t;
2041 }
2042
2043
2044 // returns transposed matrix
2045 template <class T>
2047 {
2048 o[ 0] = M[ 0];
2049 o[ 1] = M[ 4];
2050 o[ 2] = M[ 8];
2051 o[ 3] = M[12];
2052
2053 o[ 4] = M[ 1];
2054 o[ 5] = M[ 5];
2055 o[ 6] = M[ 9];
2056 o[ 7] = M[13];
2057
2058 o[ 8] = M[ 2];
2059 o[ 9] = M[ 6];
2060 o[10] = M[10];
2061 o[11] = M[14];
2062
2063 o[12] = M[ 3];
2064 o[13] = M[ 7];
2065 o[14] = M[11];
2066 o[15] = M[15];
2067#if defined ( USE_MATRIX_TEST )
2068 o.definitelyIdentityMatrix=definitelyIdentityMatrix;
2069#endif
2070 }
2071
2072
2073 // used to scale <-1,-1><1,1> to viewport
2074 template <class T>
2076 {
2077 const f32 scaleX = (viewport.getWidth() - 0.75f ) * 0.5f;
2078 const f32 scaleY = -(viewport.getHeight() - 0.75f ) * 0.5f;
2079
2080 const f32 dx = -0.5f + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) * 0.5f );
2081 const f32 dy = -0.5f + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) * 0.5f );
2082
2083 makeIdentity();
2084 M[12] = (T)dx;
2085 M[13] = (T)dy;
2086 return setScale(core::vector3d<T>((T)scaleX, (T)scaleY, (T)zScale));
2087 }
2088
2090
2095 template <class T>
2097 {
2098 // unit vectors
2101 f.normalize();
2102 t.normalize();
2103
2104 // axis multiplication by sin
2105 core::vector3df vs(t.crossProduct(f));
2106
2107 // axis of rotation
2109 v.normalize();
2110
2111 // cosinus angle
2112 T ca = f.dotProduct(t);
2113
2114 core::vector3df vt(v * (1 - ca));
2115
2116 M[0] = vt.X * v.X + ca;
2117 M[5] = vt.Y * v.Y + ca;
2118 M[10] = vt.Z * v.Z + ca;
2119
2120 vt.X *= v.Y;
2121 vt.Z *= v.X;
2122 vt.Y *= v.Z;
2123
2124 M[1] = vt.X - vs.Z;
2125 M[2] = vt.Z + vs.Y;
2126 M[3] = 0;
2127
2128 M[4] = vt.X + vs.Z;
2129 M[6] = vt.Y - vs.X;
2130 M[7] = 0;
2131
2132 M[8] = vt.Z - vs.Y;
2133 M[9] = vt.Y + vs.X;
2134 M[11] = 0;
2135
2136 M[12] = 0;
2137 M[13] = 0;
2138 M[14] = 0;
2139 M[15] = 1;
2140
2141 return *this;
2142 }
2143
2145
2151 template <class T>
2153 const core::vector3df& camPos,
2154 const core::vector3df& center,
2156 const core::vector3df& axis,
2157 const core::vector3df& from)
2158 {
2159 // axis of rotation
2161 up.normalize();
2162 const core::vector3df forward = (camPos - center).normalize();
2163 const core::vector3df right = up.crossProduct(forward).normalize();
2164
2165 // correct look vector
2166 const core::vector3df look = right.crossProduct(up);
2167
2168 // rotate from to
2169 // axis multiplication by sin
2170 const core::vector3df vs = look.crossProduct(from);
2171
2172 // cosinus angle
2173 const f32 ca = from.dotProduct(look);
2174
2175 core::vector3df vt(up * (1.f - ca));
2176
2177 M[0] = static_cast<T>(vt.X * up.X + ca);
2178 M[5] = static_cast<T>(vt.Y * up.Y + ca);
2179 M[10] = static_cast<T>(vt.Z * up.Z + ca);
2180
2181 vt.X *= up.Y;
2182 vt.Z *= up.X;
2183 vt.Y *= up.Z;
2184
2185 M[1] = static_cast<T>(vt.X - vs.Z);
2186 M[2] = static_cast<T>(vt.Z + vs.Y);
2187 M[3] = 0;
2188
2189 M[4] = static_cast<T>(vt.X + vs.Z);
2190 M[6] = static_cast<T>(vt.Y - vs.X);
2191 M[7] = 0;
2192
2193 M[8] = static_cast<T>(vt.Z - vs.Y);
2194 M[9] = static_cast<T>(vt.Y + vs.X);
2195 M[11] = 0;
2196
2197 setRotationCenter(center, translation);
2198 }
2199
2200
2202 template <class T>
2204 {
2205 M[12] = -M[0]*center.X - M[4]*center.Y - M[8]*center.Z + (center.X - translation.X );
2206 M[13] = -M[1]*center.X - M[5]*center.Y - M[9]*center.Z + (center.Y - translation.Y );
2207 M[14] = -M[2]*center.X - M[6]*center.Y - M[10]*center.Z + (center.Z - translation.Z );
2208 M[15] = (T) 1.0;
2209#if defined ( USE_MATRIX_TEST )
2211#endif
2212 }
2213
2226 template <class T>
2230 const core::vector2df &scale)
2231 {
2232 const f32 c = cosf(rotateRad);
2233 const f32 s = sinf(rotateRad);
2234
2235 M[0] = (T)(c * scale.X);
2236 M[1] = (T)(s * scale.Y);
2237 M[2] = 0;
2238 M[3] = 0;
2239
2240 M[4] = (T)(-s * scale.X);
2241 M[5] = (T)(c * scale.Y);
2242 M[6] = 0;
2243 M[7] = 0;
2244
2245 M[8] = (T)(c * scale.X * rotatecenter.X + -s * rotatecenter.Y + translate.X);
2246 M[9] = (T)(s * scale.Y * rotatecenter.X + c * rotatecenter.Y + translate.Y);
2247 M[10] = 1;
2248 M[11] = 0;
2249
2250 M[12] = 0;
2251 M[13] = 0;
2252 M[14] = 0;
2253 M[15] = 1;
2254#if defined ( USE_MATRIX_TEST )
2256#endif
2257 return *this;
2258 }
2259
2260
2261 // rotate about z axis, center ( 0.5, 0.5 )
2262 template <class T>
2264 {
2265 const f32 c = cosf(rotateRad);
2266 const f32 s = sinf(rotateRad);
2267 M[0] = (T)c;
2268 M[1] = (T)s;
2269
2270 M[4] = (T)-s;
2271 M[5] = (T)c;
2272
2273 M[8] = (T)(0.5f * ( s - c) + 0.5f);
2274 M[9] = (T)(-0.5f * ( s + c) + 0.5f);
2275
2276#if defined ( USE_MATRIX_TEST )
2278#endif
2279 return *this;
2280 }
2281
2282
2283 template <class T>
2285 {
2286 M[8] = (T)x;
2287 M[9] = (T)y;
2288
2289#if defined ( USE_MATRIX_TEST )
2290 definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f);
2291#endif
2292 return *this;
2293 }
2294
2295 template <class T>
2296 inline void CMatrix4<T>::getTextureTranslate(f32& x, f32& y) const
2297 {
2298 x = (f32)M[8];
2299 y = (f32)M[9];
2300 }
2301
2302 template <class T>
2304 {
2305 M[2] = (T)x;
2306 M[6] = (T)y;
2307
2308#if defined ( USE_MATRIX_TEST )
2309 definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f);
2310#endif
2311 return *this;
2312 }
2313
2314 template <class T>
2316 {
2317 M[0] = (T)sx;
2318 M[5] = (T)sy;
2319#if defined ( USE_MATRIX_TEST )
2321#endif
2322 return *this;
2323 }
2324
2325 template <class T>
2326 inline void CMatrix4<T>::getTextureScale ( f32& sx, f32& sy ) const
2327 {
2328 sx = (f32)M[0];
2329 sy = (f32)M[5];
2330 }
2331
2332 template <class T>
2334 {
2335 M[0] = (T)sx;
2336 M[5] = (T)sy;
2337 M[8] = (T)(0.5f - 0.5f * sx);
2338 M[9] = (T)(0.5f - 0.5f * sy);
2339
2340#if defined ( USE_MATRIX_TEST )
2342#endif
2343 return *this;
2344 }
2345
2346
2347 // sets all matrix data members at once
2348 template <class T>
2349 inline CMatrix4<T>& CMatrix4<T>::setM(const T* data)
2350 {
2351 std::copy_n(data, 16, M);
2352
2353#if defined ( USE_MATRIX_TEST )
2355#endif
2356 return *this;
2357 }
2358
2359
2360 // sets if the matrix is definitely identity matrix
2361 template <class T>
2363 {
2364#if defined ( USE_MATRIX_TEST )
2366#else
2367 (void)isDefinitelyIdentityMatrix; // prevent compiler warning
2368#endif
2369 }
2370
2371
2372 // gets if the matrix is definitely identity matrix
2373 template <class T>
2375 {
2376#if defined ( USE_MATRIX_TEST )
2378#else
2379 return false;
2380#endif
2381 }
2382
2383
2385 template <class T>
2386 inline bool CMatrix4<T>::equals(const core::CMatrix4<T>& other, const T tolerance) const
2387 {
2388#if defined ( USE_MATRIX_TEST )
2389 if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
2390 return true;
2391#endif
2392 for (s32 i = 0; i < 16; ++i)
2393 if (!core::equals(M[i],other.M[i], tolerance))
2394 return false;
2395
2396 return true;
2397 }
2398
2399
2400 // Multiply by scalar.
2401 template <class T>
2402 inline CMatrix4<T> operator*(const T scalar, const CMatrix4<T>& mat)
2403 {
2404 return mat*scalar;
2405 }
2406
2407
2410
2412 NIRTCPP_API extern const matrix4 IdentityMatrix;
2413
2414} // end namespace core
2415} // end namespace nirt
2416
2417#endif
2418
4x4 matrix. Mostly used as transformation matrix for 3d calculations.
Definition matrix4.hpp:49
CMatrix4< T > & operator+=(const CMatrix4< T > &other)
Add another matrix.
Definition matrix4.hpp:572
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.hpp:2203
vector3d< T > getTranslation() const
Gets the current translation.
Definition matrix4.hpp:814
CMatrix4< T > & setInverseRotationDegrees(const vector3d< T > &rotation)
Make an inverted rotation matrix from Euler angles.
Definition matrix4.hpp:887
CMatrix4< T > & setTranslation(const vector3d< T > &translation)
Set the translation of the current matrix. Will erase any previous values.
Definition matrix4.hpp:821
bool operator!=(const CMatrix4< T > &other) const
Returns true if other matrix is not equal to this matrix.
Definition matrix4.hpp:1581
CMatrix4< T > getTransposed() const
Gets transposed matrix.
Definition matrix4.hpp:2036
CMatrix4< T > & setInverseTranslation(const vector3d< T > &translation)
Set the inverse translation of the current matrix. Will erase any previous values.
Definition matrix4.hpp:833
void setDefinitelyIdentityMatrix(bool isDefinitelyIdentityMatrix)
Sets if the matrix is definitely identity matrix.
Definition matrix4.hpp:2362
void rotateVect(vector3df &vect) const
Transform (rotate/scale) a vector by the rotation part of this matrix.
Definition matrix4.hpp:1188
bool getInversePrimitive(CMatrix4< T > &out) const
Inverts a primitive matrix which only contains a translation and a rotation.
Definition matrix4.hpp:1490
CMatrix4< T > & buildCameraLookAtMatrixRH(const vector3df &position, const vector3df &target, const vector3df &upVector)
Builds a right-handed look-at matrix.
Definition matrix4.hpp:1978
void transformPlane(core::plane3d< f32 > &plane) const
Transforms a plane by this matrix.
Definition matrix4.hpp:1275
bool getInverse(CMatrix4< T > &out) const
Gets the inverse matrix of this one.
Definition matrix4.hpp:1404
CMatrix4< T > & setM(const T *data)
Sets all matrix data members at once.
Definition matrix4.hpp:2349
CMatrix4< T > & buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar, bool zClipFromZero=true)
Builds a right-handed perspective projection matrix.
Definition matrix4.hpp:1813
bool getDefinitelyIdentityMatrix() const
Gets if the matrix is definitely identity matrix.
Definition matrix4.hpp:2374
void translateVect(vector3df &vect) const
Translate a vector by the translation part of this matrix.
Definition matrix4.hpp:1395
bool operator==(const CMatrix4< T > &other) const
Returns true if other matrix is equal to this matrix.
Definition matrix4.hpp:1566
void transformBoxEx(core::aabbox3d< f32 > &box) const
Transforms a axis aligned bounding box.
Definition matrix4.hpp:1314
CMatrix4< T > & operator*=(const CMatrix4< T > &other)
Multiply by another matrix.
Definition matrix4.hpp:696
CMatrix4< T > & buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar, bool zClipFromZero=true)
Builds a right-handed perspective projection matrix based on a field of view.
Definition matrix4.hpp:1589
CMatrix4< T > & setScale(const T scale)
Set Scale.
Definition matrix4.hpp:244
void inverseRotateVect(vector3df &vect) const
Tranform (rotate/scale) a vector by the inverse of the rotation part this matrix.
Definition matrix4.hpp:1215
void transformVect(vector3df &vect) const
Transforms the vector by this matrix.
Definition matrix4.hpp:1224
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.hpp:1256
CMatrix4< T > & setTextureTranslateTransposed(f32 x, f32 y)
Set texture transformation translation, using a transposed representation.
Definition matrix4.hpp:2303
CMatrix4< T > & operator=(const CMatrix4< T > &other)
Sets this matrix equal to the other matrix.
Definition matrix4.hpp:1540
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.hpp:2152
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.hpp:723
core::vector3d< T > getScale() const
Get Scale.
Definition matrix4.hpp:863
CMatrix4< T > operator+(const CMatrix4< T > &other) const
Add another matrix.
Definition matrix4.hpp:546
CMatrix4< T > & setbyproduct(const CMatrix4< T > &other_a, const CMatrix4< T > &other_b)
set this matrix to the product of two matrices
Definition matrix4.hpp:758
CMatrix4< T > & setTextureScale(f32 sx, f32 sy)
Set texture transformation scale.
Definition matrix4.hpp:2315
CMatrix4< T > & buildRotateFromTo(const core::vector3df &from, const core::vector3df &to)
Builds a matrix that rotates from one vector to another.
Definition matrix4.hpp:2096
CMatrix4< T > & setInverseRotationRadians(const vector3d< T > &rotation)
Make an inverted rotation matrix from Euler angles.
Definition matrix4.hpp:1004
CMatrix4< T > & makeIdentity()
Set matrix to identity.
Definition matrix4.hpp:1071
bool makeInverse()
Calculates inverse of matrix. Slow.
Definition matrix4.hpp:1521
void multiplyWith1x4Matrix(T *matrix) const
Multiplies this matrix by a 1x4 matrix.
Definition matrix4.hpp:1365
CMatrix4< T > & setRotationRadians(const vector3d< T > &rotation)
Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
Definition matrix4.hpp:893
bool equals(const core::CMatrix4< T > &other, const T tolerance=(T) ROUNDING_ERROR_f64) const
Compare two matrices using the equal method.
Definition matrix4.hpp:2386
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.hpp:2227
void transformBox(core::aabbox3d< f32 > &box) const
Transforms a axis aligned bounding box.
Definition matrix4.hpp:1300
CMatrix4< T > & buildNDCToDCMatrix(const core::rect< s32 > &area, f32 zScale)
Builds a matrix which transforms a normalized Device Coordinate to Device Coordinates.
Definition matrix4.hpp:2075
CMatrix4< T > & setRotationDegrees(const vector3d< T > &rotation)
Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
Definition matrix4.hpp:881
T & operator[](u32 index)
Simple operator for linearly accessing every element of the matrix.
Definition matrix4.hpp:97
CMatrix4< T > & buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar, bool zClipFromZero=true)
Builds a left-handed perspective projection matrix based on a field of view.
Definition matrix4.hpp:1637
bool isIdentity_integer_base() const
Returns true if the matrix is the identity matrix.
Definition matrix4.hpp:1154
void transformVec4(T *out, const T *in) const
An alternate transform vector method, reading from and writing to an array of 4 floats.
Definition matrix4.hpp:1264
bool isOrthogonal() const
Returns true if the matrix is orthogonal.
Definition matrix4.hpp:1125
CMatrix4< T > & buildCameraLookAtMatrixLH(const vector3df &position, const vector3df &target, const vector3df &upVector)
Builds a left-handed look-at matrix.
Definition matrix4.hpp:1937
const T * pointer() const
Returns pointer to internal array.
Definition matrix4.hpp:128
T & operator()(const s32 row, const s32 col)
Simple operator for directly accessing every element of the matrix.
Definition matrix4.hpp:85
CMatrix4< T > & buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar, bool zClipFromZero=true)
Builds a left-handed perspective projection matrix.
Definition matrix4.hpp:1859
void getTextureScale(f32 &sx, f32 &sy) const
Get texture transformation scale.
Definition matrix4.hpp:2326
CMatrix4< T > & setRotationAxisRadians(const T &angle, const vector3d< T > &axis)
Make a rotation matrix from angle and axis, assuming left handed rotation.
Definition matrix4.hpp:1035
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.hpp:1685
const T & operator()(const s32 row, const s32 col) const
Simple operator for directly accessing every element of the matrix.
Definition matrix4.hpp:94
CMatrix4< T > & setScale(const vector3d< T > &scale)
Set Scale.
Definition matrix4.hpp:845
CMatrix4< T > operator-(const CMatrix4< T > &other) const
Subtract another matrix.
Definition matrix4.hpp:596
void getTextureTranslate(f32 &x, f32 &y) const
Get texture transformation translation.
Definition matrix4.hpp:2296
void inverseTranslateVect(vector3df &vect) const
Translate a vector by the inverse of the translation part of this matrix.
Definition matrix4.hpp:1387
const T & operator[](u32 index) const
Simple operator for linearly accessing every element of the matrix.
Definition matrix4.hpp:106
CMatrix4< T > & setTextureScaleCenter(f32 sx, f32 sy)
Set texture transformation scale, and recenter at (0.5,0.5)
Definition matrix4.hpp:2333
CMatrix4< T > operator*(const CMatrix4< T > &other) const
Multiply by another matrix.
Definition matrix4.hpp:775
CMatrix4< T > interpolate(const core::CMatrix4< T > &b, f32 time) const
Creates a new matrix as interpolated matrix from two other ones.
Definition matrix4.hpp:2019
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.hpp:1905
CMatrix4< T > & operator-=(const CMatrix4< T > &other)
Subtract another matrix.
Definition matrix4.hpp:622
CMatrix4< T > & setTextureRotationCenter(f32 radAngle)
Set texture transformation rotation.
Definition matrix4.hpp:2263
bool isIdentity() const
Returns true if the matrix is the identity matrix.
Definition matrix4.hpp:1087
CMatrix4< T > & buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar, bool zClipFromZero=true)
Builds a left-handed orthogonal projection matrix.
Definition matrix4.hpp:1721
CMatrix4< T > & buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar, bool zClipFromZero=true)
Builds a right-handed orthogonal projection matrix.
Definition matrix4.hpp:1767
eConstructor
Constructor Flags.
Definition matrix4.hpp:54
CMatrix4(eConstructor constructor=EM4CONST_IDENTITY)
Default constructor.
Definition matrix4.hpp:487
core::vector3d< T > getRotationDegrees() const
Returns the rotation, as set by setRotation().
Definition matrix4.hpp:969
CMatrix4(const T &r0c0, const T &r0c1, const T &r0c2, const T &r0c3, const T &r1c0, const T &r1c1, const T &r1c2, const T &r1c3, const T &r2c0, const T &r2c1, const T &r2c2, const T &r2c3, const T &r3c0, const T &r3c1, const T &r3c2, const T &r3c3)
Constructor with value initialization.
Definition matrix4.hpp:68
CMatrix4< T > & setTextureTranslate(f32 x, f32 y)
Set texture transformation translation.
Definition matrix4.hpp:2284
Axis aligned bounding box in 3d dimensional space.
Definition aabbox3d.hpp:22
vector3d< T > MinEdge
The near edge.
Definition aabbox3d.hpp:354
vector3d< T > MaxEdge
The far edge.
Definition aabbox3d.hpp:357
void repair()
Repairs the box.
Definition aabbox3d.hpp:180
aabbox3d()
Default Constructor.
Definition aabbox3d.hpp:26
T Y
Y coordinate of vector.
Definition vector2d.hpp:395
T X
X coordinate of vector.
Definition vector2d.hpp:392
T Y
Y coordinate of the vector.
Definition vector3d.hpp:453
T X
X coordinate of the vector.
Definition vector3d.hpp:450
vector3d< T > & normalize()
Normalizes the vector.
Definition vector3d.hpp:178
T Z
Z coordinate of the vector.
Definition vector3d.hpp:456
const f64 RADTODEG64
64bit constant for converting from radians to degrees
Definition irrMath.hpp:81
vector3d< T > operator*(const S scalar, const vector3d< T > &vector)
Function multiplying a scalar and a vector component-wise.
Definition vector3d.hpp:494
bool iszero(const f64 a, const f64 tolerance=ROUNDING_ERROR_f64)
returns if a equals zero, taking rounding errors into account
Definition irrMath.hpp:304
const f32 DEGTORAD
32bit Constant for converting from degrees to radians
Definition irrMath.hpp:72
const T clamp(const T &value, const T &low, const T &high)
clamps a value between low and high
Definition irrMath.hpp:164
u32 IR(f32 x)
Definition irrMath.hpp:387
bool equals(const T a, const T b, const T tolerance=roundingError< T >())
returns if a equals b, taking possible rounding errors into account
Definition irrMath.hpp:243
NIRTCPP_API const matrix4 IdentityMatrix
global const identity matrix
As of Nirtcpp 1.6, position2d is a synonym for vector2d.
Definition vector3d.hpp:11
signed int s32
32 bit signed variable.
Definition irrTypes.hpp:72
unsigned int u32
32 bit unsigned variable.
Definition irrTypes.hpp:64
double f64
64 bit floating point variable.
Definition irrTypes.hpp:114
float f32
32 bit floating point variable.
Definition irrTypes.hpp:110

Nirtcpp    @cppfx.xyz

Utxcpp    utx::print