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 36 TEST_F(MatTest, Basics) { 37 mat4 m0; 38 EXPECT_EQ(sizeof(m0), sizeof(float)*16); 39 } 40 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 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 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 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 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 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 174 TEST_F(Mat3Test, Basics) { 175 mat3 m0; 176 EXPECT_EQ(sizeof(m0), sizeof(float)*9); 177 } 178 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 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 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 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 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 281 TEST_F(Mat2Test, Basics) { 282 mat2 m0; 283 EXPECT_EQ(sizeof(m0), sizeof(float)*4); 284 } 285 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 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 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 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 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 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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. 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> 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. 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. 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. 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. 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. 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