1 /*
2 * Copyright 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "MatTest"
18
19 #include <stdlib.h>
20
21 #include <limits>
22 #include <random>
23 #include <functional>
24
25 #include <gtest/gtest.h>
26
27 #include <math/mat2.h>
28 #include <math/mat4.h>
29
30 namespace android {
31
32 class MatTest : public testing::Test {
33 protected:
34 };
35
TEST_F(MatTest,Basics)36 TEST_F(MatTest, Basics) {
37 mat4 m0;
38 EXPECT_EQ(sizeof(m0), sizeof(float)*16);
39 }
40
TEST_F(MatTest,ComparisonOps)41 TEST_F(MatTest, ComparisonOps) {
42 mat4 m0;
43 mat4 m1(2);
44
45 EXPECT_TRUE(m0 == m0);
46 EXPECT_TRUE(m0 != m1);
47 EXPECT_FALSE(m0 != m0);
48 EXPECT_FALSE(m0 == m1);
49 }
50
TEST_F(MatTest,Constructors)51 TEST_F(MatTest, Constructors) {
52 mat4 m0;
53 ASSERT_EQ(m0[0].x, 1);
54 ASSERT_EQ(m0[0].y, 0);
55 ASSERT_EQ(m0[0].z, 0);
56 ASSERT_EQ(m0[0].w, 0);
57 ASSERT_EQ(m0[1].x, 0);
58 ASSERT_EQ(m0[1].y, 1);
59 ASSERT_EQ(m0[1].z, 0);
60 ASSERT_EQ(m0[1].w, 0);
61 ASSERT_EQ(m0[2].x, 0);
62 ASSERT_EQ(m0[2].y, 0);
63 ASSERT_EQ(m0[2].z, 1);
64 ASSERT_EQ(m0[2].w, 0);
65 ASSERT_EQ(m0[3].x, 0);
66 ASSERT_EQ(m0[3].y, 0);
67 ASSERT_EQ(m0[3].z, 0);
68 ASSERT_EQ(m0[3].w, 1);
69
70 mat4 m1(2);
71 mat4 m2(vec4(2));
72 mat4 m3(m2);
73
74 EXPECT_EQ(m1, m2);
75 EXPECT_EQ(m2, m3);
76 EXPECT_EQ(m3, m1);
77
78 mat4 m4(vec4(1), vec4(2), vec4(3), vec4(4));
79 EXPECT_NE(m4, m1);
80 }
81
TEST_F(MatTest,ArithmeticOps)82 TEST_F(MatTest, ArithmeticOps) {
83 mat4 m0;
84 mat4 m1(2);
85 mat4 m2(vec4(2));
86
87 m1 += m2;
88 EXPECT_EQ(mat4(4), m1);
89
90 m2 -= m1;
91 EXPECT_EQ(mat4(-2), m2);
92
93 m1 *= 2;
94 EXPECT_EQ(mat4(8), m1);
95
96 m1 /= 2;
97 EXPECT_EQ(mat4(4), m1);
98
99 m0 = -m0;
100 EXPECT_EQ(mat4(-1), m0);
101 }
102
TEST_F(MatTest,UnaryOps)103 TEST_F(MatTest, UnaryOps) {
104 const mat4 identity;
105 mat4 m0;
106
107 m0 = -m0;
108 EXPECT_EQ(mat4(vec4(-1, 0, 0, 0),
109 vec4(0, -1, 0, 0),
110 vec4(0, 0, -1, 0),
111 vec4(0, 0, 0, -1)), m0);
112
113 m0 = -m0;
114 EXPECT_EQ(identity, m0);
115 }
116
TEST_F(MatTest,MiscOps)117 TEST_F(MatTest, MiscOps) {
118 const mat4 identity;
119 mat4 m0;
120 EXPECT_EQ(4, trace(m0));
121
122 mat4 m1(vec4(1, 2, 3, 4), vec4(5, 6, 7, 8), vec4(9, 10, 11, 12), vec4(13, 14, 15, 16));
123 mat4 m2(vec4(1, 5, 9, 13), vec4(2, 6, 10, 14), vec4(3, 7, 11, 15), vec4(4, 8, 12, 16));
124 EXPECT_EQ(m1, transpose(m2));
125 EXPECT_EQ(m2, transpose(m1));
126 EXPECT_EQ(vec4(1, 6, 11, 16), diag(m1));
127
128 EXPECT_EQ(identity, inverse(identity));
129
130 mat4 m3(vec4(4, 3, 0, 0), vec4(3, 2, 0, 0), vec4(0, 0, 1, 0), vec4(0, 0, 0, 1));
131 mat4 m3i(inverse(m3));
132 EXPECT_FLOAT_EQ(-2, m3i[0][0]);
133 EXPECT_FLOAT_EQ(3, m3i[0][1]);
134 EXPECT_FLOAT_EQ(3, m3i[1][0]);
135 EXPECT_FLOAT_EQ(-4, m3i[1][1]);
136
137 mat4 m3ii(inverse(m3i));
138 EXPECT_FLOAT_EQ(m3[0][0], m3ii[0][0]);
139 EXPECT_FLOAT_EQ(m3[0][1], m3ii[0][1]);
140 EXPECT_FLOAT_EQ(m3[1][0], m3ii[1][0]);
141 EXPECT_FLOAT_EQ(m3[1][1], m3ii[1][1]);
142
143 EXPECT_EQ(m1, m1*identity);
144
145
146 for (size_t c=0 ; c<4 ; c++) {
147 for (size_t r=0 ; r<4 ; r++) {
148 EXPECT_FLOAT_EQ(m1[c][r], m1(r, c));
149 }
150 }
151 }
152
TEST_F(MatTest,ElementAccess)153 TEST_F(MatTest, ElementAccess) {
154 mat4 m(vec4(1, 2, 3, 4), vec4(5, 6, 7, 8), vec4(9, 10, 11, 12), vec4(13, 14, 15, 16));
155 for (size_t c=0 ; c<4 ; c++) {
156 for (size_t r=0 ; r<4 ; r++) {
157 EXPECT_FLOAT_EQ(m[c][r], m(r, c));
158 }
159 }
160
161 m(3,2) = 100;
162 EXPECT_FLOAT_EQ(m[2][3], 100);
163 EXPECT_FLOAT_EQ(m(3, 2), 100);
164 }
165
166 //------------------------------------------------------------------------------
167 // MAT 3
168 //------------------------------------------------------------------------------
169
170 class Mat3Test : public testing::Test {
171 protected:
172 };
173
TEST_F(Mat3Test,Basics)174 TEST_F(Mat3Test, Basics) {
175 mat3 m0;
176 EXPECT_EQ(sizeof(m0), sizeof(float)*9);
177 }
178
TEST_F(Mat3Test,ComparisonOps)179 TEST_F(Mat3Test, ComparisonOps) {
180 mat3 m0;
181 mat3 m1(2);
182
183 EXPECT_TRUE(m0 == m0);
184 EXPECT_TRUE(m0 != m1);
185 EXPECT_FALSE(m0 != m0);
186 EXPECT_FALSE(m0 == m1);
187 }
188
TEST_F(Mat3Test,Constructors)189 TEST_F(Mat3Test, Constructors) {
190 mat3 m0;
191 ASSERT_EQ(m0[0].x, 1);
192 ASSERT_EQ(m0[0].y, 0);
193 ASSERT_EQ(m0[0].z, 0);
194 ASSERT_EQ(m0[1].x, 0);
195 ASSERT_EQ(m0[1].y, 1);
196 ASSERT_EQ(m0[1].z, 0);
197 ASSERT_EQ(m0[2].x, 0);
198 ASSERT_EQ(m0[2].y, 0);
199 ASSERT_EQ(m0[2].z, 1);
200
201 mat3 m1(2);
202 mat3 m2(vec3(2));
203 mat3 m3(m2);
204
205 EXPECT_EQ(m1, m2);
206 EXPECT_EQ(m2, m3);
207 EXPECT_EQ(m3, m1);
208 }
209
TEST_F(Mat3Test,ArithmeticOps)210 TEST_F(Mat3Test, ArithmeticOps) {
211 mat3 m0;
212 mat3 m1(2);
213 mat3 m2(vec3(2));
214
215 m1 += m2;
216 EXPECT_EQ(mat3(4), m1);
217
218 m2 -= m1;
219 EXPECT_EQ(mat3(-2), m2);
220
221 m1 *= 2;
222 EXPECT_EQ(mat3(8), m1);
223
224 m1 /= 2;
225 EXPECT_EQ(mat3(4), m1);
226
227 m0 = -m0;
228 EXPECT_EQ(mat3(-1), m0);
229 }
230
TEST_F(Mat3Test,UnaryOps)231 TEST_F(Mat3Test, UnaryOps) {
232 const mat3 identity;
233 mat3 m0;
234
235 m0 = -m0;
236 EXPECT_EQ(mat3(vec3(-1, 0, 0),
237 vec3(0, -1, 0),
238 vec3(0, 0, -1)), m0);
239
240 m0 = -m0;
241 EXPECT_EQ(identity, m0);
242 }
243
TEST_F(Mat3Test,MiscOps)244 TEST_F(Mat3Test, MiscOps) {
245 const mat3 identity;
246 mat3 m0;
247 EXPECT_EQ(3, trace(m0));
248
249 mat3 m1(vec3(1, 2, 3), vec3(4, 5, 6), vec3(7, 8, 9));
250 mat3 m2(vec3(1, 4, 7), vec3(2, 5, 8), vec3(3, 6, 9));
251 EXPECT_EQ(m1, transpose(m2));
252 EXPECT_EQ(m2, transpose(m1));
253 EXPECT_EQ(vec3(1, 5, 9), diag(m1));
254
255 EXPECT_EQ(identity, inverse(identity));
256
257 mat3 m3(vec3(4, 3, 0), vec3(3, 2, 0), vec3(0, 0, 1));
258 mat3 m3i(inverse(m3));
259 EXPECT_FLOAT_EQ(-2, m3i[0][0]);
260 EXPECT_FLOAT_EQ(3, m3i[0][1]);
261 EXPECT_FLOAT_EQ(3, m3i[1][0]);
262 EXPECT_FLOAT_EQ(-4, m3i[1][1]);
263
264 mat3 m3ii(inverse(m3i));
265 EXPECT_FLOAT_EQ(m3[0][0], m3ii[0][0]);
266 EXPECT_FLOAT_EQ(m3[0][1], m3ii[0][1]);
267 EXPECT_FLOAT_EQ(m3[1][0], m3ii[1][0]);
268 EXPECT_FLOAT_EQ(m3[1][1], m3ii[1][1]);
269
270 EXPECT_EQ(m1, m1*identity);
271 }
272
273 //------------------------------------------------------------------------------
274 // MAT 2
275 //------------------------------------------------------------------------------
276
277 class Mat2Test : public testing::Test {
278 protected:
279 };
280
TEST_F(Mat2Test,Basics)281 TEST_F(Mat2Test, Basics) {
282 mat2 m0;
283 EXPECT_EQ(sizeof(m0), sizeof(float)*4);
284 }
285
TEST_F(Mat2Test,ComparisonOps)286 TEST_F(Mat2Test, ComparisonOps) {
287 mat2 m0;
288 mat2 m1(2);
289
290 EXPECT_TRUE(m0 == m0);
291 EXPECT_TRUE(m0 != m1);
292 EXPECT_FALSE(m0 != m0);
293 EXPECT_FALSE(m0 == m1);
294 }
295
TEST_F(Mat2Test,Constructors)296 TEST_F(Mat2Test, Constructors) {
297 mat2 m0;
298 ASSERT_EQ(m0[0].x, 1);
299 ASSERT_EQ(m0[0].y, 0);
300 ASSERT_EQ(m0[1].x, 0);
301 ASSERT_EQ(m0[1].y, 1);
302
303 mat2 m1(2);
304 mat2 m2(vec2(2));
305 mat2 m3(m2);
306
307 EXPECT_EQ(m1, m2);
308 EXPECT_EQ(m2, m3);
309 EXPECT_EQ(m3, m1);
310 }
311
TEST_F(Mat2Test,ArithmeticOps)312 TEST_F(Mat2Test, ArithmeticOps) {
313 mat2 m0;
314 mat2 m1(2);
315 mat2 m2(vec2(2));
316
317 m1 += m2;
318 EXPECT_EQ(mat2(4), m1);
319
320 m2 -= m1;
321 EXPECT_EQ(mat2(-2), m2);
322
323 m1 *= 2;
324 EXPECT_EQ(mat2(8), m1);
325
326 m1 /= 2;
327 EXPECT_EQ(mat2(4), m1);
328
329 m0 = -m0;
330 EXPECT_EQ(mat2(-1), m0);
331 }
332
TEST_F(Mat2Test,UnaryOps)333 TEST_F(Mat2Test, UnaryOps) {
334 const mat2 identity;
335 mat2 m0;
336
337 m0 = -m0;
338 EXPECT_EQ(mat2(vec2(-1, 0),
339 vec2(0, -1)), m0);
340
341 m0 = -m0;
342 EXPECT_EQ(identity, m0);
343 }
344
TEST_F(Mat2Test,MiscOps)345 TEST_F(Mat2Test, MiscOps) {
346 const mat2 identity;
347 mat2 m0;
348 EXPECT_EQ(2, trace(m0));
349
350 mat2 m1(vec2(1, 2), vec2(3, 4));
351 mat2 m2(vec2(1, 3), vec2(2, 4));
352 EXPECT_EQ(m1, transpose(m2));
353 EXPECT_EQ(m2, transpose(m1));
354 EXPECT_EQ(vec2(1, 4), diag(m1));
355
356 EXPECT_EQ(identity, inverse(identity));
357
358 EXPECT_EQ(m1, m1*identity);
359 }
360
361 //------------------------------------------------------------------------------
362 // MORE MATRIX TESTS
363 //------------------------------------------------------------------------------
364
365 template <typename T>
366 class MatTestT : public ::testing::Test {
367 public:
368 };
369
370 typedef ::testing::Types<float,float> TestMatrixValueTypes;
371
372 TYPED_TEST_CASE(MatTestT, TestMatrixValueTypes);
373
374 #define TEST_MATRIX_INVERSE(MATRIX, EPSILON) \
375 { \
376 typedef decltype(MATRIX) MatrixType; \
377 MatrixType inv1 = inverse(MATRIX); \
378 MatrixType ident1 = MATRIX * inv1; \
379 static const MatrixType IDENTITY; \
380 for (size_t row = 0; row < MatrixType::ROW_SIZE; ++row) { \
381 for (size_t col = 0; col < MatrixType::COL_SIZE; ++col) { \
382 EXPECT_NEAR(ident1[row][col], IDENTITY[row][col], EPSILON); \
383 } \
384 } \
385 }
386
TYPED_TEST(MatTestT,Inverse4)387 TYPED_TEST(MatTestT, Inverse4) {
388 typedef ::android::details::TMat44<TypeParam> M44T;
389
390 M44T m1(1, 0, 0, 0,
391 0, 1, 0, 0,
392 0, 0, 1, 0,
393 0, 0, 0, 1);
394
395 M44T m2(0, -1, 0, 0,
396 1, 0, 0, 0,
397 0, 0, 1, 0,
398 0, 0, 0, 1);
399
400 M44T m3(1, 0, 0, 0,
401 0, 2, 0, 0,
402 0, 0, 0, 1,
403 0, 0, -1, 0);
404
405 M44T m4(
406 4.683281e-01, 1.251189e-02, -8.834660e-01, -4.726541e+00,
407 -8.749647e-01, 1.456563e-01, -4.617587e-01, 3.044795e+00,
408 1.229049e-01, 9.892561e-01, 7.916244e-02, -6.737138e+00,
409 0.000000e+00, 0.000000e+00, 0.000000e+00, 1.000000e+00);
410
411 M44T m5(
412 4.683281e-01, 1.251189e-02, -8.834660e-01, -4.726541e+00,
413 -8.749647e-01, 1.456563e-01, -4.617587e-01, 3.044795e+00,
414 1.229049e-01, 9.892561e-01, 7.916244e-02, -6.737138e+00,
415 1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00);
416
417 TEST_MATRIX_INVERSE(m1, 0);
418 TEST_MATRIX_INVERSE(m2, 0);
419 TEST_MATRIX_INVERSE(m3, 0);
420 TEST_MATRIX_INVERSE(m4, 20.0 * std::numeric_limits<TypeParam>::epsilon());
421 TEST_MATRIX_INVERSE(m5, 20.0 * std::numeric_limits<TypeParam>::epsilon());
422 }
423
424 //------------------------------------------------------------------------------
TYPED_TEST(MatTestT,Inverse3)425 TYPED_TEST(MatTestT, Inverse3) {
426 typedef ::android::details::TMat33<TypeParam> M33T;
427
428 M33T m1(1, 0, 0,
429 0, 1, 0,
430 0, 0, 1);
431
432 M33T m2(0, -1, 0,
433 1, 0, 0,
434 0, 0, 1);
435
436 M33T m3(2, 0, 0,
437 0, 0, 1,
438 0, -1, 0);
439
440 M33T m4(
441 4.683281e-01, 1.251189e-02, 0.000000e+00,
442 -8.749647e-01, 1.456563e-01, 0.000000e+00,
443 0.000000e+00, 0.000000e+00, 1.000000e+00);
444
445 M33T m5(
446 4.683281e-01, 1.251189e-02, -8.834660e-01,
447 -8.749647e-01, 1.456563e-01, -4.617587e-01,
448 1.229049e-01, 9.892561e-01, 7.916244e-02);
449
450 TEST_MATRIX_INVERSE(m1, 0);
451 TEST_MATRIX_INVERSE(m2, 0);
452 TEST_MATRIX_INVERSE(m3, 0);
453 TEST_MATRIX_INVERSE(m4, 20.0 * std::numeric_limits<TypeParam>::epsilon());
454 TEST_MATRIX_INVERSE(m5, 20.0 * std::numeric_limits<TypeParam>::epsilon());
455 }
456
457 //------------------------------------------------------------------------------
TYPED_TEST(MatTestT,Inverse2)458 TYPED_TEST(MatTestT, Inverse2) {
459 typedef ::android::details::TMat22<TypeParam> M22T;
460
461 M22T m1(1, 0,
462 0, 1);
463
464 M22T m2(0, -1,
465 1, 0);
466
467 M22T m3(
468 4.683281e-01, 1.251189e-02,
469 -8.749647e-01, 1.456563e-01);
470
471 M22T m4(
472 4.683281e-01, 1.251189e-02,
473 -8.749647e-01, 1.456563e-01);
474
475 TEST_MATRIX_INVERSE(m1, 0);
476 TEST_MATRIX_INVERSE(m2, 0);
477 TEST_MATRIX_INVERSE(m3, 20.0 * std::numeric_limits<TypeParam>::epsilon());
478 TEST_MATRIX_INVERSE(m4, 20.0 * std::numeric_limits<TypeParam>::epsilon());
479 }
480
481 //------------------------------------------------------------------------------
482 // A macro to help with vector comparisons within floating point range.
483 #define EXPECT_VEC_EQ(VEC1, VEC2) \
484 do { \
485 const decltype(VEC1) v1 = VEC1; \
486 const decltype(VEC2) v2 = VEC2; \
487 if (std::is_same<TypeParam,float>::value) { \
488 for (size_t i = 0; i < v1.size(); ++i) { \
489 EXPECT_FLOAT_EQ(v1[i], v2[i]); \
490 } \
491 } else if (std::is_same<TypeParam,double>::value) { \
492 for (size_t i = 0; i < v1.size(); ++i) { \
493 EXPECT_DOUBLE_EQ(v1[i], v2[i]); \
494 } \
495 } else { \
496 for (size_t i = 0; i < v1.size(); ++i) { \
497 EXPECT_EQ(v1[i], v2[i]); \
498 } \
499 } \
500 } while(0)
501
502 //------------------------------------------------------------------------------
503 // A macro to help with type comparisons within floating point range.
504 #define ASSERT_TYPE_EQ(T1, T2) \
505 do { \
506 const decltype(T1) t1 = T1; \
507 const decltype(T2) t2 = T2; \
508 if (std::is_same<TypeParam,float>::value) { \
509 ASSERT_FLOAT_EQ(t1, t2); \
510 } else if (std::is_same<TypeParam,double>::value) { \
511 ASSERT_DOUBLE_EQ(t1, t2); \
512 } else { \
513 ASSERT_EQ(t1, t2); \
514 } \
515 } while(0)
516
517 //------------------------------------------------------------------------------
518 // Test some translation stuff.
TYPED_TEST(MatTestT,Translation4)519 TYPED_TEST(MatTestT, Translation4) {
520 typedef ::android::details::TMat44<TypeParam> M44T;
521 typedef ::android::details::TVec4<TypeParam> V4T;
522
523 V4T translateBy(-7.3, 1.1, 14.4, 0.0);
524 V4T translation(translateBy[0], translateBy[1], translateBy[2], 1.0);
525 M44T translation_matrix = M44T::translate(translation);
526
527 V4T p1(9.9, 3.1, 41.1, 1.0);
528 V4T p2(-18.0, 0.0, 1.77, 1.0);
529 V4T p3(0, 0, 0, 1);
530 V4T p4(-1000, -1000, 1000, 1.0);
531
532 EXPECT_VEC_EQ(translation_matrix * p1, translateBy + p1);
533 EXPECT_VEC_EQ(translation_matrix * p2, translateBy + p2);
534 EXPECT_VEC_EQ(translation_matrix * p3, translateBy + p3);
535 EXPECT_VEC_EQ(translation_matrix * p4, translateBy + p4);
536 }
537
538 //------------------------------------------------------------------------------
539 template <typename MATRIX>
verifyOrthonormal(const MATRIX & A)540 static void verifyOrthonormal(const MATRIX& A) {
541 typedef typename MATRIX::value_type T;
542
543 static constexpr T value_eps = T(100) * std::numeric_limits<T>::epsilon();
544
545 const MATRIX prod = A * transpose(A);
546 for (size_t i = 0; i < MATRIX::NUM_COLS; ++i) {
547 for (size_t j = 0; j < MATRIX::NUM_ROWS; ++j) {
548 if (i == j) {
549 ASSERT_NEAR(prod[i][j], T(1), value_eps);
550 } else {
551 ASSERT_NEAR(prod[i][j], T(0), value_eps);
552 }
553 }
554 }
555 }
556
557 //------------------------------------------------------------------------------
558 // Test euler code.
TYPED_TEST(MatTestT,EulerZYX_44)559 TYPED_TEST(MatTestT, EulerZYX_44) {
560 typedef ::android::details::TMat44<TypeParam> M44T;
561
562 std::default_random_engine generator(82828);
563 std::uniform_real_distribution<float> distribution(-6.0 * 2.0*M_PI, 6.0 * 2.0*M_PI);
564 auto rand_gen = std::bind(distribution, generator);
565
566 for (size_t i = 0; i < 100; ++i) {
567 M44T m = M44T::eulerZYX(rand_gen(), rand_gen(), rand_gen());
568 verifyOrthonormal(m);
569 }
570
571 M44T m = M44T::eulerZYX(1, 2, 3);
572 verifyOrthonormal(m);
573 }
574
575 //------------------------------------------------------------------------------
576 // Test euler code.
TYPED_TEST(MatTestT,EulerZYX_33)577 TYPED_TEST(MatTestT, EulerZYX_33) {
578
579 typedef ::android::details::TMat33<TypeParam> M33T;
580
581 std::default_random_engine generator(112233);
582 std::uniform_real_distribution<float> distribution(-6.0 * 2.0*M_PI, 6.0 * 2.0*M_PI);
583 auto rand_gen = std::bind(distribution, generator);
584
585 for (size_t i = 0; i < 100; ++i) {
586 M33T m = M33T::eulerZYX(rand_gen(), rand_gen(), rand_gen());
587 verifyOrthonormal(m);
588 }
589
590 M33T m = M33T::eulerZYX(1, 2, 3);
591 verifyOrthonormal(m);
592 }
593
594 //------------------------------------------------------------------------------
595 // Test to quaternion with post translation.
TYPED_TEST(MatTestT,ToQuaternionPostTranslation)596 TYPED_TEST(MatTestT, ToQuaternionPostTranslation) {
597
598 typedef ::android::details::TMat44<TypeParam> M44T;
599 typedef ::android::details::TVec4<TypeParam> V4T;
600 typedef ::android::details::TQuaternion<TypeParam> QuatT;
601
602 std::default_random_engine generator(112233);
603 std::uniform_real_distribution<float> distribution(-6.0 * 2.0*M_PI, 6.0 * 2.0*M_PI);
604 auto rand_gen = std::bind(distribution, generator);
605
606 for (size_t i = 0; i < 100; ++i) {
607 M44T r = M44T::eulerZYX(rand_gen(), rand_gen(), rand_gen());
608 M44T t = M44T::translate(V4T(rand_gen(), rand_gen(), rand_gen(), 1));
609 QuatT qr = r.toQuaternion();
610 M44T tr = t * r;
611 QuatT qtr = tr.toQuaternion();
612
613 ASSERT_TYPE_EQ(qr.x, qtr.x);
614 ASSERT_TYPE_EQ(qr.y, qtr.y);
615 ASSERT_TYPE_EQ(qr.z, qtr.z);
616 ASSERT_TYPE_EQ(qr.w, qtr.w);
617 }
618
619 M44T r = M44T::eulerZYX(1, 2, 3);
620 M44T t = M44T::translate(V4T(20, -15, 2, 1));
621 QuatT qr = r.toQuaternion();
622 M44T tr = t * r;
623 QuatT qtr = tr.toQuaternion();
624
625 ASSERT_TYPE_EQ(qr.x, qtr.x);
626 ASSERT_TYPE_EQ(qr.y, qtr.y);
627 ASSERT_TYPE_EQ(qr.z, qtr.z);
628 ASSERT_TYPE_EQ(qr.w, qtr.w);
629 }
630
631 //------------------------------------------------------------------------------
632 // Test to quaternion with post translation.
TYPED_TEST(MatTestT,ToQuaternionPointTransformation33)633 TYPED_TEST(MatTestT, ToQuaternionPointTransformation33) {
634 static constexpr TypeParam value_eps =
635 TypeParam(1000) * std::numeric_limits<TypeParam>::epsilon();
636
637 typedef ::android::details::TMat33<TypeParam> M33T;
638 typedef ::android::details::TVec3<TypeParam> V3T;
639 typedef ::android::details::TQuaternion<TypeParam> QuatT;
640
641 std::default_random_engine generator(112233);
642 std::uniform_real_distribution<float> distribution(-100.0, 100.0);
643 auto rand_gen = std::bind(distribution, generator);
644
645 for (size_t i = 0; i < 100; ++i) {
646 M33T r = M33T::eulerZYX(rand_gen(), rand_gen(), rand_gen());
647 QuatT qr = r.toQuaternion();
648 V3T p(rand_gen(), rand_gen(), rand_gen());
649
650 V3T pr = r * p;
651 V3T pq = qr * p;
652
653 ASSERT_NEAR(pr.x, pq.x, value_eps);
654 ASSERT_NEAR(pr.y, pq.y, value_eps);
655 ASSERT_NEAR(pr.z, pq.z, value_eps);
656 }
657 }
658
659 //------------------------------------------------------------------------------
660 // Test to quaternion with post translation.
TYPED_TEST(MatTestT,ToQuaternionPointTransformation44)661 TYPED_TEST(MatTestT, ToQuaternionPointTransformation44) {
662 static constexpr TypeParam value_eps =
663 TypeParam(1000) * std::numeric_limits<TypeParam>::epsilon();
664
665 typedef ::android::details::TMat44<TypeParam> M44T;
666 typedef ::android::details::TVec4<TypeParam> V4T;
667 typedef ::android::details::TVec3<TypeParam> V3T;
668 typedef ::android::details::TQuaternion<TypeParam> QuatT;
669
670 std::default_random_engine generator(992626);
671 std::uniform_real_distribution<float> distribution(-100.0, 100.0);
672 auto rand_gen = std::bind(distribution, generator);
673
674 for (size_t i = 0; i < 100; ++i) {
675 M44T r = M44T::eulerZYX(rand_gen(), rand_gen(), rand_gen());
676 QuatT qr = r.toQuaternion();
677 V3T p(rand_gen(), rand_gen(), rand_gen());
678
679 V4T pr = r * V4T(p.x, p.y, p.z, 1);
680 pr.x /= pr.w;
681 pr.y /= pr.w;
682 pr.z /= pr.w;
683 V3T pq = qr * p;
684
685 ASSERT_NEAR(pr.x, pq.x, value_eps);
686 ASSERT_NEAR(pr.y, pq.y, value_eps);
687 ASSERT_NEAR(pr.z, pq.z, value_eps);
688 }
689 }
690
691 #undef TEST_MATRIX_INVERSE
692
693 }; // namespace android
694