MDL SDK API nvidia_logo_transpbg.gif Up
matrix.h
Go to the documentation of this file.
1/***************************************************************************************************
2 * Copyright 2025 NVIDIA Corporation. All rights reserved.
3 **************************************************************************************************/
9
10#ifndef MI_MATH_MATRIX_H
11#define MI_MATH_MATRIX_H
12
13#include <mi/base/types.h>
14#include <mi/math/assert.h>
15#include <mi/math/function.h>
16#include <mi/math/vector.h>
17
18namespace mi {
19
20namespace math {
21
48//------- POD struct that provides storage for matrix elements --------
49
88template <typename T, Size ROW, Size COL>
90{
91 T elements[ROW*COL];
92};
93
95template <typename T> struct Matrix_struct<T,1,1>
96{
97 T xx;
98};
99
101template <typename T> struct Matrix_struct<T,2,1>
102{
103 T xx;
104 T yx;
105};
106
108template <typename T> struct Matrix_struct<T,3,1>
109{
110 T xx;
111 T yx;
112 T zx;
113};
114
116template <typename T> struct Matrix_struct<T,4,1>
117{
118 T xx;
119 T yx;
120 T zx;
121 T wx;
122};
123
125template <typename T> struct Matrix_struct<T,1,2>
126{
127 T xx;
128 T xy;
129};
130
132template <typename T> struct Matrix_struct<T,2,2>
133{
134 T xx;
135 T xy;
136 T yx;
137 T yy;
138};
139
141template <typename T> struct Matrix_struct<T,3,2>
142{
143 T xx;
144 T xy;
145 T yx;
146 T yy;
147 T zx;
148 T zy;
149};
150
152template <typename T> struct Matrix_struct<T,4,2>
153{
154 T xx;
155 T xy;
156 T yx;
157 T yy;
158 T zx;
159 T zy;
160 T wx;
161 T wy;
162};
163
165template <typename T> struct Matrix_struct<T,1,3>
166{
167 T xx;
168 T xy;
169 T xz;
170};
171
173template <typename T> struct Matrix_struct<T,2,3>
174{
175 T xx;
176 T xy;
177 T xz;
178 T yx;
179 T yy;
180 T yz;
181};
182
184template <typename T> struct Matrix_struct<T,3,3>
185{
186 T xx;
187 T xy;
188 T xz;
189 T yx;
190 T yy;
191 T yz;
192 T zx;
193 T zy;
194 T zz;
195};
196
198template <typename T> struct Matrix_struct<T,4,3>
199{
200 T xx;
201 T xy;
202 T xz;
203 T yx;
204 T yy;
205 T yz;
206 T zx;
207 T zy;
208 T zz;
209 T wx;
210 T wy;
211 T wz;
212};
213
215template <typename T> struct Matrix_struct<T,1,4>
216{
217 T xx;
218 T xy;
219 T xz;
220 T xw;
221};
222
224template <typename T> struct Matrix_struct<T,2,4>
225{
226 T xx;
227 T xy;
228 T xz;
229 T xw;
230 T yx;
231 T yy;
232 T yz;
233 T yw;
234};
235
237template <typename T> struct Matrix_struct<T,3,4>
238{
239 T xx;
240 T xy;
241 T xz;
242 T xw;
243 T yx;
244 T yy;
245 T yz;
246 T yw;
247 T zx;
248 T zy;
249 T zz;
250 T zw;
251};
252
254template <typename T> struct Matrix_struct<T,4,4>
255{
256 T xx;
257 T xy;
258 T xz;
259 T xw;
260 T yx;
261 T yy;
262 T yz;
263 T yw;
264 T zx;
265 T zy;
266 T zz;
267 T zw;
268 T wx;
269 T wy;
270 T wz;
271 T ww;
272};
273
274//------ Indirect access to matrix storage base ptr to keep Matrix_struct a POD --
275
276// Helper class to determine the matrix struct base pointer of the generic
277// #Matrix_struct (\c specialized==\c false).
278template <typename T, class Matrix, bool specialized>
279struct Matrix_struct_get_base_pointer
280{
281 static inline T* get_base_ptr( Matrix& m) { return m.elements; }
282 static inline const T* get_base_ptr( const Matrix& m) { return m.elements; }
283};
284
285// Specialization of helper class to determine the matrix struct base pointer
286// of a specialized #Matrix_struct (\c specialized==\c true).
287template <typename T, class Matrix>
288struct Matrix_struct_get_base_pointer<T,Matrix,true>
289{
290 static inline T* get_base_ptr( Matrix& m) { return &m.xx; }
291 static inline const T* get_base_ptr( const Matrix& m) { return &m.xx; }
292};
293
294
296template <typename T, Size ROW, Size COL>
298{
299 return Matrix_struct_get_base_pointer<T,Matrix_struct<T,ROW,COL>,
300 (ROW<=4 && COL<=4)>::get_base_ptr( mat);
301}
302
304template <typename T, Size ROW, Size COL>
305inline const T* matrix_base_ptr( const Matrix_struct<T,ROW,COL>& mat)
306{
307 return Matrix_struct_get_base_pointer<T,Matrix_struct<T,ROW,COL>,
308 (ROW<=4 && COL<=4)>::get_base_ptr( mat);
309}
310 // end group mi_math_matrix_struct
312
313
365template <typename T, Size ROW, Size COL>
366class Matrix : public Matrix_struct<T,ROW,COL> //-V690 PVS
367{
368public:
371
372 using value_type = T;
373 using size_type = Size;
375 using pointer = T*;
376 using const_pointer = const T*;
377 using reference = T&;
378 using const_reference = const T&;
379
382
385
386 static constexpr Size ROWS = ROW;
387 static constexpr Size COLUMNS = COL;
388 static constexpr Size SIZE = ROW*COL;
389
391 static constexpr inline Size size() { return SIZE; }
392
394 static constexpr inline Size max_size() { return SIZE; }
395
402 };
403
405 inline T * begin() { return matrix_base_ptr( *this); }
406
408 inline T const * begin() const { return matrix_base_ptr( *this); }
409
413 inline T * end() { return begin() + SIZE; }
414
418 inline T const * end() const { return begin() + SIZE; }
419
422 {
423 mi_math_assert_msg( row < ROW, "precondition");
424 return reinterpret_cast<Row_vector&>(begin()[row * COL]);
425 }
426
428 inline const Row_vector & operator[](Size row) const
429 {
430 mi_math_assert_msg( row < ROW, "precondition");
431 return reinterpret_cast<const Row_vector&>(begin()[row * COL]);
432 }
433
435 constexpr inline Matrix() = default;
436
438 Matrix( const Matrix<T,ROW,COL>& other ) = default;
439
441 inline Matrix( const Matrix_struct<T,ROW,COL>& other)
442 {
443 for( Size i(0u); i < SIZE; ++i)
444 begin()[i] = matrix_base_ptr( other)[i];
445 }
446
450 explicit inline Matrix( T diag)
451 {
452 for( Size i(0u); i < SIZE; ++i)
453 begin()[i] = T(0);
454 constexpr Size MIN_DIM = (ROW < COL) ? ROW : COL;
455 for( Size k(0u); k < MIN_DIM; ++k)
456 begin()[k * COL + k] = diag;
457 }
458
472 template <typename Iterator>
473 inline Matrix( From_iterator_tag, Iterator p)
474 {
475 for( Size i(0u); i < SIZE; ++i, ++p)
476 begin()[i] = *p;
477 }
478
491 template <typename T2>
492 inline explicit Matrix( T2 const (& array)[SIZE])
493 {
494 for( Size i(0u); i < SIZE; ++i)
495 begin()[i] = array[i];
496 }
497
500 template <typename T2>
501 inline explicit Matrix( const Matrix<T2,ROW,COL>& other)
502 {
503 for( Size i(0u); i < SIZE; ++i)
504 begin()[i] = T(other.begin()[i]);
505 }
506
509 template <typename T2>
510 inline explicit Matrix( const Matrix_struct<T2,ROW,COL>& other)
511 {
512 for( Size i(0u); i < SIZE; ++i)
513 begin()[i] = T(matrix_base_ptr( other)[i]);
514 }
515
517 inline Matrix(
519 const Matrix<T,COL,ROW>& other)
520 {
521 for( Size i(0u); i < ROW; ++i)
522 for( Size j(0u); j < COL; ++j)
523 begin()[i * COL + j] = other.begin()[j * ROW + i];
524 }
525
529 template <typename T2>
530 inline Matrix(
532 const Matrix<T2,COL,ROW>& other)
533 {
534 for( Size i(0u); i < ROW; ++i)
535 for( Size j(0u); j < COL; ++j)
536 begin()[i * COL + j] = T(other.begin()[j * ROW + i]);
537 }
538
543 inline explicit Matrix(
544 const Row_vector& v0)
545 {
546 mi_static_assert( ROW == 1);
547 (*this)[0] = v0;
548 }
549
554 inline Matrix(
555 const Row_vector& v0,
556 const Row_vector& v1)
557 {
558 mi_static_assert( ROW == 2);
559 (*this)[0] = v0;
560 (*this)[1] = v1;
561 }
562
567 inline Matrix(
568 const Row_vector& v0,
569 const Row_vector& v1,
570 const Row_vector& v2)
571 {
572 mi_static_assert( ROW == 3);
573 (*this)[0] = v0;
574 (*this)[1] = v1;
575 (*this)[2] = v2;
576 }
577
582 inline Matrix(
583 const Row_vector& v0,
584 const Row_vector& v1,
585 const Row_vector& v2,
586 const Row_vector& v3)
587 {
588 mi_static_assert( ROW == 4);
589 (*this)[0] = v0;
590 (*this)[1] = v1;
591 (*this)[2] = v2;
592 (*this)[3] = v3;
593 }
594
598 inline Matrix( T m0, T m1)
599 {
600 mi_static_assert( SIZE == 2);
601 begin()[0] = m0; begin()[1] = m1;
602 }
603
607 inline Matrix( T m0, T m1, T m2)
608 {
609 mi_static_assert( SIZE == 3);
610 begin()[0] = m0; begin()[1] = m1; begin()[2] = m2;
611 }
612
616 inline Matrix( T m0, T m1, T m2, T m3)
617 {
618 mi_static_assert( SIZE == 4);
619 begin()[0] = m0; begin()[1] = m1; begin()[2] = m2; begin()[3] = m3;
620 }
621
625 inline Matrix( T m0, T m1, T m2, T m3, T m4, T m5)
626 {
627 mi_static_assert( SIZE == 6);
628 begin()[0] = m0; begin()[1] = m1; begin()[2] = m2; begin()[3] = m3;
629 begin()[4] = m4; begin()[5] = m5;
630 }
631
635 inline Matrix( T m0, T m1, T m2, T m3, T m4, T m5, T m6, T m7)
636 {
637 mi_static_assert( SIZE == 8);
638 begin()[0] = m0; begin()[1] = m1; begin()[2] = m2; begin()[3] = m3;
639 begin()[4] = m4; begin()[5] = m5; begin()[6] = m6; begin()[7] = m7;
640 }
641
645 inline Matrix( T m0, T m1, T m2, T m3, T m4, T m5, T m6, T m7, T m8)
646 {
647 mi_static_assert( SIZE == 9);
648 begin()[0] = m0; begin()[1] = m1; begin()[2] = m2; begin()[3] = m3;
649 begin()[4] = m4; begin()[5] = m5; begin()[6] = m6; begin()[7] = m7;
650 begin()[8] = m8;
651 }
652
656 inline Matrix(
657 T m0, T m1, T m2, T m3,
658 T m4, T m5, T m6, T m7,
659 T m8, T m9, T m10, T m11)
660 {
661 mi_static_assert( SIZE == 12);
662 begin()[0] = m0; begin()[1] = m1; begin()[2] = m2; begin()[3] = m3;
663 begin()[4] = m4; begin()[5] = m5; begin()[6] = m6; begin()[7] = m7;
664 begin()[8] = m8; begin()[9] = m9; begin()[10] = m10; begin()[11] = m11;
665 }
666
670 inline Matrix(
671 T m0, T m1, T m2, T m3,
672 T m4, T m5, T m6, T m7,
673 T m8, T m9, T m10, T m11,
674 T m12, T m13, T m14, T m15)
675 {
676 mi_static_assert( SIZE == 16);
677 begin()[0] = m0; begin()[1] = m1; begin()[2] = m2; begin()[3] = m3;
678 begin()[4] = m4; begin()[5] = m5; begin()[6] = m6; begin()[7] = m7;
679 begin()[8] = m8; begin()[9] = m9; begin()[10] = m10; begin()[11] = m11;
680 begin()[12] = m12; begin()[13] = m13; begin()[14] = m14; begin()[15] = m15;
681 }
682
684 inline Matrix& operator=( const Matrix& other)
685 {
687 return *this;
688 }
689
693 inline T& operator()( Size row, Size col)
694 {
695 mi_math_assert_msg( row < ROW, "precondition");
696 mi_math_assert_msg( col < COL, "precondition");
697 return begin()[row * COL + col];
698 }
699
703 inline const T& operator()( Size row, Size col) const
704 {
705 mi_math_assert_msg( row < ROW, "precondition");
706 mi_math_assert_msg( col < COL, "precondition");
707 return begin()[row * COL + col];
708 }
709
713 inline T get( Size i) const
714 {
715 mi_math_assert_msg( i < ROW*COL, "precondition");
716 return begin()[i];
717 }
718
722 inline T get( Size row, Size col) const
723 {
724 mi_math_assert_msg( row < ROW, "precondition");
725 mi_math_assert_msg( col < COL, "precondition");
726 return begin()[row * COL + col];
727 }
728
733 inline void set( Size i, T value)
734 {
735 mi_math_assert_msg( i < ROW*COL, "precondition");
736 begin()[i] = value;
737 }
738
743 inline void set( Size row, Size col, T value)
744 {
745 mi_math_assert_msg( row < ROW, "precondition");
746 mi_math_assert_msg( col < COL, "precondition");
747 begin()[row * COL + col] = value;
748 }
749
753 inline T det33() const
754 {
755 mi_static_assert( (ROW==3 || ROW==4) && (COL==3 || COL==4) );
756 return this->xx * this->yy * this->zz
757 + this->xy * this->yz * this->zx
758 + this->xz * this->yx * this->zy
759 - this->xx * this->zy * this->yz
760 - this->xy * this->zz * this->yx
761 - this->xz * this->zx * this->yy;
762 }
763
767 inline bool invert();
768
774 inline void transpose()
775 {
776 mi_static_assert( ROW==COL);
777 for( Size i=0; i < ROW-1; ++i) {
778 for( Size j=i+1; j < COL; ++j) {
779 T tmp = get(i,j);
780 set(i,j, get(j,i));
781 set(j,i, tmp);
782 }
783 }
784 }
785
789 inline void translate( T x, T y, T z)
790 {
791 this->wx += x;
792 this->wy += y;
793 this->wz += z;
794 }
795
799 inline void translate( const Vector<Float32,3>& vector)
800 {
801 this->wx += T( vector.x);
802 this->wy += T( vector.y);
803 this->wz += T( vector.z);
804 }
805
809 inline void translate( const Vector<Float64,3>& vector)
810 {
811 this->wx += T( vector.x);
812 this->wy += T( vector.y);
813 this->wz += T( vector.z);
814 }
815
819 inline void set_translation( T dx, T dy, T dz)
820 {
821 this->wx = dx;
822 this->wy = dy;
823 this->wz = dz;
824 }
825
829 inline void set_translation( const Vector<Float32,3>& vector)
830 {
831 this->wx = T( vector.x);
832 this->wy = T( vector.y);
833 this->wz = T( vector.z);
834 }
835
839 inline void set_translation( const Vector<Float64,3>& vector)
840 {
841 this->wx = T( vector.x);
842 this->wy = T( vector.y);
843 this->wz = T( vector.z);
844 }
845
850 inline void rotate( T xangle, T yangle, T zangle)
851 {
852 Matrix<T,4,4> tmp( T( 1));
853 tmp.set_rotation( xangle, yangle, zangle);
854 (*this) *= tmp;
855 }
856
861 inline void rotate( const Vector<Float32,3>& angles)
862 {
863 Matrix<T,4,4> tmp( T( 1));
864 tmp.set_rotation( T( angles.x), T( angles.y), T( angles.z));
865 (*this) *= tmp;
866 }
867
872 inline void rotate( const Vector<Float64,3>& angles)
873 {
874 Matrix<T,4,4> tmp( T( 1));
875 tmp.set_rotation( T( angles.x), T( angles.y), T( angles.z));
876 (*this) *= tmp;
877 }
878
884 inline void set_rotation( T x_angle, T y_angle, T z_angle);
885
891 inline void set_rotation( const Vector<Float32,3>& angles)
892 {
893 set_rotation( T( angles.x), T( angles.y), T( angles.z));
894 }
895
901 inline void set_rotation( const Vector<Float64,3>& angles)
902 {
903 set_rotation( T( angles.x), T( angles.y), T( angles.z));
904 }
905
912 inline void set_rotation( const Vector<Float32,3>& axis, Float64 angle);
913
920 inline void set_rotation( const Vector<Float64,3>& axis, Float64 angle);
921
926 inline void lookat(
927 const Vector<Float32,3>& position,
928 const Vector<Float32,3>& target,
929 const Vector<Float32,3>& up);
930
936 inline void lookat(
937 const Vector<Float64,3>& position,
938 const Vector<Float64,3>& target,
939 const Vector<Float64,3>& up);
940};
941
942
943//------ Free comparison operators ==, !=, <, <=, >, >= for matrices -----------
944
946template <typename T, Size ROW, Size COL>
947inline bool operator==(
948 const Matrix<T,ROW,COL>& lhs,
949 const Matrix<T,ROW,COL>& rhs)
950{
951 return is_equal( lhs, rhs);
952}
953
955template <typename T, Size ROW, Size COL>
956inline bool operator!=(
957 const Matrix<T,ROW,COL>& lhs,
958 const Matrix<T,ROW,COL>& rhs)
959{
960 return is_not_equal( lhs, rhs);
961}
962
966template <typename T, Size ROW, Size COL>
967inline bool operator<(
968 const Matrix<T,ROW,COL>& lhs,
969 const Matrix<T,ROW,COL>& rhs)
970{
971 return lexicographically_less( lhs, rhs);
972}
973
977template <typename T, Size ROW, Size COL>
978inline bool operator<=(
979 const Matrix<T,ROW,COL>& lhs,
980 const Matrix<T,ROW,COL>& rhs)
981{
982 return lexicographically_less_or_equal( lhs, rhs);
983}
984
988template <typename T, Size ROW, Size COL>
989inline bool operator>(
990 const Matrix<T,ROW,COL>& lhs,
991 const Matrix<T,ROW,COL>& rhs)
992{
993 return lexicographically_greater( lhs, rhs);
994}
995
999template <typename T, Size ROW, Size COL>
1000inline bool operator>=(
1001 const Matrix<T,ROW,COL>& lhs,
1002 const Matrix<T,ROW,COL>& rhs)
1003{
1004 return lexicographically_greater_or_equal( lhs, rhs);
1005}
1006
1007//------ Operator declarations for Matrix -------------------------------------
1008
1010template <typename T, Size ROW, Size COL>
1011Matrix<T,ROW,COL>& operator+=( Matrix<T,ROW,COL>& lhs, const Matrix<T,ROW,COL>& rhs);
1012
1014template <typename T, Size ROW, Size COL>
1015Matrix<T,ROW,COL>& operator-=( Matrix<T,ROW,COL>& lhs, const Matrix<T,ROW,COL>& rhs);
1016
1018template <typename T, Size ROW, Size COL>
1020 const Matrix<T,ROW,COL>& lhs,
1021 const Matrix<T,ROW,COL>& rhs)
1022{
1023 Matrix<T,ROW,COL> temp( lhs);
1024 temp += rhs;
1025 return temp;
1026}
1027
1029template <typename T, Size ROW, Size COL>
1031 const Matrix<T,ROW,COL>& lhs,
1032 const Matrix<T,ROW,COL>& rhs)
1033{
1034 Matrix<T,ROW,COL> temp( lhs);
1035 temp -= rhs;
1036 return temp;
1037}
1038
1040template <typename T, Size ROW, Size COL>
1042 const Matrix<T,ROW,COL>& mat)
1043{
1044 Matrix<T,ROW,COL> temp;
1045 for( Size i(0u); i < ROW*COL; ++i)
1046 temp.begin()[i] = -mat.get(i);
1047 return temp;
1048}
1049
1056template <typename T, Size ROW, Size COL>
1058 Matrix<T,ROW,COL>& lhs,
1059 const Matrix<T,COL,COL>& rhs)
1060{
1061 // There are more efficient ways of implementing this. Its a default solution. Specializations
1062 // exist below.
1063 Matrix<T,ROW,COL> old( lhs);
1064 for( Size rrow = 0; rrow < ROW; ++rrow) {
1065 for( Size rcol = 0; rcol < COL; ++rcol) {
1066 lhs( rrow, rcol) = T(0);
1067 for( Size k = 0; k < COL; ++k)
1068 lhs( rrow, rcol) += old( rrow, k) * rhs( k, rcol);
1069 }
1070 }
1071 return lhs;
1072}
1073
1079template <typename T, Size ROW1, Size COL1, Size ROW2, Size COL2>
1081 const Matrix<T,ROW1,COL1>& lhs,
1082 const Matrix<T,ROW2,COL2>& rhs)
1083{
1084 // There are more efficient ways of implementing this. Its a default solution. Specializations
1085 // exist below.
1086 mi_static_assert( COL1 == ROW2);
1087 Matrix<T,ROW1,COL2> result;
1088 for( Size rrow = 0; rrow < ROW1; ++rrow) {
1089 for( Size rcol = 0; rcol < COL2; ++rcol) {
1090 result( rrow, rcol) = T(0);
1091 for( Size k = 0; k < COL1; ++k)
1092 result( rrow, rcol) += lhs( rrow, k) * rhs( k, rcol);
1093 }
1094 }
1095 return result;
1096}
1097
1105template <typename T, Size ROW, Size COL, Size DIM>
1107 const Matrix<T,ROW,COL>& mat,
1108 const Vector<T,DIM>& vec)
1109{
1110 mi_static_assert( COL == DIM);
1111 Vector<T,ROW> result;
1112 for( Size row = 0; row < ROW; ++row) {
1113 result[row] = T(0);
1114 for( Size col = 0; col < COL; ++col)
1115 result[row] += mat( row, col) * vec[col];
1116 }
1117 return result;
1118}
1119
1126template <Size DIM, typename T, Size ROW, Size COL>
1128 const Vector<T,DIM>& vec,
1129 const Matrix<T,ROW,COL>& mat)
1130{
1131 mi_static_assert( DIM == ROW);
1132 Vector<T,COL> result;
1133 for( Size col = 0; col < COL; ++col) {
1134 result[col] = T(0);
1135 for( Size row = 0; row < ROW; ++row)
1136 result[col] += mat( row, col) * vec[row];
1137 }
1138 return result;
1139}
1140
1143template <typename T, Size ROW, Size COL>
1145{
1146 for( Size i=0; i < ROW*COL; ++i)
1147 mat.begin()[i] *= factor;
1148 return mat;
1149}
1150
1152template <typename T, Size ROW, Size COL>
1153inline Matrix<T,ROW,COL> operator*( const Matrix<T,ROW,COL>& mat, T factor)
1154{
1155 Matrix<T,ROW,COL> temp( mat);
1156 temp *= factor;
1157 return temp;
1158}
1159
1161template <typename T, Size ROW, Size COL>
1162inline Matrix<T,ROW,COL> operator*( T factor, const Matrix<T,ROW,COL>& mat)
1163{
1164 Matrix<T,ROW,COL> temp( mat);
1165 temp *= factor; // * on T should be commutative (IEEE-754)
1166 return temp;
1167}
1168
1169
1170//------ Free Functions for Matrix --------------------------------------------
1171
1175template <Size NEW_ROW, Size NEW_COL, typename T, Size ROW, Size COL>
1177 const Matrix<T,ROW,COL>& mat)
1178{
1179 mi_static_assert( NEW_ROW <= ROW);
1180 mi_static_assert( NEW_COL <= COL);
1182 for( Size i=0; i < NEW_ROW; ++i)
1183 for( Size j=0; j < NEW_COL; ++j)
1184 result( i, j) = mat( i, j);
1185 return result;
1186}
1187
1188
1189
1191template <typename T, Size ROW, Size COL>
1193 const Matrix<T,ROW,COL>& mat)
1194{
1195 Matrix<T,COL,ROW> result;
1196 for( Size i=0; i < ROW; ++i)
1197 for( Size j=0; j < COL; ++j)
1198 result( j, i) = mat( i, j);
1199 return result;
1200}
1201
1207template <typename T, typename U>
1209 const Matrix<T,4,4>& mat,
1210 const U& point)
1211{
1212 const T w = T(mat.xw * point + mat.ww);
1213 if( w == T(0) || w == T(1))
1214 return U(mat.xx * point + mat.wx);
1215 else
1216 return U((mat.xx * point + mat.wx) / w);
1217}
1218
1224template <typename T, typename U>
1226 const Matrix<T,4,4>& mat,
1227 const Vector<U,2>& point)
1228{
1229 T w = T(mat.xw * point.x + mat.yw * point.y + mat.ww);
1230 if( w == T(0) || w == T(1))
1231 return Vector<U, 2>(
1232 U(mat.xx * point.x + mat.yx * point.y + mat.wx),
1233 U(mat.xy * point.x + mat.yy * point.y + mat.wy));
1234 else {
1235 w = T(1)/w; // optimization
1236 return Vector<U, 2>(
1237 U((mat.xx * point.x + mat.yx * point.y + mat.wx) * w),
1238 U((mat.xy * point.x + mat.yy * point.y + mat.wy) * w));
1239 }
1240}
1241
1247template <typename T, typename U>
1249 const Matrix<T,4,3>& mat,
1250 const Vector<U,3>& point)
1251{
1252 return Vector<U,3>(
1253 U(mat.xx * point.x + mat.yx * point.y + mat.zx * point.z + mat.wx),
1254 U(mat.xy * point.x + mat.yy * point.y + mat.zy * point.z + mat.wy),
1255 U(mat.xz * point.x + mat.yz * point.y + mat.zz * point.z + mat.wz));
1256}
1257
1263template <typename T, typename U>
1265 const Matrix<T,4,4>& mat,
1266 const Vector<U,3>& point)
1267{
1268 T w = T(mat.xw * point.x + mat.yw * point.y + mat.zw * point.z + mat.ww);
1269 if( w == T(0) || w == T(1)) // avoids temporary and division
1270 return Vector<U,3>(
1271 U(mat.xx * point.x + mat.yx * point.y + mat.zx * point.z + mat.wx),
1272 U(mat.xy * point.x + mat.yy * point.y + mat.zy * point.z + mat.wy),
1273 U(mat.xz * point.x + mat.yz * point.y + mat.zz * point.z + mat.wz));
1274 else {
1275 w = T(1)/w; // optimization
1276 return Vector<U,3>(
1277 U((mat.xx * point.x + mat.yx * point.y + mat.zx * point.z + mat.wx) * w),
1278 U((mat.xy * point.x + mat.yy * point.y + mat.zy * point.z + mat.wy) * w),
1279 U((mat.xz * point.x + mat.yz * point.y + mat.zz * point.z + mat.wz) * w));
1280 }
1281}
1282
1288template <typename T, typename U>
1290 const Matrix<T,4,4>& mat,
1291 const Vector<U,4>& point)
1292{
1293 return Vector<U, 4>(
1294 U(mat.xx * point.x + mat.yx * point.y + mat.zx * point.z + mat.wx * point.w),
1295 U(mat.xy * point.x + mat.yy * point.y + mat.zy * point.z + mat.wy * point.w),
1296 U(mat.xz * point.x + mat.yz * point.y + mat.zz * point.z + mat.wz * point.w),
1297 U(mat.xw * point.x + mat.yw * point.y + mat.zw * point.z + mat.ww * point.w));
1298}
1299
1305template <typename T, typename U>
1307 const Matrix<T,4,4>& mat,
1308 const U& vector)
1309{
1310 return U(mat.xx * vector);
1311}
1312
1318template <typename T, typename U>
1320 const Matrix<T,4,4>& mat,
1321 const Vector<U,2>& vector)
1322{
1323 return Vector<U,2>(
1324 U(mat.xx * vector.x + mat.yx * vector.y),
1325 U(mat.xy * vector.x + mat.yy * vector.y));
1326}
1327
1333template <typename T, typename U>
1335 const Matrix<T,3,3>& mat,
1336 const Vector<U,3>& vector)
1337{
1338 return Vector<U,3>(
1339 U(mat.xx * vector.x + mat.yx * vector.y + mat.zx * vector.z),
1340 U(mat.xy * vector.x + mat.yy * vector.y + mat.zy * vector.z),
1341 U(mat.xz * vector.x + mat.yz * vector.y + mat.zz * vector.z));
1342}
1343
1349template <typename T, typename U>
1351 const Matrix<T,4,3>& mat,
1352 const Vector<U,3>& vector)
1353{
1354 return Vector<U,3>(
1355 U(mat.xx * vector.x + mat.yx * vector.y + mat.zx * vector.z),
1356 U(mat.xy * vector.x + mat.yy * vector.y + mat.zy * vector.z),
1357 U(mat.xz * vector.x + mat.yz * vector.y + mat.zz * vector.z));
1358}
1359
1365template <typename T, typename U>
1367 const Matrix<T,4,4>& mat,
1368 const Vector<U,3>& vector)
1369{
1370 return Vector<U,3>(
1371 U(mat.xx * vector.x + mat.yx * vector.y + mat.zx * vector.z),
1372 U(mat.xy * vector.x + mat.yy * vector.y + mat.zy * vector.z),
1373 U(mat.xz * vector.x + mat.yz * vector.y + mat.zz * vector.z));
1374}
1375
1387template <typename T, typename U>
1389 const Matrix<T,3,3>& inv_mat,
1390 const Vector<U,3>& normal)
1391{
1392 return Vector<U,3>(
1393 U(inv_mat.xx * normal.x + inv_mat.xy * normal.y + inv_mat.xz * normal.z),
1394 U(inv_mat.yx * normal.x + inv_mat.yy * normal.y + inv_mat.yz * normal.z),
1395 U(inv_mat.zx * normal.x + inv_mat.zy * normal.y + inv_mat.zz * normal.z));
1396}
1397
1409template <typename T, typename U>
1411 const Matrix<T,4,4>& inv_mat,
1412 const Vector<U,3>& normal)
1413{
1414 return Vector<U,3>(
1415 U(inv_mat.xx * normal.x + inv_mat.xy * normal.y + inv_mat.xz * normal.z),
1416 U(inv_mat.yx * normal.x + inv_mat.yy * normal.y + inv_mat.yz * normal.z),
1417 U(inv_mat.zx * normal.x + inv_mat.zy * normal.y + inv_mat.zz * normal.z));
1418}
1419
1433template <typename T, typename U>
1435 const Matrix<T,4,4>& mat,
1436 const Vector<U,3>& normal)
1437{
1438 Matrix<T,3,3> sub_mat( mat.xx, mat.xy, mat.xz,
1439 mat.yx, mat.yy, mat.yz,
1440 mat.zx, mat.zy, mat.zz);
1441 bool inverted = sub_mat.invert();
1442 if( !inverted)
1443 return normal;
1444 return Vector<U,3>(
1445 U(sub_mat.xx * normal.x + sub_mat.xy * normal.y + sub_mat.xz * normal.z),
1446 U(sub_mat.yx * normal.x + sub_mat.yy * normal.y + sub_mat.yz * normal.z),
1447 U(sub_mat.zx * normal.x + sub_mat.zy * normal.y + sub_mat.zz * normal.z));
1448}
1449
1450
1451//------ Definitions of non-inline function -----------------------------------
1452
1453template <typename T, Size ROW, Size COL>
1455 Matrix<T,ROW,COL>& lhs,
1456 const Matrix<T,ROW,COL>& rhs)
1457{
1458 for( Size i=0; i < ROW*COL; ++i)
1459 lhs.begin()[i] += rhs.get(i);
1460 return lhs;
1461}
1462
1463template <typename T, Size ROW, Size COL>
1465 Matrix<T,ROW,COL>& lhs,
1466 const Matrix<T,ROW,COL>& rhs)
1467{
1468 for( Size i=0; i < ROW*COL; ++i)
1469 lhs.begin()[i] -= rhs.get(i);
1470 return lhs;
1471}
1472
1473#ifndef MI_FOR_DOXYGEN_ONLY
1474
1475template <typename T, Size ROW, Size COL>
1476inline void Matrix<T,ROW,COL>::set_rotation( T xangle, T yangle, T zangle)
1477{
1478 mi_static_assert( COL == 4 && ROW == 4);
1479 T tsx, tsy, tsz; // sine of [xyz]_angle
1480 T tcx, tcy, tcz; // cosine of [xyz]_angle
1481 T tmp;
1482 const T min_angle = T(0.00024f);
1483
1484 if( abs( xangle) > min_angle) {
1485 tsx = sin( xangle);
1486 tcx = cos( xangle);
1487 } else {
1488 tsx = xangle;
1489 tcx = T(1);
1490 }
1491 if( abs( yangle) > min_angle) {
1492 tsy = sin( yangle);
1493 tcy = cos( yangle);
1494 } else {
1495 tsy = yangle;
1496 tcy = T(1);
1497 }
1498 if( abs(zangle) > min_angle) {
1499 tsz = sin( zangle);
1500 tcz = cos( zangle);
1501 } else {
1502 tsz = T(zangle);
1503 tcz = T(1);
1504 }
1505 this->xx = tcy * tcz;
1506 this->xy = tcy * tsz;
1507 this->xz = -tsy;
1508
1509 tmp = tsx * tsy;
1510 this->yx = tmp * tcz - tcx * tsz;
1511 this->yy = tmp * tsz + tcx * tcz;
1512 this->yz = tsx * tcy;
1513
1514 tmp = tcx * tsy;
1515 this->zx = tmp * tcz + tsx * tsz;
1516 this->zy = tmp * tsz - tsx * tcz;
1517 this->zz = tcx * tcy;
1518}
1519
1520template <typename T, Size ROW, Size COL>
1521inline void Matrix<T,ROW,COL>::set_rotation( const Vector<Float32,3>& axis_v, Float64 angle)
1522{
1523 mi_static_assert( COL == 4 && ROW == 4);
1524 Vector<T,3> axis( axis_v);
1525 const T min_angle = T(0.00024f);
1526
1527 if( abs( T(angle)) < min_angle) {
1528 T xa = axis.x * T(angle);
1529 T ya = axis.y * T(angle);
1530 T za = axis.z * T(angle);
1531
1532 this->xx = T(1);
1533 this->xy = za;
1534 this->xz = -ya;
1535 this->xw = T(0);
1536
1537 this->yx = za;
1538 this->yy = T(1);
1539 this->yz = xa;
1540 this->yw = T(0);
1541
1542 this->zx = -ya;
1543 this->zy = -xa;
1544 this->zz = T(1);
1545 this->zw = T(0);
1546 } else {
1547 T s = sin( T(angle));
1548 T c = cos( T(angle));
1549 T t = T(1) - c;
1550 T tmp;
1551
1552 tmp = t * T(axis.x);
1553 this->xx = tmp * T(axis.x) + c;
1554 this->xy = tmp * T(axis.y) + s * T(axis.z);
1555 this->xz = tmp * T(axis.z) - s * T(axis.y);
1556 this->xw = T(0);
1557
1558 tmp = t * T(axis.y);
1559 this->yx = tmp * T(axis.x) - s * T(axis.z);
1560 this->yy = tmp * T(axis.y) + c;
1561 this->yz = tmp * T(axis.z) + s * T(axis.x);
1562 this->yw = T(0);
1563
1564 tmp = t * T(axis.z);
1565 this->zx = tmp * T(axis.x) + s * T(axis.y);
1566 this->zy = tmp * T(axis.y) - s * T(axis.x);
1567 this->zz = tmp * T(axis.z) + c;
1568 this->zw = T(0);
1569 }
1570 this->wx = this->wy = this->wz = T(0);
1571 this->ww = T(1);
1572}
1573
1574template <typename T, Size ROW, Size COL>
1575inline void Matrix<T,ROW,COL>::set_rotation( const Vector<Float64,3>& axis_v, Float64 angle)
1576{
1577 mi_static_assert( COL == 4 && ROW == 4);
1578 Vector<T,3> axis( axis_v);
1579 constexpr T min_angle = T(0.00024f);
1580
1581 if( abs(T(angle)) < min_angle) {
1582 T xa = axis.x * T(angle);
1583 T ya = axis.y * T(angle);
1584 T za = axis.z * T(angle);
1585
1586 this->xx = T(1);
1587 this->xy = za;
1588 this->xz = -ya;
1589 this->xw = T(0);
1590
1591 this->yx = za;
1592 this->yy = T(1);
1593 this->yz = xa;
1594 this->yw = T(0);
1595
1596 this->zx = -ya;
1597 this->zy = -xa;
1598 this->zz = T(1);
1599 this->zw = T(0);
1600 } else {
1601 T s = sin( T(angle));
1602 T c = cos( T(angle));
1603 T t = T(1) - c;
1604 T tmp;
1605
1606 tmp = t * T(axis.x);
1607 this->xx = tmp * T(axis.x) + c;
1608 this->xy = tmp * T(axis.y) + s * T(axis.z);
1609 this->xz = tmp * T(axis.z) - s * T(axis.y);
1610 this->xw = T(0);
1611
1612 tmp = t * T(axis.y);
1613 this->yx = tmp * T(axis.x) - s * T(axis.z);
1614 this->yy = tmp * T(axis.y) + c;
1615 this->yz = tmp * T(axis.z) + s * T(axis.x);
1616 this->yw = T(0);
1617
1618 tmp = t * T(axis.z);
1619 this->zx = tmp * T(axis.x) + s * T(axis.y);
1620 this->zy = tmp * T(axis.y) - s * T(axis.x);
1621 this->zz = tmp * T(axis.z) + c;
1622 this->zw = T(0);
1623 }
1624 this->wx = this->wy = this->wz = T(0);
1625 this->ww = T(1);
1626}
1627
1628template <typename T, Size ROW, Size COL>
1629inline void Matrix<T,ROW,COL>::lookat(
1630 const Vector<Float32,3>& position,
1631 const Vector<Float32,3>& target,
1632 const Vector<Float32,3>& up)
1633{
1634 mi_static_assert( COL == 4 && ROW == 4);
1635 Vector<Float32,3> xaxis, yaxis, zaxis;
1636
1637 // Z vector
1638 zaxis = position - target;
1639 zaxis.normalize();
1640
1641 // X vector = up cross Z
1642 xaxis = cross( up, zaxis);
1643 xaxis.normalize();
1644
1645 // Recompute Y = Z cross X
1646 yaxis = cross( zaxis, xaxis);
1647 yaxis.normalize();
1648
1649 // Build rotation matrix
1650 Matrix<T,4,4> rot(
1651 T(xaxis.x), T(yaxis.x), T(zaxis.x), T(0),
1652 T(xaxis.y), T(yaxis.y), T(zaxis.y), T(0),
1653 T(xaxis.z), T(yaxis.z), T(zaxis.z), T(0),
1654 T(0), T(0), T(0), T(1));
1655
1656 // Compute the new position by multiplying the inverse position with the rotation matrix
1657 Matrix<T,4,4> trans(
1658 T(1), T(0), T(0), T(0),
1659 T(0), T(1), T(0), T(0),
1660 T(0), T(0), T(1), T(0),
1661 T(-position.x), T(-position.y), T(-position.z), T(1));
1662
1663 *this = trans * rot;
1664}
1665
1666template <typename T, Size ROW, Size COL>
1667inline void Matrix<T,ROW,COL>::lookat(
1668 const Vector<Float64,3>& position,
1669 const Vector<Float64,3>& target,
1670 const Vector<Float64,3>& up)
1671{
1672 mi_static_assert( COL == 4 && ROW == 4);
1673 Vector<Float64,3> xaxis, yaxis, zaxis;
1674
1675 // Z vector
1676 zaxis = position - target;
1677 zaxis.normalize();
1678
1679 // X vector = up cross Z
1680 xaxis = cross( up, zaxis);
1681 xaxis.normalize();
1682
1683 // Recompute Y = Z cross X
1684 yaxis = cross( zaxis, xaxis);
1685 yaxis.normalize();
1686
1687 // Build rotation matrix
1688 Matrix<T,4,4> rot(
1689 T(xaxis.x), T(yaxis.x), T(zaxis.x), T(0),
1690 T(xaxis.y), T(yaxis.y), T(zaxis.y), T(0),
1691 T(xaxis.z), T(yaxis.z), T(zaxis.z), T(0),
1692 T(0), T(0), T(0), T(1));
1693
1694 // Compute the new position by multiplying the inverse position with the rotation matrix
1695 Matrix<T,4,4> trans(
1696 T(1), T(0), T(0), T(0),
1697 T(0), T(1), T(0), T(0),
1698 T(0), T(0), T(1), T(0),
1699 T(-position.x), T(-position.y), T(-position.z), T(1));
1700
1701 *this = trans * rot;
1702}
1703
1704
1705//------ Definition and helper for matrix inversion ---------------------------
1706
1707// Matrix inversion class, specialized for symmetric matrices and low dimensions
1708template <class T, Size ROW, Size COL>
1709class Matrix_inverter
1710{
1711public:
1712 using Matrix = math::Matrix<T, ROW, COL>;
1713
1714 // Inverts the matrix \c M if possible and returns \c true.
1715 //
1716 // If the matrix cannot be inverted or if \c ROW != \c COL, this function returns \c false.
1717 static inline bool invert( Matrix& /* M */) { return false; }
1718};
1719
1720// Matrix inversion class, specialization for symmetric matrices
1721template <class T, Size DIM>
1722class Matrix_inverter<T,DIM,DIM>
1723{
1724public:
1725 using Matrix = math::Matrix<T, DIM, DIM>;
1726 using Value_vector = math::Vector<T, DIM>;
1727 using Index_vector = math::Vector<Size, DIM>;
1728
1729 // LU decomposition of matrix lu in place.
1730 //
1731 // Returns \c false if matrix cannot be decomposed, for example, if it is not invertible, and \c
1732 // true otherwise. Returns also a row permutation in indx.
1733 static bool lu_decomposition(
1734 Matrix& lu, // matrix to decompose, modified in place
1735 Index_vector& indx); // row permutation info indx[4]
1736
1737 // Solves the equation lu * x = b for x. lu and indx are the results of lu_decomposition. The
1738 // solution is returned in b.
1739 static void lu_backsubstitution(
1740 const Matrix& lu, // LU decomposed matrix
1741 const Index_vector& indx, // permutation vector
1742 Value_vector& b); // right hand side vector b, modified in place
1743
1744 static bool invert( Matrix& mat);
1745};
1746
1747template <class T, Size DIM>
1748bool Matrix_inverter<T,DIM,DIM>::lu_decomposition(
1749 Matrix& lu,
1750 Index_vector& indx)
1751{
1752 Value_vector vv; // implicit scaling of each row
1753
1754 for( Size i = 0; i < DIM; i++) { // get implicit scaling
1755 T big = T(0);
1756 for( Size j = 0; j < DIM; j++) {
1757 T temp = abs(lu.get(i,j));
1758 if( temp > big)
1759 big = temp;
1760 }
1761 if( big == T(0))
1762 return false;
1763 vv[i] = T(1) / big; // save scaling
1764 }
1765 //
1766 // loop over columns of Crout's method
1767 //
1768 Size imax = 0;
1769 for( Size j = 0; j < DIM; j++) {
1770 for( Size i = 0; i < j; i++) {
1771 T sum = lu.get(i,j);
1772 for( Size k = 0; k < i; k++)
1773 sum -= lu.get(i,k) * lu.get(k,j);
1774 lu.set(i, j, sum);
1775 }
1776 T big = 0; // init for pivot search
1777 for( Size i = j; i < DIM; i++) {
1778 T sum = lu.get(i,j);
1779 for( Size k = 0; k < j; k++)
1780 sum -= lu.get(i,k) * lu.get(k,j);
1781 lu.set(i, j, sum);
1782 T dum = vv[i] * abs(sum);
1783 if( dum >= big) { // pivot good?
1784 big = dum;
1785 imax = i;
1786 }
1787 }
1788 if( j != imax) { // interchange rows
1789 for( Size k = 0; k < DIM; k++) {
1790 T dum = lu.get(imax,k);
1791 lu.set(imax, k, lu.get(j,k));
1792 lu.set(j, k, dum);
1793 }
1794 vv[imax] = vv[j]; // interchange scale factor
1795 }
1796 indx[j] = imax;
1797 if( lu.get(j,j) == 0)
1798 return false;
1799 if( j != DIM-1) { // divide by pivot element
1800 T dum = T(1) / lu.get(j,j);
1801 for( Size i = j + 1; i < DIM; i++)
1802 lu.set(i, j, lu.get(i,j) * dum);
1803 }
1804 }
1805 return true;
1806}
1807
1808template <class T, Size DIM>
1809void Matrix_inverter<T,DIM,DIM>::lu_backsubstitution(
1810 const Matrix& lu,
1811 const Index_vector& indx,
1812 Value_vector& b)
1813{
1814 // when ii != DIM+1, ii is index of first non-vanishing element of b
1815 Size ii = DIM+1;
1816 for( Size i = 0; i < DIM; i++) {
1817 Size ip = indx[i];
1818 T sum = b[ip];
1819 b[ip] = b[i];
1820 if( ii != DIM+1) {
1821 for( Size j = ii; j < i; j++) {
1822 sum -= lu.get(i,j) * b[j];
1823 }
1824 } else {
1825 if( sum != T(0)) { // non-zero element
1826 ii = i;
1827 }
1828 }
1829 b[i] = sum;
1830 }
1831 for( Size i2 = DIM; i2 > 0;) { // backsubstitution
1832 --i2;
1833 T sum = b[i2];
1834 for( Size j = i2+1; j < DIM; j++)
1835 sum -= lu.get(i2,j) * b[j];
1836 b[i2] = sum / lu.get(i2,i2); // store comp. of sol. vector
1837 }
1838}
1839
1840template <class T, Size DIM>
1841bool Matrix_inverter<T,DIM,DIM>::invert( Matrix& mat)
1842{
1843 Matrix lu(mat); // working copy of matrix to invert
1844 Index_vector indx; // row permutation info
1845
1846 // LU decompose, return if it fails
1847 if( !lu_decomposition(lu, indx))
1848 return false;
1849
1850 // solve for each column vector of the I matrix
1851 for( Size j = 0; j < DIM; ++j) {
1852 Value_vector col(T(0)); // TODO: do that directly in the mat matrix
1853 col[j] = T(1);
1854 lu_backsubstitution( lu, indx, col);
1855 for( Size i = 0; i < DIM; ++i) {
1856 mat.set( i, j, col[i]);
1857 }
1858 }
1859 return true;
1860}
1861
1862// Matrix inversion class, specialization for 1x1 matrix
1863template <class T>
1864class Matrix_inverter<T,1,1>
1865{
1866public:
1867 using Matrix = math::Matrix<T, 1, 1>;
1868
1869 static inline bool invert( Matrix& mat)
1870 {
1871 T s = mat.get( 0, 0);
1872 if( s == T(0))
1873 return false;
1874 mat.set( 0, 0, T(1) / s);
1875 return true;
1876 }
1877};
1878
1879// Matrix inversion class, specialization for 2x2 matrix
1880template <class T>
1881class Matrix_inverter<T,2,2>
1882{
1883public:
1884 using Matrix = math::Matrix<T, 2, 2>;
1885
1886 static inline bool invert( Matrix& mat)
1887 {
1888 T a = mat.get( 0, 0);
1889 T b = mat.get( 0, 1);
1890 T c = mat.get( 1, 0);
1891 T d = mat.get( 1, 1);
1892 T det = a*d - b*c;
1893 if( det == T( 0))
1894 return false;
1895 T rdet = T(1) / det;
1896 mat.set( 0, 0, d * rdet);
1897 mat.set( 0, 1,-b * rdet);
1898 mat.set( 1, 0,-c * rdet);
1899 mat.set( 1, 1, a * rdet);
1900 return true;
1901 }
1902};
1903
1904template <typename T, Size ROW, Size COL>
1905inline bool Matrix<T,ROW,COL>::invert()
1906{
1907 return Matrix_inverter<T,ROW,COL>::invert( *this);
1908}
1909
1910
1911
1912//------ Specializations and (specialized) overloads --------------------------
1913
1914// Specialization of common matrix multiplication for 4x4 matrices.
1915template <typename T>
1916inline Matrix<T,4,4>& operator*=(
1917 Matrix<T,4,4>& lhs,
1918 const Matrix<T,4,4>& rhs)
1919{
1920 Matrix<T,4,4> old( lhs);
1921
1922 lhs.xx = old.xx * rhs.xx + old.xy * rhs.yx + old.xz * rhs.zx + old.xw * rhs.wx;
1923 lhs.xy = old.xx * rhs.xy + old.xy * rhs.yy + old.xz * rhs.zy + old.xw * rhs.wy;
1924 lhs.xz = old.xx * rhs.xz + old.xy * rhs.yz + old.xz * rhs.zz + old.xw * rhs.wz;
1925 lhs.xw = old.xx * rhs.xw + old.xy * rhs.yw + old.xz * rhs.zw + old.xw * rhs.ww;
1926
1927 lhs.yx = old.yx * rhs.xx + old.yy * rhs.yx + old.yz * rhs.zx + old.yw * rhs.wx;
1928 lhs.yy = old.yx * rhs.xy + old.yy * rhs.yy + old.yz * rhs.zy + old.yw * rhs.wy;
1929 lhs.yz = old.yx * rhs.xz + old.yy * rhs.yz + old.yz * rhs.zz + old.yw * rhs.wz;
1930 lhs.yw = old.yx * rhs.xw + old.yy * rhs.yw + old.yz * rhs.zw + old.yw * rhs.ww;
1931
1932 lhs.zx = old.zx * rhs.xx + old.zy * rhs.yx + old.zz * rhs.zx + old.zw * rhs.wx;
1933 lhs.zy = old.zx * rhs.xy + old.zy * rhs.yy + old.zz * rhs.zy + old.zw * rhs.wy;
1934 lhs.zz = old.zx * rhs.xz + old.zy * rhs.yz + old.zz * rhs.zz + old.zw * rhs.wz;
1935 lhs.zw = old.zx * rhs.xw + old.zy * rhs.yw + old.zz * rhs.zw + old.zw * rhs.ww;
1936
1937 lhs.wx = old.wx * rhs.xx + old.wy * rhs.yx + old.wz * rhs.zx + old.ww * rhs.wx;
1938 lhs.wy = old.wx * rhs.xy + old.wy * rhs.yy + old.wz * rhs.zy + old.ww * rhs.wy;
1939 lhs.wz = old.wx * rhs.xz + old.wy * rhs.yz + old.wz * rhs.zz + old.ww * rhs.wz;
1940 lhs.ww = old.wx * rhs.xw + old.wy * rhs.yw + old.wz * rhs.zw + old.ww * rhs.ww;
1941
1942 return lhs;
1943}
1944
1945// Specialization of common matrix multiplication for 4x4 matrices.
1946template <typename T>
1947inline Matrix<T,4,4> operator*(
1948 const Matrix<T,4,4>& lhs,
1949 const Matrix<T,4,4>& rhs)
1950{
1951 Matrix<T,4,4> temp( lhs);
1952 temp *= rhs;
1953 return temp;
1954}
1955
1956#endif // MI_FOR_DOXYGEN_ONLY
1957 // end group mi_math_matrix
1959
1960} // namespace math
1961
1962} // namespace mi
1963
1964#endif // MI_MATH_MATRIX_H
NxM-dimensional matrix class template of fixed dimensions.
Definition: matrix.h:367
Fixed-size math vector class template with generic operations.
Definition: vector.h:286
Math functions and function templates on simple types or generic container and vector concepts.
#define mi_static_assert(expr)
Compile time assertion that raises a compilation error if the constant expression expr evaluates to f...
Definition: assert.h:58
double Float64
64-bit float.
Definition: types.h:52
Uint64 Size
Unsigned integral type that is large enough to hold the size of all types.
Definition: types.h:112
Sint64 Difference
Signed integral type that is large enough to hold the difference of two pointers.
Definition: types.h:122
bool lexicographically_less(const V &lhs, const V &rhs)
Returns true if vector lhs is lexicographically less than vector rhs, and false otherwise.
Definition: function.h:1114
bool lexicographically_less_or_equal(const V &lhs, const V &rhs)
Returns true if vector lhs is lexicographically less than or equal to vector rhs, and false otherwise...
Definition: function.h:1130
bool lexicographically_greater_or_equal(const V &lhs, const V &rhs)
Returns true if vector lhs is lexicographically greater than or equal to vector rhs,...
Definition: function.h:1162
bool is_not_equal(const V &lhs, const V &rhs)
Returns true if vector lhs is elementwise not equal to vector rhs, and false otherwise.
Definition: function.h:1101
bool lexicographically_greater(const V &lhs, const V &rhs)
Returns true if vector lhs is lexicographically greater than vector rhs, and false otherwise.
Definition: function.h:1146
bool is_equal(const V &lhs, const V &rhs)
Returns true if vector lhs is elementwise equal to vector rhs, and false otherwise.
Definition: function.h:1090
#define mi_math_assert_msg(expr, msg)
Math API assertion macro (with message).
Definition: assert.h:80
bool operator>=(const Bbox<T, DIM> &lhs, const Bbox<T, DIM> &rhs)
Returns true if lhs is lexicographically greater than or equal to rhs.
Definition: bbox.h:650
Bbox<T, DIM> operator+(const Bbox<T, DIM> &bbox, T value)
Returns a bounding box that is the bbox increased by a constant value at each face,...
Definition: bbox.h:468
bool operator<(const Bbox<T, DIM> &lhs, const Bbox<T, DIM> &rhs)
Returns true if lhs is lexicographically less than rhs.
Definition: bbox.h:605
Bbox<T, DIM> & operator*=(Bbox<T, DIM> &bbox, T factor)
Scales bbox by factor, i.e., bbox.max and bbox.min are multiplied by factor.
Definition: bbox.h:562
Bbox<T, DIM> & operator+=(Bbox<T, DIM> &bbox, T value)
Increases bbox by a constant value at each face, i.e., value is added to bbox.max and subtracted from...
Definition: bbox.h:533
bool operator==(const Bbox<T, DIM> &lhs, const Bbox<T, DIM> &rhs)
Returns true if lhs is elementwise equal to rhs.
Definition: bbox.h:589
bool operator>(const Bbox<T, DIM> &lhs, const Bbox<T, DIM> &rhs)
Returns true if lhs is lexicographically greater than rhs.
Definition: bbox.h:635
bool operator!=(const Bbox<T, DIM> &lhs, const Bbox<T, DIM> &rhs)
Returns true if lhs is elementwise not equal to rhs.
Definition: bbox.h:596
bool operator<=(const Bbox<T, DIM> &lhs, const Bbox<T, DIM> &rhs)
Returns true if lhs is lexicographically less than or equal to rhs.
Definition: bbox.h:620
Bbox<T, 3> transform_vector(const Matrix<TT, 4, 4> &mat, const Bbox<T, 3> &bbox)
Returns the 3D bounding box transformed by a matrix.
Definition: bbox.h:843
Bbox<T, DIM> & operator-=(Bbox<T, DIM> &bbox, T value)
Shrinks bbox by a constant value at each face, i.e., value is subtracted from bbox....
Definition: bbox.h:548
Bbox<T, 3> transform_point(const Matrix<TT, 4, 4> &mat, const Bbox<T, 3> &bbox)
Returns the 3D bounding box transformed by a matrix.
Definition: bbox.h:780
Bbox<T, DIM> operator-(const Bbox<T, DIM> &bbox, T value)
Returns a bounding box that is the bbox shrunk by a constant value at each face, i....
Definition: bbox.h:484
Bbox<T, DIM> operator*(const Bbox<T, DIM> &bbox, T factor)
Returns a bounding box that is a version of bbox scaled by factor, i.e., bbox.max and bbox....
Definition: bbox.h:500
Color abs(const Color &c)
Returns a color with the elementwise absolute values of the color c.
Definition: color.h:459
Color sin(const Color &c)
Returns a color with the elementwise sine of the color c.
Definition: color.h:749
Color cos(const Color &c)
Returns a color with the elementwise cosine of the color c.
Definition: color.h:546
T * begin()
Returns the pointer to the first matrix element.
Definition: matrix.h:405
const T & const_reference
Const reference to element.
Definition: matrix.h:378
T yw
yw-element.
Definition: matrix.h:263
static constexpr Size size()
Constant size of the vector.
Definition: matrix.h:391
T yx
yx-element.
Definition: matrix.h:156
Matrix(T2 const (&array)[SIZE])
Constructor initializes the matrix elements from an array of dimension ROW times COL.
Definition: matrix.h:492
T zz
zz-element.
Definition: matrix.h:208
T yx
yx-element.
Definition: matrix.h:203
void set_rotation(const Vector<Float32, 3> &angles)
Stores an absolute rotation in the upper left 3x3 rotation matrix (Euler angles, by vector).
Definition: matrix.h:891
void lookat(const Vector<Float64, 3> &position, const Vector<Float64, 3> &target, const Vector<Float64, 3> &up)
Sets a transformation matrix based on a given center, a reference point, and a direction.
T xy
xy-element.
Definition: matrix.h:176
T xy
xy-element.
Definition: matrix.h:240
bool invert()
Inverts this matrix and returns success or failure.
T & reference
Mutable reference to element.
Definition: matrix.h:377
T yy
yy-element.
Definition: matrix.h:261
T xz
xz-element.
Definition: matrix.h:219
T yw
yw-element.
Definition: matrix.h:233
T get(Size i) const
Accesses the i-th matrix element, indexed in the order of the row-major memory layout.
Definition: matrix.h:713
T wy
wy-element.
Definition: matrix.h:269
Matrix(const Matrix_struct<T2, ROW, COL> &other)
Template constructor that allows explicit conversions from underlying storage type with assignment co...
Definition: matrix.h:510
T xx
xx-element.
Definition: matrix.h:110
Matrix(Transposed_copy_tag, const Matrix<T, COL, ROW> &other)
Constructor that initializes the matrix with the transpose matrix of other.
Definition: matrix.h:517
T xx
xx-element.
Definition: matrix.h:226
T const * end() const
Returns the past-the-end pointer.
Definition: matrix.h:418
T xx
xx-element.
Definition: matrix.h:256
T xx
xx-element.
Definition: matrix.h:127
T yz
yz-element.
Definition: matrix.h:232
T zy
zy-element.
Definition: matrix.h:265
T xw
xw-element.
Definition: matrix.h:242
T wx
wx-element.
Definition: matrix.h:209
T * end()
Returns the past-the-end pointer.
Definition: matrix.h:413
Matrix & operator=(const Matrix &other)
Assignment.
Definition: matrix.h:684
Matrix(T m0, T m1, T m2, T m3, T m4, T m5, T m6, T m7)
8-element constructor, must be a 2x4 or 4x2 matrix.
Definition: matrix.h:635
T xw
xw-element.
Definition: matrix.h:220
void translate(const Vector<Float32, 3> &vector)
Adds a relative translation to the matrix (by vector).
Definition: matrix.h:799
T xy
xy-element.
Definition: matrix.h:227
Matrix(T m0, T m1, T m2, T m3, T m4, T m5, T m6, T m7, T m8, T m9, T m10, T m11)
12-element constructor, must be a 3x4 or 4x3 matrix.
Definition: matrix.h:656
T xw
xw-element.
Definition: matrix.h:259
T * pointer
Mutable pointer to element.
Definition: matrix.h:375
void set_translation(T dx, T dy, T dz)
Stores an absolute translation in the matrix (by component).
Definition: matrix.h:819
T yz
yz-element.
Definition: matrix.h:191
T yx
yx-element.
Definition: matrix.h:260
T yx
yx-element.
Definition: matrix.h:243
T const * begin() const
Returns the pointer to the first matrix element.
Definition: matrix.h:408
Matrix(Transposed_copy_tag, const Matrix<T2, COL, ROW> &other)
Template constructor that initializes the matrix with the transpose matrix of other that allows the e...
Definition: matrix.h:530
T xx
xx-element.
Definition: matrix.h:103
T zx
zx-element.
Definition: matrix.h:264
T xz
xz-element.
Definition: matrix.h:228
T yy
yy-element.
Definition: matrix.h:231
Matrix(T m0, T m1, T m2, T m3, T m4, T m5, T m6, T m7, T m8)
9-element constructor, must be a 3x3 matrix.
Definition: matrix.h:645
T zz
zz-element.
Definition: matrix.h:194
T zw
zw-element.
Definition: matrix.h:267
Row_vector & operator[](Size row)
Accesses the row-th row vector, 0 <= row < ROW.
Definition: matrix.h:421
Matrix(T m0, T m1, T m2, T m3, T m4, T m5)
6-element constructor, must be a 2x3 or 3x2 matrix.
Definition: matrix.h:625
T yy
yy-element.
Definition: matrix.h:244
T yy
yy-element.
Definition: matrix.h:146
static constexpr Size max_size()
Constant maximum size of the vector.
Definition: matrix.h:394
T yx
yx-element.
Definition: matrix.h:230
T yy
yy-element.
Definition: matrix.h:190
T yx
yx-element.
Definition: matrix.h:104
Matrix(T m0, T m1, T m2, T m3)
4-element constructor, must be a 1x4, 2x2, or 4x1 matrix.
Definition: matrix.h:616
T xx
xx-element.
Definition: matrix.h:200
T yz
yz-element.
Definition: matrix.h:245
void set_translation(const Vector<Float64, 3> &vector)
Stores an absolute translation in the matrix (by vector).
Definition: matrix.h:839
const T & operator()(Size row, Size col) const
Accesses the (row, col)-th matrix element.
Definition: matrix.h:703
void set_translation(const Vector<Float32, 3> &vector)
Stores an absolute translation in the matrix (by vector).
Definition: matrix.h:829
T yx
yx-element.
Definition: matrix.h:136
T xz
xz-element.
Definition: matrix.h:188
T wy
wy-element.
Definition: matrix.h:161
Matrix(const Row_vector &v0, const Row_vector &v1, const Row_vector &v2, const Row_vector &v3)
Dedicated constructor, for ROW==4 only, that initializes matrix from four row vectors (v0,...
Definition: matrix.h:582
T xz
xz-element.
Definition: matrix.h:258
T zw
zw-element.
Definition: matrix.h:250
void rotate(const Vector<Float32, 3> &angles)
Adds a relative rotation to the matrix (Euler angles, by vector).
Definition: matrix.h:861
T xy
xy-element.
Definition: matrix.h:144
T xx
xx-element.
Definition: matrix.h:217
void translate(const Vector<Float64, 3> &vector)
Adds a relative translation to the matrix (by vector).
Definition: matrix.h:809
void rotate(const Vector<Float64, 3> &angles)
Adds a relative rotation to the matrix (Euler angles, by vector).
Definition: matrix.h:872
T xy
xy-element.
Definition: matrix.h:168
T xx
xx-element.
Definition: matrix.h:134
Matrix(T m0, T m1)
2-element constructor, must be a 1x2 or 2x1 matrix.
Definition: matrix.h:598
const T * const_pointer
Const pointer to element.
Definition: matrix.h:376
T yx
yx-element.
Definition: matrix.h:178
static constexpr Size ROWS
Constant number of rows of the matrix.
Definition: matrix.h:386
T xy
xy-element.
Definition: matrix.h:257
T xx
xx-element.
Definition: matrix.h:97
Size size_type
Size type, unsigned.
Definition: matrix.h:373
T zx
zx-element.
Definition: matrix.h:192
T yz
yz-element.
Definition: matrix.h:205
Matrix< T, NEW_ROW, NEW_COL > sub_matrix(const Matrix<T, ROW, COL> &mat)
Returns the upper-left sub-matrix of size NEW_ROW times NEW_COL.
Definition: matrix.h:1176
T xx
xx-element.
Definition: matrix.h:118
void set_rotation(const Vector<Float64, 3> &angles)
Stores an absolute rotation in the upper left 3x3 rotation matrix (Euler angles, by vector).
Definition: matrix.h:901
T zy
zy-element.
Definition: matrix.h:207
T yx
yx-element.
Definition: matrix.h:111
T zy
zy-element.
Definition: matrix.h:193
T wx
wx-element.
Definition: matrix.h:268
T yx
yx-element.
Definition: matrix.h:145
T elements[ROW *COL]
general case matrix elements.
Definition: matrix.h:91
T yy
yy-element.
Definition: matrix.h:157
Matrix(T m0, T m1, T m2, T m3, T m4, T m5, T m6, T m7, T m8, T m9, T m10, T m11, T m12, T m13, T m14, T m15)
16-element constructor, must be a 4x4 matrix.
Definition: matrix.h:670
T get(Size row, Size col) const
Accesses the (row, col)-th matrix element.
Definition: matrix.h:722
Matrix(From_iterator_tag, Iterator p)
Constructor requires the mi::math::FROM_ITERATOR tag as first argument and initializes the matrix ele...
Definition: matrix.h:473
T xy
xy-element.
Definition: matrix.h:135
Vector<U, 3> transform_normal_inv(const Matrix<T, 3, 3> &inv_mat, const Vector<U, 3> &normal)
Returns an inverse transformed 3D normal vector by applying the 3x3 transposed linear transformation ...
Definition: matrix.h:1388
void transpose()
Transposes this matrix by exchanging rows and columns.
Definition: matrix.h:774
static constexpr Size COLUMNS
Constant number of columns of the matrix.
Definition: matrix.h:387
void lookat(const Vector<Float32, 3> &position, const Vector<Float32, 3> &target, const Vector<Float32, 3> &up)
Sets a transformation matrix based on a given center, a reference point, and a direction.
T yy
yy-element.
Definition: matrix.h:179
T zy
zy-element.
Definition: matrix.h:148
T wz
wz-element.
Definition: matrix.h:211
void set_rotation(const Vector<Float32, 3> &axis, Float64 angle)
Stores an absolute rotation (by axis and angle).
Matrix(T diag)
Constructor initializes all matrix elements to zero and the diagonal elements to diag.
Definition: matrix.h:450
Matrix(const Row_vector &v0, const Row_vector &v1, const Row_vector &v2)
Dedicated constructor, for ROW==3 only, that initializes matrix from three row vectors (v0,...
Definition: matrix.h:567
T det33() const
Returns the determinant of the upper-left 3x3 sub-matrix.
Definition: matrix.h:753
T yx
yx-element.
Definition: matrix.h:119
T wz
wz-element.
Definition: matrix.h:270
constexpr Matrix()=default
The default constructor leaves the vector elements uninitialized.
static constexpr Size SIZE
Constant size of the matrix.
Definition: matrix.h:388
T xx
xx-element.
Definition: matrix.h:175
Matrix(const Matrix<T2, ROW, COL> &other)
Template constructor that allows explicit conversions from other matrices with assignment compatible ...
Definition: matrix.h:501
Matrix(const Row_vector &v0, const Row_vector &v1)
Dedicated constructor, for ROW==2 only, that initializes matrix from two row vectors (v0,...
Definition: matrix.h:554
T xw
xw-element.
Definition: matrix.h:229
void set(Size row, Size col, T value)
Sets the i-th matrix element to value, indexed in the order of the row-major memory layout.
Definition: matrix.h:743
void set_rotation(T x_angle, T y_angle, T z_angle)
Stores an absolute rotation in the upper left 3x3 rotation matrix (Euler angles, by component).
T & operator()(Size row, Size col)
Accesses the (row,col)-th matrix element.
Definition: matrix.h:693
T zx
zx-element.
Definition: matrix.h:158
T wx
wx-element.
Definition: matrix.h:160
T yz
yz-element.
Definition: matrix.h:180
T xy
xy-element.
Definition: matrix.h:187
void set(Size i, T value)
Sets the i-th matrix element to value, indexed in the order of the row-major memory layout.
Definition: matrix.h:733
T xx
xx-element.
Definition: matrix.h:154
T xy
xy-element.
Definition: matrix.h:128
T ww
ww-element.
Definition: matrix.h:271
T zx
zx-element.
Definition: matrix.h:206
T zx
zx-element.
Definition: matrix.h:112
T xz
xz-element.
Definition: matrix.h:169
Matrix(const Matrix<T, ROW, COL> &other)=default
Default copy constructor.
T zx
zx-element.
Definition: matrix.h:120
T xx
xx-element.
Definition: matrix.h:186
T xy
xy-element.
Definition: matrix.h:155
Vector<U, 3> transform_normal(const Matrix<T, 4, 4> &mat, const Vector<U, 3> &normal)
Returns a transformed 3D normal vector by applying the 3x3 transposed linear sub-transformation in th...
Definition: matrix.h:1434
void translate(T x, T y, T z)
Adds a relative translation to the matrix (by components).
Definition: matrix.h:789
T wx
wx-element.
Definition: matrix.h:121
T zz
zz-element.
Definition: matrix.h:249
T xy
xy-element.
Definition: matrix.h:218
T zx
zx-element.
Definition: matrix.h:147
T xz
xz-element.
Definition: matrix.h:202
T yz
yz-element.
Definition: matrix.h:262
Difference difference_type
Difference type, signed.
Definition: matrix.h:374
T xz
xz-element.
Definition: matrix.h:177
Matrix(T m0, T m1, T m2)
3-element constructor, must be a 1x3 or 3x1 matrix.
Definition: matrix.h:607
T value_type
Element type.
Definition: matrix.h:372
T wy
wy-element.
Definition: matrix.h:210
T xy
xy-element.
Definition: matrix.h:201
T yx
yx-element.
Definition: matrix.h:189
T zy
zy-element.
Definition: matrix.h:159
T yy
yy-element.
Definition: matrix.h:137
T zz
zz-element.
Definition: matrix.h:266
T yw
yw-element.
Definition: matrix.h:246
T zx
zx-element.
Definition: matrix.h:247
void rotate(T xangle, T yangle, T zangle)
Adds a relative rotation to the matrix (Euler angles, by component).
Definition: matrix.h:850
T xx
xx-element.
Definition: matrix.h:143
T xx
xx-element.
Definition: matrix.h:167
T xz
xz-element.
Definition: matrix.h:241
Matrix<T, COL, ROW> transpose(const Matrix<T, ROW, COL> &mat)
Returns the transpose of the matrix mat by exchanging rows and columns.
Definition: matrix.h:1192
T zy
zy-element.
Definition: matrix.h:248
Matrix(const Row_vector &v0)
Dedicated constructor, for ROW==1 only, that initializes matrix from one row vector v0.
Definition: matrix.h:543
Matrix(const Matrix_struct<T, ROW, COL> &other)
Constructor from underlying storage type.
Definition: matrix.h:441
void set_rotation(const Vector<Float64, 3> &axis, Float64 angle)
Stores an absolute rotation (by axis and angle).
T xx
xx-element.
Definition: matrix.h:239
T yy
yy-element.
Definition: matrix.h:204
Transposed_copy_tag
Enum type used to tag a special copy constructor that transposes the matrix while copying.
Definition: matrix.h:398
T * matrix_base_ptr(Matrix_struct<T, ROW, COL> &mat)
Returns the base pointer to the matrix data.
Definition: matrix.h:297
@ TRANSPOSED_COPY_TAG
Enum value used to call a special copy constructor that transposes the matrix while copying.
Definition: matrix.h:401
T cross(const Vector_struct<T, 2> &lhs, const Vector_struct<T, 2> &rhs)
Returns the two-times-two determinant result for the two vectors lhs and rhs.
Definition: vector.h:1921
From_iterator_tag
Enum used for initializing a vector from an iterator.
Definition: vector.h:36
Assertions and compile-time assertions.
Common namespace for APIs of NVIDIA Advanced Rendering Center GmbH.
Definition: example_derivatives.dox:5
Storage class for a NxM-dimensional matrix class template of fixed dimensions.
Definition: matrix.h:90
Basic types.
Math vector class template of fixed dimension with arithmetic operators and generic functions.