Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0 | ||
3 | |||
4 | #ifndef OPENVDB_MATH_MAT4_H_HAS_BEEN_INCLUDED | ||
5 | #define OPENVDB_MATH_MAT4_H_HAS_BEEN_INCLUDED | ||
6 | |||
7 | #include <openvdb/Exceptions.h> | ||
8 | #include <openvdb/Platform.h> | ||
9 | #include "Math.h" | ||
10 | #include "Mat3.h" | ||
11 | #include "Vec3.h" | ||
12 | #include "Vec4.h" | ||
13 | #include <algorithm> // for std::copy(), std::swap() | ||
14 | #include <cassert> | ||
15 | #include <iomanip> | ||
16 | #include <cmath> | ||
17 | |||
18 | |||
19 | namespace openvdb { | ||
20 | OPENVDB_USE_VERSION_NAMESPACE | ||
21 | namespace OPENVDB_VERSION_NAME { | ||
22 | namespace math { | ||
23 | |||
24 | template<typename T> class Vec4; | ||
25 | |||
26 | |||
27 | /// @class Mat4 Mat4.h | ||
28 | /// @brief 4x4 -matrix class. | ||
29 | template<typename T> | ||
30 | class Mat4: public Mat<4, T> | ||
31 | { | ||
32 | public: | ||
33 | /// Data type held by the matrix. | ||
34 | using value_type = T; | ||
35 | using ValueType = T; | ||
36 | using MyBase = Mat<4, T>; | ||
37 | |||
38 | /// Trivial constructor, the matrix is NOT initialized | ||
39 | #if OPENVDB_ABI_VERSION_NUMBER >= 8 | ||
40 | /// @note destructor, copy constructor, assignment operator and | ||
41 | /// move constructor are left to be defined by the compiler (default) | ||
42 | Mat4() = default; | ||
43 | #else | ||
44 | Mat4() {} | ||
45 | |||
46 | /// Copy constructor | ||
47 | Mat4(const Mat<4, T> &m) | ||
48 | { | ||
49 | for (int i = 0; i < 4; ++i) { | ||
50 | for (int j = 0; j < 4; ++j) { | ||
51 | MyBase::mm[i*4 + j] = m[i][j]; | ||
52 | } | ||
53 | } | ||
54 | } | ||
55 | #endif | ||
56 | |||
57 | /// Constructor given array of elements, the ordering is in row major form: | ||
58 | /** @verbatim | ||
59 | a[ 0] a[1] a[ 2] a[ 3] | ||
60 | a[ 4] a[5] a[ 6] a[ 7] | ||
61 | a[ 8] a[9] a[10] a[11] | ||
62 | a[12] a[13] a[14] a[15] | ||
63 | @endverbatim */ | ||
64 | template<typename Source> | ||
65 | Mat4(Source *a) | ||
66 | { | ||
67 | for (int i = 0; i < 16; i++) { | ||
68 | MyBase::mm[i] = static_cast<T>(a[i]); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | /// Constructor given array of elements, the ordering is in row major form: | ||
73 | /** @verbatim | ||
74 | a b c d | ||
75 | e f g h | ||
76 | i j k l | ||
77 | m n o p | ||
78 | @endverbatim */ | ||
79 | template<typename Source> | ||
80 | 743978 | Mat4(Source a, Source b, Source c, Source d, | |
81 | Source e, Source f, Source g, Source h, | ||
82 | Source i, Source j, Source k, Source l, | ||
83 | Source m, Source n, Source o, Source p) | ||
84 | { | ||
85 | 743979 | MyBase::mm[ 0] = static_cast<T>(a); | |
86 | 743979 | MyBase::mm[ 1] = static_cast<T>(b); | |
87 | 743979 | MyBase::mm[ 2] = static_cast<T>(c); | |
88 | 743979 | MyBase::mm[ 3] = static_cast<T>(d); | |
89 | |||
90 | 743979 | MyBase::mm[ 4] = static_cast<T>(e); | |
91 | 743979 | MyBase::mm[ 5] = static_cast<T>(f); | |
92 | 743979 | MyBase::mm[ 6] = static_cast<T>(g); | |
93 | 743979 | MyBase::mm[ 7] = static_cast<T>(h); | |
94 | |||
95 | 743979 | MyBase::mm[ 8] = static_cast<T>(i); | |
96 | 743979 | MyBase::mm[ 9] = static_cast<T>(j); | |
97 | 743979 | MyBase::mm[10] = static_cast<T>(k); | |
98 | 743979 | MyBase::mm[11] = static_cast<T>(l); | |
99 | |||
100 | 743979 | MyBase::mm[12] = static_cast<T>(m); | |
101 | 743979 | MyBase::mm[13] = static_cast<T>(n); | |
102 | 743979 | MyBase::mm[14] = static_cast<T>(o); | |
103 |
15/25✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 1 times.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 2 times.
✓ Branch 16 taken 2 times.
✓ Branch 17 taken 1 times.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 2 times.
✓ Branch 23 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 1 times.
✗ Branch 30 not taken.
|
743970 | MyBase::mm[15] = static_cast<T>(p); |
104 | } | ||
105 | |||
106 | /// Construct matrix from rows or columns vectors (defaults to rows | ||
107 | /// for historical reasons) | ||
108 | template<typename Source> | ||
109 | Mat4(const Vec4<Source> &v1, const Vec4<Source> &v2, | ||
110 | const Vec4<Source> &v3, const Vec4<Source> &v4, bool rows = true) | ||
111 | { | ||
112 | if (rows) { | ||
113 | this->setRows(v1, v2, v3, v4); | ||
114 | } else { | ||
115 | this->setColumns(v1, v2, v3, v4); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | /// Conversion constructor | ||
120 | template<typename Source> | ||
121 | explicit Mat4(const Mat4<Source> &m) | ||
122 | { | ||
123 | const Source *src = m.asPointer(); | ||
124 | |||
125 | for (int i=0; i<16; ++i) { | ||
126 | MyBase::mm[i] = static_cast<T>(src[i]); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | /// Predefined constant for identity matrix | ||
131 | 738714 | static const Mat4<T>& identity() { | |
132 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 738712 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
738714 | static const Mat4<T> sIdentity = Mat4<T>( |
133 | 1, 0, 0, 0, | ||
134 | 0, 1, 0, 0, | ||
135 | 0, 0, 1, 0, | ||
136 | 0, 0, 0, 1 | ||
137 | ); | ||
138 | 738714 | return sIdentity; | |
139 | } | ||
140 | |||
141 | /// Predefined constant for zero matrix | ||
142 | 7284032 | static const Mat4<T>& zero() { | |
143 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3642179 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
7284032 | static const Mat4<T> sZero = Mat4<T>( |
144 | 0, 0, 0, 0, | ||
145 | 0, 0, 0, 0, | ||
146 | 0, 0, 0, 0, | ||
147 | 0, 0, 0, 0 | ||
148 | ); | ||
149 | 7284032 | return sZero; | |
150 | } | ||
151 | |||
152 | /// Set ith row to vector v | ||
153 | void setRow(int i, const Vec4<T> &v) | ||
154 | { | ||
155 | // assert(i>=0 && i<4); | ||
156 | int i4 = i * 4; | ||
157 | MyBase::mm[i4+0] = v[0]; | ||
158 | MyBase::mm[i4+1] = v[1]; | ||
159 | MyBase::mm[i4+2] = v[2]; | ||
160 | MyBase::mm[i4+3] = v[3]; | ||
161 | } | ||
162 | |||
163 | /// Get ith row, e.g. Vec4f v = m.row(1); | ||
164 | Vec4<T> row(int i) const | ||
165 | { | ||
166 | // assert(i>=0 && i<3); | ||
167 | return Vec4<T>((*this)(i,0), (*this)(i,1), (*this)(i,2), (*this)(i,3)); | ||
168 | } | ||
169 | |||
170 | /// Set jth column to vector v | ||
171 | void setCol(int j, const Vec4<T>& v) | ||
172 | { | ||
173 | // assert(j>=0 && j<4); | ||
174 | ✗ | MyBase::mm[ 0+j] = v[0]; | |
175 | ✗ | MyBase::mm[ 4+j] = v[1]; | |
176 | ✗ | MyBase::mm[ 8+j] = v[2]; | |
177 | ✗ | MyBase::mm[12+j] = v[3]; | |
178 | } | ||
179 | |||
180 | /// Get jth column, e.g. Vec4f v = m.col(0); | ||
181 | Vec4<T> col(int j) const | ||
182 | { | ||
183 | // assert(j>=0 && j<4); | ||
184 | return Vec4<T>((*this)(0,j), (*this)(1,j), (*this)(2,j), (*this)(3,j)); | ||
185 | } | ||
186 | |||
187 | /// Alternative indexed reference to the elements | ||
188 | /// Note that the indices are row first and column second. | ||
189 | /// e.g. m(0,0) = 1; | ||
190 | T& operator()(int i, int j) | ||
191 | { | ||
192 | // assert(i>=0 && i<4); | ||
193 | // assert(j>=0 && j<4); | ||
194 | return MyBase::mm[4*i+j]; | ||
195 | } | ||
196 | |||
197 | /// Alternative indexed constant reference to the elements, | ||
198 | /// Note that the indices are row first and column second. | ||
199 | /// e.g. float f = m(1,0); | ||
200 | T operator()(int i, int j) const | ||
201 | { | ||
202 | // assert(i>=0 && i<4); | ||
203 | // assert(j>=0 && j<4); | ||
204 |
18/96✓ Branch 0 taken 183 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 663619 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 64 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 64 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 8 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 64 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 8 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 64 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 8 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 64 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 8 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 120 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 16 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 64 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 4 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
|
667515 | return MyBase::mm[4*i+j]; |
205 | } | ||
206 | |||
207 | /// Set the rows of this matrix to the vectors v1, v2, v3, v4 | ||
208 | void setRows(const Vec4<T> &v1, const Vec4<T> &v2, | ||
209 | const Vec4<T> &v3, const Vec4<T> &v4) | ||
210 | { | ||
211 | MyBase::mm[ 0] = v1[0]; | ||
212 | MyBase::mm[ 1] = v1[1]; | ||
213 | MyBase::mm[ 2] = v1[2]; | ||
214 | MyBase::mm[ 3] = v1[3]; | ||
215 | |||
216 | MyBase::mm[ 4] = v2[0]; | ||
217 | MyBase::mm[ 5] = v2[1]; | ||
218 | MyBase::mm[ 6] = v2[2]; | ||
219 | MyBase::mm[ 7] = v2[3]; | ||
220 | |||
221 | MyBase::mm[ 8] = v3[0]; | ||
222 | MyBase::mm[ 9] = v3[1]; | ||
223 | MyBase::mm[10] = v3[2]; | ||
224 | MyBase::mm[11] = v3[3]; | ||
225 | |||
226 | MyBase::mm[12] = v4[0]; | ||
227 | MyBase::mm[13] = v4[1]; | ||
228 | MyBase::mm[14] = v4[2]; | ||
229 | MyBase::mm[15] = v4[3]; | ||
230 | } | ||
231 | |||
232 | /// Set the columns of this matrix to the vectors v1, v2, v3, v4 | ||
233 | void setColumns(const Vec4<T> &v1, const Vec4<T> &v2, | ||
234 | const Vec4<T> &v3, const Vec4<T> &v4) | ||
235 | { | ||
236 | MyBase::mm[ 0] = v1[0]; | ||
237 | MyBase::mm[ 1] = v2[0]; | ||
238 | MyBase::mm[ 2] = v3[0]; | ||
239 | MyBase::mm[ 3] = v4[0]; | ||
240 | |||
241 | MyBase::mm[ 4] = v1[1]; | ||
242 | MyBase::mm[ 5] = v2[1]; | ||
243 | MyBase::mm[ 6] = v3[1]; | ||
244 | MyBase::mm[ 7] = v4[1]; | ||
245 | |||
246 | MyBase::mm[ 8] = v1[2]; | ||
247 | MyBase::mm[ 9] = v2[2]; | ||
248 | MyBase::mm[10] = v3[2]; | ||
249 | MyBase::mm[11] = v4[2]; | ||
250 | |||
251 | MyBase::mm[12] = v1[3]; | ||
252 | MyBase::mm[13] = v2[3]; | ||
253 | MyBase::mm[14] = v3[3]; | ||
254 | MyBase::mm[15] = v4[3]; | ||
255 | } | ||
256 | |||
257 | // Set this matrix to zero | ||
258 | void setZero() | ||
259 | { | ||
260 | MyBase::mm[ 0] = 0; | ||
261 | 10 | MyBase::mm[ 1] = 0; | |
262 | 10 | MyBase::mm[ 2] = 0; | |
263 | 10 | MyBase::mm[ 3] = 0; | |
264 | 10 | MyBase::mm[ 4] = 0; | |
265 | MyBase::mm[ 5] = 0; | ||
266 | 10 | MyBase::mm[ 6] = 0; | |
267 | 10 | MyBase::mm[ 7] = 0; | |
268 | 10 | MyBase::mm[ 8] = 0; | |
269 | 10 | MyBase::mm[ 9] = 0; | |
270 | MyBase::mm[10] = 0; | ||
271 | 10 | MyBase::mm[11] = 0; | |
272 | 10 | MyBase::mm[12] = 0; | |
273 | 10 | MyBase::mm[13] = 0; | |
274 |
10/20✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
|
10 | MyBase::mm[14] = 0; |
275 | MyBase::mm[15] = 0; | ||
276 | } | ||
277 | |||
278 | /// Set this matrix to identity | ||
279 | void setIdentity() | ||
280 | { | ||
281 | 406170 | MyBase::mm[ 0] = 1; | |
282 | 406171 | MyBase::mm[ 1] = 0; | |
283 | 406171 | MyBase::mm[ 2] = 0; | |
284 | 406171 | MyBase::mm[ 3] = 0; | |
285 | |||
286 | 406171 | MyBase::mm[ 4] = 0; | |
287 | 406170 | MyBase::mm[ 5] = 1; | |
288 | 406171 | MyBase::mm[ 6] = 0; | |
289 | 406171 | MyBase::mm[ 7] = 0; | |
290 | |||
291 | 406171 | MyBase::mm[ 8] = 0; | |
292 | 406171 | MyBase::mm[ 9] = 0; | |
293 | 406170 | MyBase::mm[10] = 1; | |
294 | 406171 | MyBase::mm[11] = 0; | |
295 | |||
296 | 406171 | MyBase::mm[12] = 0; | |
297 | 406171 | MyBase::mm[13] = 0; | |
298 | 406171 | MyBase::mm[14] = 0; | |
299 |
2/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
406170 | MyBase::mm[15] = 1; |
300 | } | ||
301 | |||
302 | |||
303 | /// Set upper left to a Mat3 | ||
304 | void setMat3(const Mat3<T> &m) | ||
305 | { | ||
306 |
4/4✓ Branch 0 taken 39 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 3 times.
|
64 | for (int i = 0; i < 3; i++) |
307 |
4/4✓ Branch 0 taken 117 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 9 times.
|
192 | for (int j=0; j < 3; j++) |
308 | 144 | MyBase::mm[i*4+j] = m[i][j]; | |
309 | } | ||
310 | |||
311 | Mat3<T> getMat3() const | ||
312 | { | ||
313 | Mat3<T> m; | ||
314 | |||
315 |
8/12✓ Branch 0 taken 1991460 times.
✓ Branch 1 taken 663820 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 303 times.
✓ Branch 9 taken 101 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
2655712 | for (int i = 0; i < 3; i++) |
316 |
8/12✓ Branch 0 taken 5974380 times.
✓ Branch 1 taken 1991460 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 909 times.
✓ Branch 9 taken 303 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
7967136 | for (int j = 0; j < 3; j++) |
317 | 5975352 | m[i][j] = MyBase::mm[i*4+j]; | |
318 | |||
319 | return m; | ||
320 | } | ||
321 | |||
322 | /// Return the translation component | ||
323 | Vec3<T> getTranslation() const | ||
324 | { | ||
325 | 663558 | return Vec3<T>(MyBase::mm[12], MyBase::mm[13], MyBase::mm[14]); | |
326 | } | ||
327 | |||
328 | void setTranslation(const Vec3<T> &t) | ||
329 | { | ||
330 | 406093 | MyBase::mm[12] = t[0]; | |
331 | 406093 | MyBase::mm[13] = t[1]; | |
332 |
2/30✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 331776 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
|
331789 | MyBase::mm[14] = t[2]; |
333 | 74304 | } | |
334 | |||
335 | /// Assignment operator | ||
336 | template<typename Source> | ||
337 | const Mat4& operator=(const Mat4<Source> &m) | ||
338 | { | ||
339 | const Source *src = m.asPointer(); | ||
340 | |||
341 | // don't suppress warnings when assigning from different numerical types | ||
342 | std::copy(src, (src + this->numElements()), MyBase::mm); | ||
343 | return *this; | ||
344 | } | ||
345 | |||
346 | /// Return @c true if this matrix is equivalent to @a m within a tolerance of @a eps. | ||
347 | bool eq(const Mat4 &m, T eps=1.0e-8) const | ||
348 | { | ||
349 |
95/100✓ Branch 0 taken 3112 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 93 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 80 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 32 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 38 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 32 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 16 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 16 times.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 16 times.
✓ Branch 17 taken 1 times.
✓ Branch 18 taken 16 times.
✓ Branch 19 taken 1 times.
✓ Branch 20 taken 16 times.
✓ Branch 21 taken 1 times.
✓ Branch 22 taken 16 times.
✓ Branch 23 taken 1 times.
✓ Branch 24 taken 16 times.
✓ Branch 25 taken 1 times.
✓ Branch 26 taken 1188880 times.
✓ Branch 27 taken 74305 times.
✓ Branch 28 taken 5308432 times.
✓ Branch 29 taken 331777 times.
✓ Branch 30 taken 16 times.
✓ Branch 31 taken 1 times.
✓ Branch 32 taken 16 times.
✓ Branch 33 taken 1 times.
✓ Branch 34 taken 16 times.
✓ Branch 35 taken 1 times.
✓ Branch 36 taken 16 times.
✓ Branch 37 taken 1 times.
✓ Branch 38 taken 16 times.
✓ Branch 39 taken 1 times.
✓ Branch 40 taken 16 times.
✓ Branch 41 taken 1 times.
✓ Branch 42 taken 16 times.
✓ Branch 43 taken 1 times.
✓ Branch 44 taken 16 times.
✓ Branch 45 taken 1 times.
✓ Branch 46 taken 16 times.
✓ Branch 47 taken 1 times.
✓ Branch 48 taken 16 times.
✓ Branch 49 taken 1 times.
✓ Branch 50 taken 16 times.
✓ Branch 51 taken 1 times.
✓ Branch 52 taken 16 times.
✓ Branch 53 taken 1 times.
✓ Branch 54 taken 16 times.
✓ Branch 55 taken 1 times.
✓ Branch 56 taken 16 times.
✓ Branch 57 taken 1 times.
✓ Branch 58 taken 16 times.
✓ Branch 59 taken 1 times.
✓ Branch 60 taken 16 times.
✓ Branch 61 taken 1 times.
✓ Branch 62 taken 16 times.
✓ Branch 63 taken 1 times.
✓ Branch 64 taken 16 times.
✓ Branch 65 taken 1 times.
✓ Branch 66 taken 16 times.
✓ Branch 67 taken 1 times.
✓ Branch 68 taken 16 times.
✓ Branch 69 taken 1 times.
✓ Branch 70 taken 16 times.
✓ Branch 71 taken 1 times.
✓ Branch 72 taken 16 times.
✓ Branch 73 taken 1 times.
✓ Branch 74 taken 16 times.
✓ Branch 75 taken 1 times.
✓ Branch 76 taken 16 times.
✓ Branch 77 taken 1 times.
✓ Branch 78 taken 16 times.
✓ Branch 79 taken 1 times.
✓ Branch 80 taken 16 times.
✓ Branch 81 taken 1 times.
✓ Branch 82 taken 16 times.
✓ Branch 83 taken 1 times.
✓ Branch 84 taken 16 times.
✓ Branch 85 taken 1 times.
✓ Branch 86 taken 16 times.
✓ Branch 87 taken 1 times.
✓ Branch 88 taken 16 times.
✓ Branch 89 taken 1 times.
✓ Branch 90 taken 16 times.
✓ Branch 91 taken 1 times.
✓ Branch 92 taken 16 times.
✓ Branch 93 taken 1 times.
✓ Branch 94 taken 1 times.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
|
6907605 | for (int i = 0; i < 16; i++) { |
350 |
51/100✓ Branch 0 taken 2890 times.
✓ Branch 1 taken 222 times.
✓ Branch 2 taken 92 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 80 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 32 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 37 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 32 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 16 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 16 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 16 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 16 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 16 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 16 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 16 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1188880 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 5308432 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 16 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 16 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 16 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 16 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 16 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 16 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 16 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 16 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 16 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 16 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 16 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 16 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 16 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 16 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 16 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 16 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 16 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 16 times.
✗ Branch 65 not taken.
✓ Branch 66 taken 16 times.
✗ Branch 67 not taken.
✓ Branch 68 taken 16 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 16 times.
✗ Branch 71 not taken.
✓ Branch 72 taken 16 times.
✗ Branch 73 not taken.
✓ Branch 74 taken 16 times.
✗ Branch 75 not taken.
✓ Branch 76 taken 16 times.
✗ Branch 77 not taken.
✓ Branch 78 taken 16 times.
✗ Branch 79 not taken.
✓ Branch 80 taken 16 times.
✗ Branch 81 not taken.
✓ Branch 82 taken 16 times.
✗ Branch 83 not taken.
✓ Branch 84 taken 16 times.
✗ Branch 85 not taken.
✓ Branch 86 taken 16 times.
✗ Branch 87 not taken.
✓ Branch 88 taken 16 times.
✗ Branch 89 not taken.
✓ Branch 90 taken 16 times.
✗ Branch 91 not taken.
✓ Branch 92 taken 16 times.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✓ Branch 95 taken 1 times.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
|
6501324 | if (!isApproxEqual(MyBase::mm[i], m.mm[i], eps)) |
351 | return false; | ||
352 | } | ||
353 | return true; | ||
354 | } | ||
355 | |||
356 | /// Negation operator, for e.g. m1 = -m2; | ||
357 | 4 | Mat4<T> operator-() const | |
358 | { | ||
359 | return Mat4<T>( | ||
360 | 4 | -MyBase::mm[ 0], -MyBase::mm[ 1], -MyBase::mm[ 2], -MyBase::mm[ 3], | |
361 | 4 | -MyBase::mm[ 4], -MyBase::mm[ 5], -MyBase::mm[ 6], -MyBase::mm[ 7], | |
362 | 4 | -MyBase::mm[ 8], -MyBase::mm[ 9], -MyBase::mm[10], -MyBase::mm[11], | |
363 | 4 | -MyBase::mm[12], -MyBase::mm[13], -MyBase::mm[14], -MyBase::mm[15] | |
364 | 4 | ); | |
365 | } // trivial | ||
366 | |||
367 | /// Multiply each element of this matrix by @a scalar. | ||
368 | template <typename S> | ||
369 | const Mat4<T>& operator*=(S scalar) | ||
370 | { | ||
371 | MyBase::mm[ 0] *= scalar; | ||
372 | MyBase::mm[ 1] *= scalar; | ||
373 | MyBase::mm[ 2] *= scalar; | ||
374 | MyBase::mm[ 3] *= scalar; | ||
375 | |||
376 | MyBase::mm[ 4] *= scalar; | ||
377 | MyBase::mm[ 5] *= scalar; | ||
378 | MyBase::mm[ 6] *= scalar; | ||
379 | MyBase::mm[ 7] *= scalar; | ||
380 | |||
381 | MyBase::mm[ 8] *= scalar; | ||
382 | MyBase::mm[ 9] *= scalar; | ||
383 | MyBase::mm[10] *= scalar; | ||
384 | MyBase::mm[11] *= scalar; | ||
385 | |||
386 | MyBase::mm[12] *= scalar; | ||
387 | MyBase::mm[13] *= scalar; | ||
388 | MyBase::mm[14] *= scalar; | ||
389 | MyBase::mm[15] *= scalar; | ||
390 | return *this; | ||
391 | } | ||
392 | |||
393 | /// Add each element of the given matrix to the corresponding element of this matrix. | ||
394 | template <typename S> | ||
395 | 24 | const Mat4<T> &operator+=(const Mat4<S> &m1) | |
396 | { | ||
397 | const S* s = m1.asPointer(); | ||
398 | |||
399 | 24 | MyBase::mm[ 0] += s[ 0]; | |
400 | 24 | MyBase::mm[ 1] += s[ 1]; | |
401 | 24 | MyBase::mm[ 2] += s[ 2]; | |
402 | 24 | MyBase::mm[ 3] += s[ 3]; | |
403 | |||
404 | 24 | MyBase::mm[ 4] += s[ 4]; | |
405 | 24 | MyBase::mm[ 5] += s[ 5]; | |
406 | 24 | MyBase::mm[ 6] += s[ 6]; | |
407 | 24 | MyBase::mm[ 7] += s[ 7]; | |
408 | |||
409 | 24 | MyBase::mm[ 8] += s[ 8]; | |
410 | 24 | MyBase::mm[ 9] += s[ 9]; | |
411 | 24 | MyBase::mm[10] += s[10]; | |
412 | 24 | MyBase::mm[11] += s[11]; | |
413 | |||
414 | 24 | MyBase::mm[12] += s[12]; | |
415 | 24 | MyBase::mm[13] += s[13]; | |
416 | 24 | MyBase::mm[14] += s[14]; | |
417 | 24 | MyBase::mm[15] += s[15]; | |
418 | |||
419 | 24 | return *this; | |
420 | } | ||
421 | |||
422 | /// Subtract each element of the given matrix from the corresponding element of this matrix. | ||
423 | template <typename S> | ||
424 | 164074 | const Mat4<T> &operator-=(const Mat4<S> &m1) | |
425 | { | ||
426 | const S* s = m1.asPointer(); | ||
427 | |||
428 | 164074 | MyBase::mm[ 0] -= s[ 0]; | |
429 | 164074 | MyBase::mm[ 1] -= s[ 1]; | |
430 | 164074 | MyBase::mm[ 2] -= s[ 2]; | |
431 | 164074 | MyBase::mm[ 3] -= s[ 3]; | |
432 | |||
433 | 164074 | MyBase::mm[ 4] -= s[ 4]; | |
434 | 164074 | MyBase::mm[ 5] -= s[ 5]; | |
435 | 164074 | MyBase::mm[ 6] -= s[ 6]; | |
436 | 164074 | MyBase::mm[ 7] -= s[ 7]; | |
437 | |||
438 | 164074 | MyBase::mm[ 8] -= s[ 8]; | |
439 | 164074 | MyBase::mm[ 9] -= s[ 9]; | |
440 | 164074 | MyBase::mm[10] -= s[10]; | |
441 | 164074 | MyBase::mm[11] -= s[11]; | |
442 | |||
443 | 164074 | MyBase::mm[12] -= s[12]; | |
444 | 164074 | MyBase::mm[13] -= s[13]; | |
445 | 164074 | MyBase::mm[14] -= s[14]; | |
446 | 164074 | MyBase::mm[15] -= s[15]; | |
447 | |||
448 | 164074 | return *this; | |
449 | } | ||
450 | |||
451 | /// Multiply this matrix by the given matrix. | ||
452 | template <typename S> | ||
453 | 1962135 | const Mat4<T> &operator*=(const Mat4<S> &m1) | |
454 | { | ||
455 | 1962135 | Mat4<T> m0(*this); | |
456 | |||
457 | const T* s0 = m0.asPointer(); | ||
458 | const S* s1 = m1.asPointer(); | ||
459 | |||
460 |
2/2✓ Branch 0 taken 7848532 times.
✓ Branch 1 taken 1962133 times.
|
9810675 | for (int i = 0; i < 4; i++) { |
461 | 7848540 | int i4 = 4 * i; | |
462 | 7848540 | MyBase::mm[i4+0] = static_cast<T>(s0[i4+0] * s1[ 0] + | |
463 | 7848540 | s0[i4+1] * s1[ 4] + | |
464 | 7848540 | s0[i4+2] * s1[ 8] + | |
465 | 7848540 | s0[i4+3] * s1[12]); | |
466 | |||
467 | 7848540 | MyBase::mm[i4+1] = static_cast<T>(s0[i4+0] * s1[ 1] + | |
468 | 7848540 | s0[i4+1] * s1[ 5] + | |
469 | 7848540 | s0[i4+2] * s1[ 9] + | |
470 | 7848540 | s0[i4+3] * s1[13]); | |
471 | |||
472 | 7848540 | MyBase::mm[i4+2] = static_cast<T>(s0[i4+0] * s1[ 2] + | |
473 | 7848540 | s0[i4+1] * s1[ 6] + | |
474 | 7848540 | s0[i4+2] * s1[10] + | |
475 | 7848540 | s0[i4+3] * s1[14]); | |
476 | |||
477 | 7848540 | MyBase::mm[i4+3] = static_cast<T>(s0[i4+0] * s1[ 3] + | |
478 | 7848540 | s0[i4+1] * s1[ 7] + | |
479 | 7848540 | s0[i4+2] * s1[11] + | |
480 | 7848540 | s0[i4+3] * s1[15]); | |
481 | } | ||
482 | 1962135 | return *this; | |
483 | } | ||
484 | |||
485 | /// @return transpose of this | ||
486 | Mat4 transpose() const | ||
487 | { | ||
488 | return Mat4<T>( | ||
489 | 87 | MyBase::mm[ 0], MyBase::mm[ 4], MyBase::mm[ 8], MyBase::mm[12], | |
490 | 87 | MyBase::mm[ 1], MyBase::mm[ 5], MyBase::mm[ 9], MyBase::mm[13], | |
491 | 87 | MyBase::mm[ 2], MyBase::mm[ 6], MyBase::mm[10], MyBase::mm[14], | |
492 |
2/6✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
|
87 | MyBase::mm[ 3], MyBase::mm[ 7], MyBase::mm[11], MyBase::mm[15] |
493 | ); | ||
494 | } | ||
495 | |||
496 | |||
497 | /// @return inverse of this | ||
498 | /// @throw ArithmeticError if singular | ||
499 | 380 | Mat4 inverse(T tolerance = 0) const | |
500 | { | ||
501 | // | ||
502 | // inv [ A | b ] = [ E | f ] A: 3x3, b: 3x1, c': 1x3 d: 1x1 | ||
503 | // [ c' | d ] [ g' | h ] | ||
504 | // | ||
505 | // If A is invertible use | ||
506 | // | ||
507 | // E = A^-1 + p*h*r | ||
508 | // p = A^-1 * b | ||
509 | // f = -p * h | ||
510 | // g' = -h * c' | ||
511 | // h = 1 / (d - c'*p) | ||
512 | // r' = c'*A^-1 | ||
513 | // | ||
514 | // Otherwise use gauss-jordan elimination | ||
515 | // | ||
516 | |||
517 | // | ||
518 | // We create this alias to ourself so we can easily use own subscript | ||
519 | // operator. | ||
520 | const Mat4<T>& m(*this); | ||
521 | |||
522 | 380 | T m0011 = m[0][0] * m[1][1]; | |
523 | 380 | T m0012 = m[0][0] * m[1][2]; | |
524 | 380 | T m0110 = m[0][1] * m[1][0]; | |
525 | 380 | T m0210 = m[0][2] * m[1][0]; | |
526 | 380 | T m0120 = m[0][1] * m[2][0]; | |
527 | 380 | T m0220 = m[0][2] * m[2][0]; | |
528 | |||
529 | 380 | T detA = m0011 * m[2][2] - m0012 * m[2][1] - m0110 * m[2][2] | |
530 |
1/2✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
|
380 | + m0210 * m[2][1] + m0120 * m[1][2] - m0220 * m[1][1]; |
531 | |||
532 | bool hasPerspective = | ||
533 |
1/2✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
|
380 | (!isExactlyEqual(m[0][3], T(0.0)) || |
534 |
1/2✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
|
380 | !isExactlyEqual(m[1][3], T(0.0)) || |
535 |
2/4✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 380 times.
|
760 | !isExactlyEqual(m[2][3], T(0.0)) || |
536 | !isExactlyEqual(m[3][3], T(1.0))); | ||
537 | |||
538 | T det; | ||
539 | if (hasPerspective) { | ||
540 | ✗ | det = m[0][3] * det3(m, 1,2,3, 0,2,1) | |
541 | ✗ | + m[1][3] * det3(m, 2,0,3, 0,2,1) | |
542 | ✗ | + m[2][3] * det3(m, 3,0,1, 0,2,1) | |
543 | ✗ | + m[3][3] * detA; | |
544 | } else { | ||
545 | 380 | det = detA * m[3][3]; | |
546 | } | ||
547 | |||
548 | Mat4<T> inv; | ||
549 | bool invertible; | ||
550 | |||
551 |
1/2✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
|
380 | if (isApproxEqual(det,T(0.0),tolerance)) { |
552 | invertible = false; | ||
553 | |||
554 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
|
380 | } else if (isApproxEqual(detA,T(0.0),T(1e-8))) { |
555 | // det is too small to rely on inversion by subblocks | ||
556 | ✗ | invertible = m.invert(inv, tolerance); | |
557 | |||
558 | } else { | ||
559 | invertible = true; | ||
560 | 380 | detA = 1.0 / detA; | |
561 | |||
562 | // | ||
563 | // Calculate A^-1 | ||
564 | // | ||
565 | 380 | inv[0][0] = detA * ( m[1][1] * m[2][2] - m[1][2] * m[2][1]); | |
566 | 380 | inv[0][1] = detA * (-m[0][1] * m[2][2] + m[0][2] * m[2][1]); | |
567 | 380 | inv[0][2] = detA * ( m[0][1] * m[1][2] - m[0][2] * m[1][1]); | |
568 | |||
569 | 380 | inv[1][0] = detA * (-m[1][0] * m[2][2] + m[1][2] * m[2][0]); | |
570 | 380 | inv[1][1] = detA * ( m[0][0] * m[2][2] - m0220); | |
571 | 380 | inv[1][2] = detA * ( m0210 - m0012); | |
572 | |||
573 | 380 | inv[2][0] = detA * ( m[1][0] * m[2][1] - m[1][1] * m[2][0]); | |
574 | 380 | inv[2][1] = detA * ( m0120 - m[0][0] * m[2][1]); | |
575 | 380 | inv[2][2] = detA * ( m0011 - m0110); | |
576 | |||
577 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
|
380 | if (hasPerspective) { |
578 | // | ||
579 | // Calculate r, p, and h | ||
580 | // | ||
581 | Vec3<T> r; | ||
582 | ✗ | r[0] = m[3][0] * inv[0][0] + m[3][1] * inv[1][0] | |
583 | ✗ | + m[3][2] * inv[2][0]; | |
584 | ✗ | r[1] = m[3][0] * inv[0][1] + m[3][1] * inv[1][1] | |
585 | ✗ | + m[3][2] * inv[2][1]; | |
586 | ✗ | r[2] = m[3][0] * inv[0][2] + m[3][1] * inv[1][2] | |
587 | ✗ | + m[3][2] * inv[2][2]; | |
588 | |||
589 | Vec3<T> p; | ||
590 | ✗ | p[0] = inv[0][0] * m[0][3] + inv[0][1] * m[1][3] | |
591 | ✗ | + inv[0][2] * m[2][3]; | |
592 | ✗ | p[1] = inv[1][0] * m[0][3] + inv[1][1] * m[1][3] | |
593 | ✗ | + inv[1][2] * m[2][3]; | |
594 | ✗ | p[2] = inv[2][0] * m[0][3] + inv[2][1] * m[1][3] | |
595 | ✗ | + inv[2][2] * m[2][3]; | |
596 | |||
597 | ✗ | T h = m[3][3] - p.dot(Vec3<T>(m[3][0],m[3][1],m[3][2])); | |
598 | ✗ | if (isApproxEqual(h,T(0.0),tolerance)) { | |
599 | invertible = false; | ||
600 | |||
601 | } else { | ||
602 | ✗ | h = 1.0 / h; | |
603 | |||
604 | // | ||
605 | // Calculate h, g, and f | ||
606 | // | ||
607 | ✗ | inv[3][3] = h; | |
608 | ✗ | inv[3][0] = -h * r[0]; | |
609 | ✗ | inv[3][1] = -h * r[1]; | |
610 | ✗ | inv[3][2] = -h * r[2]; | |
611 | |||
612 | ✗ | inv[0][3] = -h * p[0]; | |
613 | ✗ | inv[1][3] = -h * p[1]; | |
614 | ✗ | inv[2][3] = -h * p[2]; | |
615 | |||
616 | // | ||
617 | // Calculate E | ||
618 | // | ||
619 | p *= h; | ||
620 | ✗ | inv[0][0] += p[0] * r[0]; | |
621 | ✗ | inv[0][1] += p[0] * r[1]; | |
622 | ✗ | inv[0][2] += p[0] * r[2]; | |
623 | ✗ | inv[1][0] += p[1] * r[0]; | |
624 | ✗ | inv[1][1] += p[1] * r[1]; | |
625 | ✗ | inv[1][2] += p[1] * r[2]; | |
626 | ✗ | inv[2][0] += p[2] * r[0]; | |
627 | ✗ | inv[2][1] += p[2] * r[1]; | |
628 | ✗ | inv[2][2] += p[2] * r[2]; | |
629 | } | ||
630 | } else { | ||
631 | // Equations are much simpler in the non-perspective case | ||
632 | 380 | inv[3][0] = - (m[3][0] * inv[0][0] + m[3][1] * inv[1][0] | |
633 | 380 | + m[3][2] * inv[2][0]); | |
634 | 380 | inv[3][1] = - (m[3][0] * inv[0][1] + m[3][1] * inv[1][1] | |
635 | 380 | + m[3][2] * inv[2][1]); | |
636 | 380 | inv[3][2] = - (m[3][0] * inv[0][2] + m[3][1] * inv[1][2] | |
637 | 380 | + m[3][2] * inv[2][2]); | |
638 | 380 | inv[0][3] = 0.0; | |
639 | 380 | inv[1][3] = 0.0; | |
640 | 380 | inv[2][3] = 0.0; | |
641 | 380 | inv[3][3] = 1.0; | |
642 | } | ||
643 | } | ||
644 | |||
645 | ✗ | if (!invertible) OPENVDB_THROW(ArithmeticError, "Inversion of singular 4x4 matrix"); | |
646 | 380 | return inv; | |
647 | } | ||
648 | |||
649 | |||
650 | /// Determinant of matrix | ||
651 | 173 | T det() const | |
652 | { | ||
653 | const T *ap; | ||
654 | Mat3<T> submat; | ||
655 | T det; | ||
656 | T *sp; | ||
657 | int i, j, k, sign; | ||
658 | |||
659 | det = 0; | ||
660 | sign = 1; | ||
661 |
2/2✓ Branch 0 taken 356 times.
✓ Branch 1 taken 89 times.
|
865 | for (i = 0; i < 4; i++) { |
662 | 692 | ap = &MyBase::mm[ 0]; | |
663 | sp = submat.asPointer(); | ||
664 |
2/2✓ Branch 0 taken 1424 times.
✓ Branch 1 taken 356 times.
|
3460 | for (j = 0; j < 4; j++) { |
665 |
2/2✓ Branch 0 taken 5696 times.
✓ Branch 1 taken 1424 times.
|
13840 | for (k = 0; k < 4; k++) { |
666 |
2/2✓ Branch 0 taken 3204 times.
✓ Branch 1 taken 2492 times.
|
11072 | if ((k != i) && (j != 0)) { |
667 | 6228 | *sp++ = *ap; | |
668 | } | ||
669 | 11072 | ap++; | |
670 | } | ||
671 | } | ||
672 | |||
673 | 692 | det += T(sign) * MyBase::mm[i] * submat.det(); | |
674 | 692 | sign = -sign; | |
675 | } | ||
676 | |||
677 | 173 | return det; | |
678 | } | ||
679 | |||
680 | /// Sets the matrix to a matrix that translates by v | ||
681 | static Mat4 translation(const Vec3d& v) | ||
682 | { | ||
683 | return Mat4( | ||
684 | T(1), T(0), T(0), T(0), | ||
685 | T(0), T(1), T(0), T(0), | ||
686 | T(0), T(0), T(1), T(0), | ||
687 | T(v.x()), T(v.y()),T(v.z()), T(1)); | ||
688 | } | ||
689 | |||
690 | /// Sets the matrix to a matrix that translates by v | ||
691 | template <typename T0> | ||
692 | void setToTranslation(const Vec3<T0>& v) | ||
693 | { | ||
694 | ✗ | MyBase::mm[ 0] = 1; | |
695 | ✗ | MyBase::mm[ 1] = 0; | |
696 | ✗ | MyBase::mm[ 2] = 0; | |
697 | ✗ | MyBase::mm[ 3] = 0; | |
698 | |||
699 | ✗ | MyBase::mm[ 4] = 0; | |
700 | ✗ | MyBase::mm[ 5] = 1; | |
701 | ✗ | MyBase::mm[ 6] = 0; | |
702 | ✗ | MyBase::mm[ 7] = 0; | |
703 | |||
704 | ✗ | MyBase::mm[ 8] = 0; | |
705 | ✗ | MyBase::mm[ 9] = 0; | |
706 | ✗ | MyBase::mm[10] = 1; | |
707 | ✗ | MyBase::mm[11] = 0; | |
708 | |||
709 | ✗ | MyBase::mm[12] = v.x(); | |
710 | ✗ | MyBase::mm[13] = v.y(); | |
711 | ✗ | MyBase::mm[14] = v.z(); | |
712 | ✗ | MyBase::mm[15] = 1; | |
713 | } | ||
714 | |||
715 | /// Left multiples by the specified translation, i.e. Trans * (*this) | ||
716 | template <typename T0> | ||
717 | 743785 | void preTranslate(const Vec3<T0>& tr) | |
718 | { | ||
719 | Vec3<T> tmp(tr.x(), tr.y(), tr.z()); | ||
720 | Mat4<T> Tr = Mat4<T>::translation(tmp); | ||
721 | |||
722 | 743785 | *this = Tr * (*this); | |
723 | |||
724 | 743785 | } | |
725 | |||
726 | /// Right multiplies by the specified translation matrix, i.e. (*this) * Trans | ||
727 | template <typename T0> | ||
728 | 45 | void postTranslate(const Vec3<T0>& tr) | |
729 | { | ||
730 | Vec3<T> tmp(tr.x(), tr.y(), tr.z()); | ||
731 | Mat4<T> Tr = Mat4<T>::translation(tmp); | ||
732 | |||
733 | 45 | *this = (*this) * Tr; | |
734 | |||
735 | 45 | } | |
736 | |||
737 | |||
738 | /// Sets the matrix to a matrix that scales by v | ||
739 | template <typename T0> | ||
740 | void setToScale(const Vec3<T0>& v) | ||
741 | { | ||
742 | this->setIdentity(); | ||
743 | 1 | MyBase::mm[ 0] = v.x(); | |
744 | 1 | MyBase::mm[ 5] = v.y(); | |
745 | 1 | MyBase::mm[10] = v.z(); | |
746 | } | ||
747 | |||
748 | // Left multiples by the specified scale matrix, i.e. Sc * (*this) | ||
749 | template <typename T0> | ||
750 | 149499 | void preScale(const Vec3<T0>& v) | |
751 | { | ||
752 | 149499 | MyBase::mm[ 0] *= v.x(); | |
753 | 149499 | MyBase::mm[ 1] *= v.x(); | |
754 | 149499 | MyBase::mm[ 2] *= v.x(); | |
755 | 149499 | MyBase::mm[ 3] *= v.x(); | |
756 | |||
757 | 149499 | MyBase::mm[ 4] *= v.y(); | |
758 | 149499 | MyBase::mm[ 5] *= v.y(); | |
759 | 149499 | MyBase::mm[ 6] *= v.y(); | |
760 | 149499 | MyBase::mm[ 7] *= v.y(); | |
761 | |||
762 | 149499 | MyBase::mm[ 8] *= v.z(); | |
763 | 149499 | MyBase::mm[ 9] *= v.z(); | |
764 | 149499 | MyBase::mm[10] *= v.z(); | |
765 | 149499 | MyBase::mm[11] *= v.z(); | |
766 | 149499 | } | |
767 | |||
768 | |||
769 | |||
770 | // Right multiples by the specified scale matrix, i.e. (*this) * Sc | ||
771 | template <typename T0> | ||
772 | 704 | void postScale(const Vec3<T0>& v) | |
773 | { | ||
774 | |||
775 | 704 | MyBase::mm[ 0] *= v.x(); | |
776 | 704 | MyBase::mm[ 1] *= v.y(); | |
777 | 704 | MyBase::mm[ 2] *= v.z(); | |
778 | |||
779 | 704 | MyBase::mm[ 4] *= v.x(); | |
780 | 704 | MyBase::mm[ 5] *= v.y(); | |
781 | 704 | MyBase::mm[ 6] *= v.z(); | |
782 | |||
783 | 704 | MyBase::mm[ 8] *= v.x(); | |
784 | 704 | MyBase::mm[ 9] *= v.y(); | |
785 | 704 | MyBase::mm[10] *= v.z(); | |
786 | |||
787 | 704 | MyBase::mm[12] *= v.x(); | |
788 | 704 | MyBase::mm[13] *= v.y(); | |
789 | 704 | MyBase::mm[14] *= v.z(); | |
790 | |||
791 | 704 | } | |
792 | |||
793 | |||
794 | /// @brief Sets the matrix to a rotation about the given axis. | ||
795 | /// @param axis The axis (one of X, Y, Z) to rotate about. | ||
796 | /// @param angle The rotation angle, in radians. | ||
797 |
0/3✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | void setToRotation(Axis axis, T angle) {*this = rotation<Mat4<T> >(axis, angle);} |
798 | |||
799 | /// @brief Sets the matrix to a rotation about an arbitrary axis | ||
800 | /// @param axis The axis of rotation (cannot be zero-length) | ||
801 | /// @param angle The rotation angle, in radians. | ||
802 | 7 | void setToRotation(const Vec3<T>& axis, T angle) {*this = rotation<Mat4<T> >(axis, angle);} | |
803 | |||
804 | /// @brief Sets the matrix to a rotation that maps v1 onto v2 about the cross | ||
805 | /// product of v1 and v2. | ||
806 | 14 | void setToRotation(const Vec3<T>& v1, const Vec3<T>& v2) {*this = rotation<Mat4<T> >(v1, v2);} | |
807 | |||
808 | |||
809 | /// @brief Left multiplies by a rotation clock-wiseabout the given axis into this matrix. | ||
810 | /// @param axis The axis (one of X, Y, Z) of rotation. | ||
811 | /// @param angle The clock-wise rotation angle, in radians. | ||
812 | 446302 | void preRotate(Axis axis, T angle) | |
813 | { | ||
814 | 446302 | T c = static_cast<T>(cos(angle)); | |
815 | 446302 | T s = -static_cast<T>(sin(angle)); // the "-" makes it clockwise | |
816 | |||
817 |
3/4✓ Branch 0 taken 148782 times.
✓ Branch 1 taken 148762 times.
✓ Branch 2 taken 148758 times.
✗ Branch 3 not taken.
|
446302 | switch (axis) { |
818 | 148782 | case X_AXIS: | |
819 | { | ||
820 | T a4, a5, a6, a7; | ||
821 | |||
822 | 148782 | a4 = c * MyBase::mm[ 4] - s * MyBase::mm[ 8]; | |
823 | 148782 | a5 = c * MyBase::mm[ 5] - s * MyBase::mm[ 9]; | |
824 | 148782 | a6 = c * MyBase::mm[ 6] - s * MyBase::mm[10]; | |
825 | 148782 | a7 = c * MyBase::mm[ 7] - s * MyBase::mm[11]; | |
826 | |||
827 | |||
828 | 148782 | MyBase::mm[ 8] = s * MyBase::mm[ 4] + c * MyBase::mm[ 8]; | |
829 | 148782 | MyBase::mm[ 9] = s * MyBase::mm[ 5] + c * MyBase::mm[ 9]; | |
830 | 148782 | MyBase::mm[10] = s * MyBase::mm[ 6] + c * MyBase::mm[10]; | |
831 | 148782 | MyBase::mm[11] = s * MyBase::mm[ 7] + c * MyBase::mm[11]; | |
832 | |||
833 | 148782 | MyBase::mm[ 4] = a4; | |
834 | 148782 | MyBase::mm[ 5] = a5; | |
835 | 148782 | MyBase::mm[ 6] = a6; | |
836 | 148782 | MyBase::mm[ 7] = a7; | |
837 | } | ||
838 | 148782 | break; | |
839 | |||
840 | 148762 | case Y_AXIS: | |
841 | { | ||
842 | T a0, a1, a2, a3; | ||
843 | |||
844 | 148762 | a0 = c * MyBase::mm[ 0] + s * MyBase::mm[ 8]; | |
845 | 148762 | a1 = c * MyBase::mm[ 1] + s * MyBase::mm[ 9]; | |
846 | 148762 | a2 = c * MyBase::mm[ 2] + s * MyBase::mm[10]; | |
847 | 148762 | a3 = c * MyBase::mm[ 3] + s * MyBase::mm[11]; | |
848 | |||
849 | 148762 | MyBase::mm[ 8] = -s * MyBase::mm[ 0] + c * MyBase::mm[ 8]; | |
850 | 148762 | MyBase::mm[ 9] = -s * MyBase::mm[ 1] + c * MyBase::mm[ 9]; | |
851 | 148762 | MyBase::mm[10] = -s * MyBase::mm[ 2] + c * MyBase::mm[10]; | |
852 | 148762 | MyBase::mm[11] = -s * MyBase::mm[ 3] + c * MyBase::mm[11]; | |
853 | |||
854 | |||
855 | 148762 | MyBase::mm[ 0] = a0; | |
856 | 148762 | MyBase::mm[ 1] = a1; | |
857 | 148762 | MyBase::mm[ 2] = a2; | |
858 | 148762 | MyBase::mm[ 3] = a3; | |
859 | } | ||
860 | 148762 | break; | |
861 | |||
862 | 148758 | case Z_AXIS: | |
863 | { | ||
864 | T a0, a1, a2, a3; | ||
865 | |||
866 | 148758 | a0 = c * MyBase::mm[ 0] - s * MyBase::mm[ 4]; | |
867 | 148758 | a1 = c * MyBase::mm[ 1] - s * MyBase::mm[ 5]; | |
868 | 148758 | a2 = c * MyBase::mm[ 2] - s * MyBase::mm[ 6]; | |
869 | 148758 | a3 = c * MyBase::mm[ 3] - s * MyBase::mm[ 7]; | |
870 | |||
871 | 148758 | MyBase::mm[ 4] = s * MyBase::mm[ 0] + c * MyBase::mm[ 4]; | |
872 | 148758 | MyBase::mm[ 5] = s * MyBase::mm[ 1] + c * MyBase::mm[ 5]; | |
873 | 148758 | MyBase::mm[ 6] = s * MyBase::mm[ 2] + c * MyBase::mm[ 6]; | |
874 | 148758 | MyBase::mm[ 7] = s * MyBase::mm[ 3] + c * MyBase::mm[ 7]; | |
875 | |||
876 | 148758 | MyBase::mm[ 0] = a0; | |
877 | 148758 | MyBase::mm[ 1] = a1; | |
878 | 148758 | MyBase::mm[ 2] = a2; | |
879 | 148758 | MyBase::mm[ 3] = a3; | |
880 | } | ||
881 | 148758 | break; | |
882 | |||
883 | ✗ | default: | |
884 | ✗ | assert(axis==X_AXIS || axis==Y_AXIS || axis==Z_AXIS); | |
885 | } | ||
886 | 446302 | } | |
887 | |||
888 | |||
889 | /// @brief Right multiplies by a rotation clock-wiseabout the given axis into this matrix. | ||
890 | /// @param axis The axis (one of X, Y, Z) of rotation. | ||
891 | /// @param angle The clock-wise rotation angle, in radians. | ||
892 | 31 | void postRotate(Axis axis, T angle) | |
893 | { | ||
894 | 31 | T c = static_cast<T>(cos(angle)); | |
895 | 31 | T s = -static_cast<T>(sin(angle)); // the "-" makes it clockwise | |
896 | |||
897 | |||
898 | |||
899 |
3/4✓ Branch 0 taken 24 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
31 | switch (axis) { |
900 | 24 | case X_AXIS: | |
901 | { | ||
902 | T a2, a6, a10, a14; | ||
903 | |||
904 | 24 | a2 = c * MyBase::mm[ 2] - s * MyBase::mm[ 1]; | |
905 | 24 | a6 = c * MyBase::mm[ 6] - s * MyBase::mm[ 5]; | |
906 | 24 | a10 = c * MyBase::mm[10] - s * MyBase::mm[ 9]; | |
907 | 24 | a14 = c * MyBase::mm[14] - s * MyBase::mm[13]; | |
908 | |||
909 | |||
910 | 24 | MyBase::mm[ 1] = c * MyBase::mm[ 1] + s * MyBase::mm[ 2]; | |
911 | 24 | MyBase::mm[ 5] = c * MyBase::mm[ 5] + s * MyBase::mm[ 6]; | |
912 | 24 | MyBase::mm[ 9] = c * MyBase::mm[ 9] + s * MyBase::mm[10]; | |
913 | 24 | MyBase::mm[13] = c * MyBase::mm[13] + s * MyBase::mm[14]; | |
914 | |||
915 | 24 | MyBase::mm[ 2] = a2; | |
916 | 24 | MyBase::mm[ 6] = a6; | |
917 | 24 | MyBase::mm[10] = a10; | |
918 | 24 | MyBase::mm[14] = a14; | |
919 | } | ||
920 | 24 | break; | |
921 | |||
922 | 5 | case Y_AXIS: | |
923 | { | ||
924 | T a2, a6, a10, a14; | ||
925 | |||
926 | 5 | a2 = c * MyBase::mm[ 2] + s * MyBase::mm[ 0]; | |
927 | 5 | a6 = c * MyBase::mm[ 6] + s * MyBase::mm[ 4]; | |
928 | 5 | a10 = c * MyBase::mm[10] + s * MyBase::mm[ 8]; | |
929 | 5 | a14 = c * MyBase::mm[14] + s * MyBase::mm[12]; | |
930 | |||
931 | 5 | MyBase::mm[ 0] = c * MyBase::mm[ 0] - s * MyBase::mm[ 2]; | |
932 | 5 | MyBase::mm[ 4] = c * MyBase::mm[ 4] - s * MyBase::mm[ 6]; | |
933 | 5 | MyBase::mm[ 8] = c * MyBase::mm[ 8] - s * MyBase::mm[10]; | |
934 | 5 | MyBase::mm[12] = c * MyBase::mm[12] - s * MyBase::mm[14]; | |
935 | |||
936 | 5 | MyBase::mm[ 2] = a2; | |
937 | 5 | MyBase::mm[ 6] = a6; | |
938 | 5 | MyBase::mm[10] = a10; | |
939 | 5 | MyBase::mm[14] = a14; | |
940 | } | ||
941 | 5 | break; | |
942 | |||
943 | 2 | case Z_AXIS: | |
944 | { | ||
945 | T a1, a5, a9, a13; | ||
946 | |||
947 | 2 | a1 = c * MyBase::mm[ 1] - s * MyBase::mm[ 0]; | |
948 | 2 | a5 = c * MyBase::mm[ 5] - s * MyBase::mm[ 4]; | |
949 | 2 | a9 = c * MyBase::mm[ 9] - s * MyBase::mm[ 8]; | |
950 | 2 | a13 = c * MyBase::mm[13] - s * MyBase::mm[12]; | |
951 | |||
952 | 2 | MyBase::mm[ 0] = c * MyBase::mm[ 0] + s * MyBase::mm[ 1]; | |
953 | 2 | MyBase::mm[ 4] = c * MyBase::mm[ 4] + s * MyBase::mm[ 5]; | |
954 | 2 | MyBase::mm[ 8] = c * MyBase::mm[ 8] + s * MyBase::mm[ 9]; | |
955 | 2 | MyBase::mm[12] = c * MyBase::mm[12] + s * MyBase::mm[13]; | |
956 | |||
957 | 2 | MyBase::mm[ 1] = a1; | |
958 | 2 | MyBase::mm[ 5] = a5; | |
959 | 2 | MyBase::mm[ 9] = a9; | |
960 | 2 | MyBase::mm[13] = a13; | |
961 | |||
962 | } | ||
963 | 2 | break; | |
964 | |||
965 | ✗ | default: | |
966 | ✗ | assert(axis==X_AXIS || axis==Y_AXIS || axis==Z_AXIS); | |
967 | } | ||
968 | 31 | } | |
969 | |||
970 | /// @brief Sets the matrix to a shear along axis0 by a fraction of axis1. | ||
971 | /// @param axis0 The fixed axis of the shear. | ||
972 | /// @param axis1 The shear axis. | ||
973 | /// @param shearby The shear factor. | ||
974 | void setToShear(Axis axis0, Axis axis1, T shearby) | ||
975 | { | ||
976 | 2 | *this = shear<Mat4<T> >(axis0, axis1, shearby); | |
977 | } | ||
978 | |||
979 | |||
980 | /// @brief Left multiplies a shearing transformation into the matrix. | ||
981 | /// @see setToShear | ||
982 | 7 | void preShear(Axis axis0, Axis axis1, T shear) | |
983 | { | ||
984 | 7 | int index0 = static_cast<int>(axis0); | |
985 | 7 | int index1 = static_cast<int>(axis1); | |
986 | |||
987 | // to row "index1" add a multiple of the index0 row | ||
988 | 13 | MyBase::mm[index1 * 4 + 0] += shear * MyBase::mm[index0 * 4 + 0]; | |
989 | 13 | MyBase::mm[index1 * 4 + 1] += shear * MyBase::mm[index0 * 4 + 1]; | |
990 | 13 | MyBase::mm[index1 * 4 + 2] += shear * MyBase::mm[index0 * 4 + 2]; | |
991 | 12 | MyBase::mm[index1 * 4 + 3] += shear * MyBase::mm[index0 * 4 + 3]; | |
992 | 7 | } | |
993 | |||
994 | |||
995 | /// @brief Right multiplies a shearing transformation into the matrix. | ||
996 | /// @see setToShear | ||
997 | 7 | void postShear(Axis axis0, Axis axis1, T shear) | |
998 | { | ||
999 | 7 | int index0 = static_cast<int>(axis0); | |
1000 | 7 | int index1 = static_cast<int>(axis1); | |
1001 | |||
1002 | // to collumn "index0" add a multiple of the index1 row | ||
1003 | 12 | MyBase::mm[index0 + 0] += shear * MyBase::mm[index1 + 0]; | |
1004 | 12 | MyBase::mm[index0 + 4] += shear * MyBase::mm[index1 + 4]; | |
1005 | 12 | MyBase::mm[index0 + 8] += shear * MyBase::mm[index1 + 8]; | |
1006 | 11 | MyBase::mm[index0 + 12] += shear * MyBase::mm[index1 + 12]; | |
1007 | |||
1008 | 8 | } | |
1009 | |||
1010 | /// Transform a Vec4 by post-multiplication. | ||
1011 | template<typename T0> | ||
1012 | Vec4<T0> transform(const Vec4<T0> &v) const | ||
1013 | { | ||
1014 | return static_cast< Vec4<T0> >(v * *this); | ||
1015 | } | ||
1016 | |||
1017 | /// Transform a Vec3 by post-multiplication, without homogenous division. | ||
1018 | template<typename T0> | ||
1019 | 1108081 | Vec3<T0> transform(const Vec3<T0> &v) const | |
1020 | { | ||
1021 | 1108094 | return static_cast< Vec3<T0> >(v * *this); | |
1022 | } | ||
1023 | |||
1024 | /// Transform a Vec4 by pre-multiplication. | ||
1025 | template<typename T0> | ||
1026 | Vec4<T0> pretransform(const Vec4<T0> &v) const | ||
1027 | { | ||
1028 | return static_cast< Vec4<T0> >(*this * v); | ||
1029 | } | ||
1030 | |||
1031 | /// Transform a Vec3 by pre-multiplication, without homogenous division. | ||
1032 | template<typename T0> | ||
1033 | Vec3<T0> pretransform(const Vec3<T0> &v) const | ||
1034 | { | ||
1035 | return static_cast< Vec3<T0> >(*this * v); | ||
1036 | } | ||
1037 | |||
1038 | /// Transform a Vec3 by post-multiplication, doing homogenous divison. | ||
1039 | template<typename T0> | ||
1040 |
1/2✓ Branch 0 taken 55078 times.
✗ Branch 1 not taken.
|
55078 | Vec3<T0> transformH(const Vec3<T0> &p) const |
1041 | { | ||
1042 | T0 w; | ||
1043 | |||
1044 | // w = p * (*this).col(3); | ||
1045 | 55078 | w = static_cast<T0>(p[0] * MyBase::mm[ 3] + p[1] * MyBase::mm[ 7] | |
1046 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
55078 | + p[2] * MyBase::mm[11] + MyBase::mm[15]); |
1047 | |||
1048 |
1/2✓ Branch 0 taken 55078 times.
✗ Branch 1 not taken.
|
55078 | if ( !isExactlyEqual(w , 0.0) ) { |
1049 | 55078 | return Vec3<T0>(static_cast<T0>((p[0] * MyBase::mm[ 0] + p[1] * MyBase::mm[ 4] + | |
1050 | 55078 | p[2] * MyBase::mm[ 8] + MyBase::mm[12]) / w), | |
1051 | 55078 | static_cast<T0>((p[0] * MyBase::mm[ 1] + p[1] * MyBase::mm[ 5] + | |
1052 | 55078 | p[2] * MyBase::mm[ 9] + MyBase::mm[13]) / w), | |
1053 | 55078 | static_cast<T0>((p[0] * MyBase::mm[ 2] + p[1] * MyBase::mm[ 6] + | |
1054 | 55078 | p[2] * MyBase::mm[10] + MyBase::mm[14]) / w)); | |
1055 | } | ||
1056 | |||
1057 | ✗ | return Vec3<T0>(0, 0, 0); | |
1058 | } | ||
1059 | |||
1060 | /// Transform a Vec3 by pre-multiplication, doing homogenous division. | ||
1061 | template<typename T0> | ||
1062 | Vec3<T0> pretransformH(const Vec3<T0> &p) const | ||
1063 | { | ||
1064 | T0 w; | ||
1065 | |||
1066 | // w = p * (*this).col(3); | ||
1067 | w = p[0] * MyBase::mm[12] + p[1] * MyBase::mm[13] + p[2] * MyBase::mm[14] + MyBase::mm[15]; | ||
1068 | |||
1069 | if ( !isExactlyEqual(w , 0.0) ) { | ||
1070 | return Vec3<T0>(static_cast<T0>((p[0] * MyBase::mm[ 0] + p[1] * MyBase::mm[ 1] + | ||
1071 | p[2] * MyBase::mm[ 2] + MyBase::mm[ 3]) / w), | ||
1072 | static_cast<T0>((p[0] * MyBase::mm[ 4] + p[1] * MyBase::mm[ 5] + | ||
1073 | p[2] * MyBase::mm[ 6] + MyBase::mm[ 7]) / w), | ||
1074 | static_cast<T0>((p[0] * MyBase::mm[ 8] + p[1] * MyBase::mm[ 9] + | ||
1075 | p[2] * MyBase::mm[10] + MyBase::mm[11]) / w)); | ||
1076 | } | ||
1077 | |||
1078 | return Vec3<T0>(0, 0, 0); | ||
1079 | } | ||
1080 | |||
1081 | /// Transform a Vec3 by post-multiplication, without translation. | ||
1082 | template<typename T0> | ||
1083 | 112168 | Vec3<T0> transform3x3(const Vec3<T0> &v) const | |
1084 | { | ||
1085 | return Vec3<T0>( | ||
1086 | 112168 | static_cast<T0>(v[0] * MyBase::mm[ 0] + v[1] * MyBase::mm[ 4] + v[2] * MyBase::mm[ 8]), | |
1087 | 112168 | static_cast<T0>(v[0] * MyBase::mm[ 1] + v[1] * MyBase::mm[ 5] + v[2] * MyBase::mm[ 9]), | |
1088 | 112168 | static_cast<T0>(v[0] * MyBase::mm[ 2] + v[1] * MyBase::mm[ 6] + v[2] * MyBase::mm[10])); | |
1089 | } | ||
1090 | |||
1091 | |||
1092 | private: | ||
1093 | bool invert(Mat4<T> &inverse, T tolerance) const; | ||
1094 | |||
1095 | T det2(const Mat4<T> &a, int i0, int i1, int j0, int j1) const { | ||
1096 | int i0row = i0 * 4; | ||
1097 | int i1row = i1 * 4; | ||
1098 | ✗ | return a.mm[i0row+j0]*a.mm[i1row+j1] - a.mm[i0row+j1]*a.mm[i1row+j0]; | |
1099 | } | ||
1100 | |||
1101 | T det3(const Mat4<T> &a, int i0, int i1, int i2, | ||
1102 | int j0, int j1, int j2) const { | ||
1103 | int i0row = i0 * 4; | ||
1104 | ✗ | return a.mm[i0row+j0]*det2(a, i1,i2, j1,j2) + | |
1105 | ✗ | a.mm[i0row+j1]*det2(a, i1,i2, j2,j0) + | |
1106 | ✗ | a.mm[i0row+j2]*det2(a, i1,i2, j0,j1); | |
1107 | } | ||
1108 | }; // class Mat4 | ||
1109 | |||
1110 | |||
1111 | /// @relates Mat4 | ||
1112 | /// @brief Equality operator, does exact floating point comparisons | ||
1113 | template <typename T0, typename T1> | ||
1114 | 83927889 | bool operator==(const Mat4<T0> &m0, const Mat4<T1> &m1) | |
1115 | { | ||
1116 | const T0 *t0 = m0.asPointer(); | ||
1117 | const T1 *t1 = m1.asPointer(); | ||
1118 | |||
1119 |
4/4✓ Branch 0 taken 670329300 times.
✓ Branch 1 taken 41889929 times.
✓ Branch 2 taken 670255280 times.
✓ Branch 3 taken 74020 times.
|
1424438305 | for (int i=0; i<16; ++i) if (!isExactlyEqual(t0[i], t1[i])) return false; |
1120 | return true; | ||
1121 | } | ||
1122 | |||
1123 | /// @relates Mat4 | ||
1124 | /// @brief Inequality operator, does exact floating point comparisons | ||
1125 | template <typename T0, typename T1> | ||
1126 | 83927080 | bool operator!=(const Mat4<T0> &m0, const Mat4<T1> &m1) { return !(m0 == m1); } | |
1127 | |||
1128 | /// @relates Mat4 | ||
1129 | /// @brief Multiply each element of the given matrix by @a scalar and return the result. | ||
1130 | template <typename S, typename T> | ||
1131 | Mat4<typename promote<S, T>::type> operator*(S scalar, const Mat4<T> &m) | ||
1132 | { | ||
1133 | return m*scalar; | ||
1134 | } | ||
1135 | |||
1136 | /// @relates Mat4 | ||
1137 | /// @brief Multiply each element of the given matrix by @a scalar and return the result. | ||
1138 | template <typename S, typename T> | ||
1139 | Mat4<typename promote<S, T>::type> operator*(const Mat4<T> &m, S scalar) | ||
1140 | { | ||
1141 | Mat4<typename promote<S, T>::type> result(m); | ||
1142 | result *= scalar; | ||
1143 | return result; | ||
1144 | } | ||
1145 | |||
1146 | /// @relates Mat4 | ||
1147 | /// @brief Multiply @a _m by @a _v and return the resulting vector. | ||
1148 | template<typename T, typename MT> | ||
1149 | inline Vec4<typename promote<T, MT>::type> | ||
1150 | 296 | operator*(const Mat4<MT> &_m, | |
1151 | const Vec4<T> &_v) | ||
1152 | { | ||
1153 | MT const *m = _m.asPointer(); | ||
1154 | return Vec4<typename promote<T, MT>::type>( | ||
1155 | 296 | _v[0]*m[0] + _v[1]*m[1] + _v[2]*m[2] + _v[3]*m[3], | |
1156 | 296 | _v[0]*m[4] + _v[1]*m[5] + _v[2]*m[6] + _v[3]*m[7], | |
1157 | 296 | _v[0]*m[8] + _v[1]*m[9] + _v[2]*m[10] + _v[3]*m[11], | |
1158 | 296 | _v[0]*m[12] + _v[1]*m[13] + _v[2]*m[14] + _v[3]*m[15]); | |
1159 | } | ||
1160 | |||
1161 | /// @relates Mat4 | ||
1162 | /// @brief Multiply @a _v by @a _m and return the resulting vector. | ||
1163 | template<typename T, typename MT> | ||
1164 | inline Vec4<typename promote<T, MT>::type> | ||
1165 | 296 | operator*(const Vec4<T> &_v, | |
1166 | const Mat4<MT> &_m) | ||
1167 | { | ||
1168 | MT const *m = _m.asPointer(); | ||
1169 | return Vec4<typename promote<T, MT>::type>( | ||
1170 | 296 | _v[0]*m[0] + _v[1]*m[4] + _v[2]*m[8] + _v[3]*m[12], | |
1171 | 296 | _v[0]*m[1] + _v[1]*m[5] + _v[2]*m[9] + _v[3]*m[13], | |
1172 | 296 | _v[0]*m[2] + _v[1]*m[6] + _v[2]*m[10] + _v[3]*m[14], | |
1173 | 296 | _v[0]*m[3] + _v[1]*m[7] + _v[2]*m[11] + _v[3]*m[15]); | |
1174 | } | ||
1175 | |||
1176 | /// @relates Mat4 | ||
1177 | /// @brief Multiply @a _m by @a _v and return the resulting vector. | ||
1178 | template<typename T, typename MT> | ||
1179 | inline Vec3<typename promote<T, MT>::type> | ||
1180 | 592 | operator*(const Mat4<MT> &_m, const Vec3<T> &_v) | |
1181 | { | ||
1182 | MT const *m = _m.asPointer(); | ||
1183 | return Vec3<typename promote<T, MT>::type>( | ||
1184 | 592 | _v[0]*m[0] + _v[1]*m[1] + _v[2]*m[2] + m[3], | |
1185 | 592 | _v[0]*m[4] + _v[1]*m[5] + _v[2]*m[6] + m[7], | |
1186 | 592 | _v[0]*m[8] + _v[1]*m[9] + _v[2]*m[10] + m[11]); | |
1187 | } | ||
1188 | |||
1189 | /// @relates Mat4 | ||
1190 | /// @brief Multiply @a _v by @a _m and return the resulting vector. | ||
1191 | template<typename T, typename MT> | ||
1192 | inline Vec3<typename promote<T, MT>::type> | ||
1193 | 2646490322 | operator*(const Vec3<T> &_v, const Mat4<MT> &_m) | |
1194 | { | ||
1195 | MT const *m = _m.asPointer(); | ||
1196 | return Vec3<typename promote<T, MT>::type>( | ||
1197 | 2646490322 | _v[0]*m[0] + _v[1]*m[4] + _v[2]*m[8] + m[12], | |
1198 | 2646490322 | _v[0]*m[1] + _v[1]*m[5] + _v[2]*m[9] + m[13], | |
1199 | 2646490322 | _v[0]*m[2] + _v[1]*m[6] + _v[2]*m[10] + m[14]); | |
1200 | } | ||
1201 | |||
1202 | /// @relates Mat4 | ||
1203 | /// @brief Add corresponding elements of @a m0 and @a m1 and return the result. | ||
1204 | template <typename T0, typename T1> | ||
1205 | Mat4<typename promote<T0, T1>::type> | ||
1206 | 24 | operator+(const Mat4<T0> &m0, const Mat4<T1> &m1) | |
1207 | { | ||
1208 | 24 | Mat4<typename promote<T0, T1>::type> result(m0); | |
1209 | 24 | result += m1; | |
1210 | 24 | return result; | |
1211 | } | ||
1212 | |||
1213 | /// @relates Mat4 | ||
1214 | /// @brief Subtract corresponding elements of @a m0 and @a m1 and return the result. | ||
1215 | template <typename T0, typename T1> | ||
1216 | Mat4<typename promote<T0, T1>::type> | ||
1217 | 164074 | operator-(const Mat4<T0> &m0, const Mat4<T1> &m1) | |
1218 | { | ||
1219 | 164074 | Mat4<typename promote<T0, T1>::type> result(m0); | |
1220 | 164074 | result -= m1; | |
1221 | 164074 | return result; | |
1222 | } | ||
1223 | |||
1224 | /// @relates Mat4 | ||
1225 | /// @brief Multiply @a m0 by @a m1 and return the resulting matrix. | ||
1226 | template <typename T0, typename T1> | ||
1227 | Mat4<typename promote<T0, T1>::type> | ||
1228 | 1962135 | operator*(const Mat4<T0> &m0, const Mat4<T1> &m1) | |
1229 | { | ||
1230 | 1962135 | Mat4<typename promote<T0, T1>::type> result(m0); | |
1231 | 1962135 | result *= m1; | |
1232 | 1962135 | return result; | |
1233 | } | ||
1234 | |||
1235 | |||
1236 | /// Transform a Vec3 by pre-multiplication, without translation. | ||
1237 | /// Presumes this matrix is inverse of coordinate transform | ||
1238 | /// Synonymous to "pretransform3x3" | ||
1239 | template<typename T0, typename T1> | ||
1240 | Vec3<T1> transformNormal(const Mat4<T0> &m, const Vec3<T1> &n) | ||
1241 | { | ||
1242 | return Vec3<T1>( | ||
1243 | static_cast<T1>(m[0][0]*n[0] + m[0][1]*n[1] + m[0][2]*n[2]), | ||
1244 | static_cast<T1>(m[1][0]*n[0] + m[1][1]*n[1] + m[1][2]*n[2]), | ||
1245 | static_cast<T1>(m[2][0]*n[0] + m[2][1]*n[1] + m[2][2]*n[2])); | ||
1246 | } | ||
1247 | |||
1248 | |||
1249 | /// Invert via gauss-jordan elimination. Modified from dreamworks internal mx library | ||
1250 | template<typename T> | ||
1251 | ✗ | bool Mat4<T>::invert(Mat4<T> &inverse, T tolerance) const | |
1252 | { | ||
1253 | ✗ | Mat4<T> temp(*this); | |
1254 | inverse.setIdentity(); | ||
1255 | |||
1256 | // Forward elimination step | ||
1257 | double det = 1.0; | ||
1258 | ✗ | for (int i = 0; i < 4; ++i) { | |
1259 | int row = i; | ||
1260 | ✗ | double max = fabs(temp[i][i]); | |
1261 | |||
1262 | ✗ | for (int k = i+1; k < 4; ++k) { | |
1263 | ✗ | if (fabs(temp[k][i]) > max) { | |
1264 | row = k; | ||
1265 | max = fabs(temp[k][i]); | ||
1266 | } | ||
1267 | } | ||
1268 | |||
1269 | ✗ | if (isExactlyEqual(max, 0.0)) return false; | |
1270 | |||
1271 | // must move pivot to row i | ||
1272 | ✗ | if (row != i) { | |
1273 | ✗ | det = -det; | |
1274 | ✗ | for (int k = 0; k < 4; ++k) { | |
1275 | ✗ | std::swap(temp[row][k], temp[i][k]); | |
1276 | ✗ | std::swap(inverse[row][k], inverse[i][k]); | |
1277 | } | ||
1278 | } | ||
1279 | |||
1280 | ✗ | double pivot = temp[i][i]; | |
1281 | ✗ | det *= pivot; | |
1282 | |||
1283 | // scale row i | ||
1284 | ✗ | for (int k = 0; k < 4; ++k) { | |
1285 | ✗ | temp[i][k] /= pivot; | |
1286 | ✗ | inverse[i][k] /= pivot; | |
1287 | } | ||
1288 | |||
1289 | // eliminate in rows below i | ||
1290 | ✗ | for (int j = i+1; j < 4; ++j) { | |
1291 | ✗ | double t = temp[j][i]; | |
1292 | ✗ | if (!isExactlyEqual(t, 0.0)) { | |
1293 | // subtract scaled row i from row j | ||
1294 | ✗ | for (int k = 0; k < 4; ++k) { | |
1295 | ✗ | temp[j][k] -= temp[i][k] * t; | |
1296 | ✗ | inverse[j][k] -= inverse[i][k] * t; | |
1297 | } | ||
1298 | } | ||
1299 | } | ||
1300 | } | ||
1301 | |||
1302 | // Backward elimination step | ||
1303 | ✗ | for (int i = 3; i > 0; --i) { | |
1304 | ✗ | for (int j = 0; j < i; ++j) { | |
1305 | ✗ | double t = temp[j][i]; | |
1306 | |||
1307 | ✗ | if (!isExactlyEqual(t, 0.0)) { | |
1308 | ✗ | for (int k = 0; k < 4; ++k) { | |
1309 | ✗ | inverse[j][k] -= inverse[i][k]*t; | |
1310 | } | ||
1311 | } | ||
1312 | } | ||
1313 | } | ||
1314 | ✗ | return det*det >= tolerance*tolerance; | |
1315 | } | ||
1316 | |||
1317 | template <typename T> | ||
1318 | inline bool isAffine(const Mat4<T>& m) { | ||
1319 | return (m.col(3) == Vec4<T>(0, 0, 0, 1)); | ||
1320 | } | ||
1321 | |||
1322 | template <typename T> | ||
1323 | inline bool hasTranslation(const Mat4<T>& m) { | ||
1324 | return (m.row(3) != Vec4<T>(0, 0, 0, 1)); | ||
1325 | } | ||
1326 | |||
1327 | template<typename T> | ||
1328 | inline Mat4<T> | ||
1329 | Abs(const Mat4<T>& m) | ||
1330 | { | ||
1331 | Mat4<T> out; | ||
1332 | const T* ip = m.asPointer(); | ||
1333 | T* op = out.asPointer(); | ||
1334 |
4/4✓ Branch 0 taken 656224 times.
✓ Branch 1 taken 41014 times.
✓ Branch 2 taken 656304 times.
✓ Branch 3 taken 41019 times.
|
1394561 | for (unsigned i = 0; i < 16; ++i, ++op, ++ip) *op = math::Abs(*ip); |
1335 | return out; | ||
1336 | } | ||
1337 | |||
1338 | template<typename Type1, typename Type2> | ||
1339 | inline Mat4<Type1> | ||
1340 | cwiseAdd(const Mat4<Type1>& m, const Type2 s) | ||
1341 | { | ||
1342 | Mat4<Type1> out; | ||
1343 | const Type1* ip = m.asPointer(); | ||
1344 | Type1* op = out.asPointer(); | ||
1345 | ✗ | for (unsigned i = 0; i < 16; ++i, ++op, ++ip) { | |
1346 | OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN | ||
1347 | ✗ | *op = *ip + s; | |
1348 | OPENVDB_NO_TYPE_CONVERSION_WARNING_END | ||
1349 | } | ||
1350 | return out; | ||
1351 | } | ||
1352 | |||
1353 | template<typename T> | ||
1354 | inline bool | ||
1355 | cwiseLessThan(const Mat4<T>& m0, const Mat4<T>& m1) | ||
1356 | { | ||
1357 | return cwiseLessThan<4, T>(m0, m1); | ||
1358 | } | ||
1359 | |||
1360 | template<typename T> | ||
1361 | inline bool | ||
1362 | cwiseGreaterThan(const Mat4<T>& m0, const Mat4<T>& m1) | ||
1363 | { | ||
1364 | return cwiseGreaterThan<4, T>(m0, m1); | ||
1365 | } | ||
1366 | |||
1367 | using Mat4s = Mat4<float>; | ||
1368 | using Mat4d = Mat4<double>; | ||
1369 | using Mat4f = Mat4d; | ||
1370 | |||
1371 | #if OPENVDB_ABI_VERSION_NUMBER >= 8 | ||
1372 | OPENVDB_IS_POD(Mat4s) | ||
1373 | OPENVDB_IS_POD(Mat4d) | ||
1374 | #endif | ||
1375 | |||
1376 | } // namespace math | ||
1377 | |||
1378 | |||
1379 |
0/25✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
|
1714017 | template<> inline math::Mat4s zeroVal<math::Mat4s>() { return math::Mat4s::zero(); } |
1380 |
0/25✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
|
1928135 | template<> inline math::Mat4d zeroVal<math::Mat4d>() { return math::Mat4d::zero(); } |
1381 | |||
1382 | } // namespace OPENVDB_VERSION_NAME | ||
1383 | } // namespace openvdb | ||
1384 | |||
1385 | #endif // OPENVDB_UTIL_MAT4_H_HAS_BEEN_INCLUDED | ||
1386 |