OLD | NEW |
(Empty) | |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "config.h" |
| 6 |
| 7 #include <public/WebTransformationMatrix.h> |
| 8 |
| 9 #include "CCLayerTreeTestCommon.h" |
| 10 #include <gtest/gtest.h> |
| 11 #include <wtf/MathExtras.h> |
| 12 |
| 13 #define EXPECT_ROW1_EQ(a, b, c, d, matrix) \ |
| 14 EXPECT_FLOAT_EQ((a), (matrix).m11()); \ |
| 15 EXPECT_FLOAT_EQ((b), (matrix).m21()); \ |
| 16 EXPECT_FLOAT_EQ((c), (matrix).m31()); \ |
| 17 EXPECT_FLOAT_EQ((d), (matrix).m41()); |
| 18 |
| 19 #define EXPECT_ROW2_EQ(a, b, c, d, matrix) \ |
| 20 EXPECT_FLOAT_EQ((a), (matrix).m12()); \ |
| 21 EXPECT_FLOAT_EQ((b), (matrix).m22()); \ |
| 22 EXPECT_FLOAT_EQ((c), (matrix).m32()); \ |
| 23 EXPECT_FLOAT_EQ((d), (matrix).m42()); |
| 24 |
| 25 #define EXPECT_ROW3_EQ(a, b, c, d, matrix) \ |
| 26 EXPECT_FLOAT_EQ((a), (matrix).m13()); \ |
| 27 EXPECT_FLOAT_EQ((b), (matrix).m23()); \ |
| 28 EXPECT_FLOAT_EQ((c), (matrix).m33()); \ |
| 29 EXPECT_FLOAT_EQ((d), (matrix).m43()); |
| 30 |
| 31 #define EXPECT_ROW4_EQ(a, b, c, d, matrix) \ |
| 32 EXPECT_FLOAT_EQ((a), (matrix).m14()); \ |
| 33 EXPECT_FLOAT_EQ((b), (matrix).m24()); \ |
| 34 EXPECT_FLOAT_EQ((c), (matrix).m34()); \ |
| 35 EXPECT_FLOAT_EQ((d), (matrix).m44()); \ |
| 36 |
| 37 // Checking float values for equality close to zero is not robust using EXPECT_F
LOAT_EQ |
| 38 // (see gtest documentation). So, to verify rotation matrices, we must use a loo
ser |
| 39 // absolute error threshold in some places. |
| 40 #define EXPECT_ROW1_NEAR(a, b, c, d, matrix, errorThreshold) \ |
| 41 EXPECT_NEAR((a), (matrix).m11(), (errorThreshold)); \ |
| 42 EXPECT_NEAR((b), (matrix).m21(), (errorThreshold)); \ |
| 43 EXPECT_NEAR((c), (matrix).m31(), (errorThreshold)); \ |
| 44 EXPECT_NEAR((d), (matrix).m41(), (errorThreshold)); |
| 45 |
| 46 #define EXPECT_ROW2_NEAR(a, b, c, d, matrix, errorThreshold) \ |
| 47 EXPECT_NEAR((a), (matrix).m12(), (errorThreshold)); \ |
| 48 EXPECT_NEAR((b), (matrix).m22(), (errorThreshold)); \ |
| 49 EXPECT_NEAR((c), (matrix).m32(), (errorThreshold)); \ |
| 50 EXPECT_NEAR((d), (matrix).m42(), (errorThreshold)); |
| 51 |
| 52 #define EXPECT_ROW3_NEAR(a, b, c, d, matrix, errorThreshold) \ |
| 53 EXPECT_NEAR((a), (matrix).m13(), (errorThreshold)); \ |
| 54 EXPECT_NEAR((b), (matrix).m23(), (errorThreshold)); \ |
| 55 EXPECT_NEAR((c), (matrix).m33(), (errorThreshold)); \ |
| 56 EXPECT_NEAR((d), (matrix).m43(), (errorThreshold)); |
| 57 |
| 58 #define ERROR_THRESHOLD 1e-14 |
| 59 #define LOOSE_ERROR_THRESHOLD 1e-7 |
| 60 |
| 61 using namespace WebKit; |
| 62 |
| 63 namespace { |
| 64 |
| 65 static void initializeTestMatrix(WebTransformationMatrix& transform) |
| 66 { |
| 67 transform.setM11(10); |
| 68 transform.setM12(11); |
| 69 transform.setM13(12); |
| 70 transform.setM14(13); |
| 71 transform.setM21(14); |
| 72 transform.setM22(15); |
| 73 transform.setM23(16); |
| 74 transform.setM24(17); |
| 75 transform.setM31(18); |
| 76 transform.setM32(19); |
| 77 transform.setM33(20); |
| 78 transform.setM34(21); |
| 79 transform.setM41(22); |
| 80 transform.setM42(23); |
| 81 transform.setM43(24); |
| 82 transform.setM44(25); |
| 83 |
| 84 // Sanity check |
| 85 EXPECT_ROW1_EQ(10, 14, 18, 22, transform); |
| 86 EXPECT_ROW2_EQ(11, 15, 19, 23, transform); |
| 87 EXPECT_ROW3_EQ(12, 16, 20, 24, transform); |
| 88 EXPECT_ROW4_EQ(13, 17, 21, 25, transform); |
| 89 } |
| 90 |
| 91 static void initializeTestMatrix2(WebTransformationMatrix& transform) |
| 92 { |
| 93 transform.setM11(30); |
| 94 transform.setM12(31); |
| 95 transform.setM13(32); |
| 96 transform.setM14(33); |
| 97 transform.setM21(34); |
| 98 transform.setM22(35); |
| 99 transform.setM23(36); |
| 100 transform.setM24(37); |
| 101 transform.setM31(38); |
| 102 transform.setM32(39); |
| 103 transform.setM33(40); |
| 104 transform.setM34(41); |
| 105 transform.setM41(42); |
| 106 transform.setM42(43); |
| 107 transform.setM43(44); |
| 108 transform.setM44(45); |
| 109 |
| 110 // Sanity check |
| 111 EXPECT_ROW1_EQ(30, 34, 38, 42, transform); |
| 112 EXPECT_ROW2_EQ(31, 35, 39, 43, transform); |
| 113 EXPECT_ROW3_EQ(32, 36, 40, 44, transform); |
| 114 EXPECT_ROW4_EQ(33, 37, 41, 45, transform); |
| 115 } |
| 116 |
| 117 TEST(WebTransformationMatrixTest, verifyDefaultConstructorCreatesIdentityMatrix) |
| 118 { |
| 119 WebTransformationMatrix A; |
| 120 EXPECT_ROW1_EQ(1, 0, 0, 0, A); |
| 121 EXPECT_ROW2_EQ(0, 1, 0, 0, A); |
| 122 EXPECT_ROW3_EQ(0, 0, 1, 0, A); |
| 123 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 124 EXPECT_TRUE(A.isIdentity()); |
| 125 } |
| 126 |
| 127 TEST(WebTransformationMatrixTest, verifyConstructorFor2dElements) |
| 128 { |
| 129 WebTransformationMatrix A(1, 2, 3, 4, 5, 6); |
| 130 EXPECT_ROW1_EQ(1, 3, 0, 5, A); |
| 131 EXPECT_ROW2_EQ(2, 4, 0, 6, A); |
| 132 EXPECT_ROW3_EQ(0, 0, 1, 0, A); |
| 133 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 134 } |
| 135 |
| 136 TEST(WebTransformationMatrixTest, verifyConstructorForAllElements) |
| 137 { |
| 138 WebTransformationMatrix A(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16); |
| 139 EXPECT_ROW1_EQ(1, 5, 9, 13, A); |
| 140 EXPECT_ROW2_EQ(2, 6, 10, 14, A); |
| 141 EXPECT_ROW3_EQ(3, 7, 11, 15, A); |
| 142 EXPECT_ROW4_EQ(4, 8, 12, 16, A); |
| 143 } |
| 144 |
| 145 TEST(WebTransformationMatrixTest, verifyCopyConstructor) |
| 146 { |
| 147 WebTransformationMatrix A; |
| 148 initializeTestMatrix(A); |
| 149 |
| 150 // Copy constructor should produce exact same elements as matrix A. |
| 151 WebTransformationMatrix B(A); |
| 152 EXPECT_ROW1_EQ(10, 14, 18, 22, B); |
| 153 EXPECT_ROW2_EQ(11, 15, 19, 23, B); |
| 154 EXPECT_ROW3_EQ(12, 16, 20, 24, B); |
| 155 EXPECT_ROW4_EQ(13, 17, 21, 25, B); |
| 156 } |
| 157 |
| 158 TEST(WebTransformationMatrixTest, verifyMatrixInversion) |
| 159 { |
| 160 // Invert a translation |
| 161 WebTransformationMatrix translation; |
| 162 translation.translate3d(2, 3, 4); |
| 163 EXPECT_TRUE(translation.isInvertible()); |
| 164 |
| 165 WebTransformationMatrix inverseTranslation = translation.inverse(); |
| 166 EXPECT_ROW1_EQ(1, 0, 0, -2, inverseTranslation); |
| 167 EXPECT_ROW2_EQ(0, 1, 0, -3, inverseTranslation); |
| 168 EXPECT_ROW3_EQ(0, 0, 1, -4, inverseTranslation); |
| 169 EXPECT_ROW4_EQ(0, 0, 0, 1, inverseTranslation); |
| 170 |
| 171 // Note that inversion should not have changed the original matrix. |
| 172 EXPECT_ROW1_EQ(1, 0, 0, 2, translation); |
| 173 EXPECT_ROW2_EQ(0, 1, 0, 3, translation); |
| 174 EXPECT_ROW3_EQ(0, 0, 1, 4, translation); |
| 175 EXPECT_ROW4_EQ(0, 0, 0, 1, translation); |
| 176 |
| 177 // Invert a non-uniform scale |
| 178 WebTransformationMatrix scale; |
| 179 scale.scale3d(4, 10, 100); |
| 180 EXPECT_TRUE(scale.isInvertible()); |
| 181 |
| 182 WebTransformationMatrix inverseScale = scale.inverse(); |
| 183 EXPECT_ROW1_EQ(0.25, 0, 0, 0, inverseScale); |
| 184 EXPECT_ROW2_EQ(0, .1f, 0, 0, inverseScale); |
| 185 EXPECT_ROW3_EQ(0, 0, .01f, 0, inverseScale); |
| 186 EXPECT_ROW4_EQ(0, 0, 0, 1, inverseScale); |
| 187 |
| 188 // Try to invert a matrix that is not invertible. |
| 189 // The inverse() function should simply return an identity matrix. |
| 190 WebTransformationMatrix notInvertible; |
| 191 notInvertible.setM11(0); |
| 192 notInvertible.setM22(0); |
| 193 notInvertible.setM33(0); |
| 194 notInvertible.setM44(0); |
| 195 EXPECT_FALSE(notInvertible.isInvertible()); |
| 196 |
| 197 WebTransformationMatrix inverseOfNotInvertible; |
| 198 initializeTestMatrix(inverseOfNotInvertible); // initialize this to somethin
g non-identity, to make sure that assignment below actually took place. |
| 199 inverseOfNotInvertible = notInvertible.inverse(); |
| 200 EXPECT_TRUE(inverseOfNotInvertible.isIdentity()); |
| 201 } |
| 202 |
| 203 TEST(WebTransformationMatrixTest, verifyTo2DTransform) |
| 204 { |
| 205 WebTransformationMatrix A; |
| 206 initializeTestMatrix(A); |
| 207 |
| 208 WebTransformationMatrix B = A.to2dTransform(); |
| 209 |
| 210 EXPECT_ROW1_EQ(10, 14, 0, 22, B); |
| 211 EXPECT_ROW2_EQ(11, 15, 0, 23, B); |
| 212 EXPECT_ROW3_EQ(0, 0, 1, 0, B); |
| 213 EXPECT_ROW4_EQ(13, 17, 0, 25, B); |
| 214 |
| 215 // Note that to2DTransform should not have changed the original matrix. |
| 216 EXPECT_ROW1_EQ(10, 14, 18, 22, A); |
| 217 EXPECT_ROW2_EQ(11, 15, 19, 23, A); |
| 218 EXPECT_ROW3_EQ(12, 16, 20, 24, A); |
| 219 EXPECT_ROW4_EQ(13, 17, 21, 25, A); |
| 220 } |
| 221 |
| 222 TEST(WebTransformationMatrixTest, verifyAssignmentOperator) |
| 223 { |
| 224 WebTransformationMatrix A; |
| 225 initializeTestMatrix(A); |
| 226 WebTransformationMatrix B; |
| 227 initializeTestMatrix2(B); |
| 228 WebTransformationMatrix C; |
| 229 initializeTestMatrix2(C); |
| 230 C = B = A; |
| 231 |
| 232 // Both B and C should now have been re-assigned to the value of A. |
| 233 EXPECT_ROW1_EQ(10, 14, 18, 22, B); |
| 234 EXPECT_ROW2_EQ(11, 15, 19, 23, B); |
| 235 EXPECT_ROW3_EQ(12, 16, 20, 24, B); |
| 236 EXPECT_ROW4_EQ(13, 17, 21, 25, B); |
| 237 |
| 238 EXPECT_ROW1_EQ(10, 14, 18, 22, C); |
| 239 EXPECT_ROW2_EQ(11, 15, 19, 23, C); |
| 240 EXPECT_ROW3_EQ(12, 16, 20, 24, C); |
| 241 EXPECT_ROW4_EQ(13, 17, 21, 25, C); |
| 242 } |
| 243 |
| 244 TEST(WebTransformationMatrixTest, verifyEqualsBooleanOperator) |
| 245 { |
| 246 WebTransformationMatrix A; |
| 247 initializeTestMatrix(A); |
| 248 |
| 249 WebTransformationMatrix B; |
| 250 initializeTestMatrix(B); |
| 251 EXPECT_TRUE(A == B); |
| 252 |
| 253 // Modifying multiple elements should cause equals operator to return false. |
| 254 WebTransformationMatrix C; |
| 255 initializeTestMatrix2(C); |
| 256 EXPECT_FALSE(A == C); |
| 257 |
| 258 // Modifying any one individual element should cause equals operator to retu
rn false. |
| 259 WebTransformationMatrix D; |
| 260 D = A; |
| 261 D.setM11(0); |
| 262 EXPECT_FALSE(A == D); |
| 263 |
| 264 D = A; |
| 265 D.setM12(0); |
| 266 EXPECT_FALSE(A == D); |
| 267 |
| 268 D = A; |
| 269 D.setM13(0); |
| 270 EXPECT_FALSE(A == D); |
| 271 |
| 272 D = A; |
| 273 D.setM14(0); |
| 274 EXPECT_FALSE(A == D); |
| 275 |
| 276 D = A; |
| 277 D.setM21(0); |
| 278 EXPECT_FALSE(A == D); |
| 279 |
| 280 D = A; |
| 281 D.setM22(0); |
| 282 EXPECT_FALSE(A == D); |
| 283 |
| 284 D = A; |
| 285 D.setM23(0); |
| 286 EXPECT_FALSE(A == D); |
| 287 |
| 288 D = A; |
| 289 D.setM24(0); |
| 290 EXPECT_FALSE(A == D); |
| 291 |
| 292 D = A; |
| 293 D.setM31(0); |
| 294 EXPECT_FALSE(A == D); |
| 295 |
| 296 D = A; |
| 297 D.setM32(0); |
| 298 EXPECT_FALSE(A == D); |
| 299 |
| 300 D = A; |
| 301 D.setM33(0); |
| 302 EXPECT_FALSE(A == D); |
| 303 |
| 304 D = A; |
| 305 D.setM34(0); |
| 306 EXPECT_FALSE(A == D); |
| 307 |
| 308 D = A; |
| 309 D.setM41(0); |
| 310 EXPECT_FALSE(A == D); |
| 311 |
| 312 D = A; |
| 313 D.setM42(0); |
| 314 EXPECT_FALSE(A == D); |
| 315 |
| 316 D = A; |
| 317 D.setM43(0); |
| 318 EXPECT_FALSE(A == D); |
| 319 |
| 320 D = A; |
| 321 D.setM44(0); |
| 322 EXPECT_FALSE(A == D); |
| 323 } |
| 324 |
| 325 TEST(WebTransformationMatrixTest, verifyMultiplyOperator) |
| 326 { |
| 327 WebTransformationMatrix A; |
| 328 initializeTestMatrix(A); |
| 329 |
| 330 WebTransformationMatrix B; |
| 331 initializeTestMatrix2(B); |
| 332 |
| 333 WebTransformationMatrix C = A * B; |
| 334 EXPECT_ROW1_EQ(2036, 2292, 2548, 2804, C); |
| 335 EXPECT_ROW2_EQ(2162, 2434, 2706, 2978, C); |
| 336 EXPECT_ROW3_EQ(2288, 2576, 2864, 3152, C); |
| 337 EXPECT_ROW4_EQ(2414, 2718, 3022, 3326, C); |
| 338 |
| 339 // Just an additional sanity check; matrix multiplication is not commutative
. |
| 340 EXPECT_FALSE(A * B == B * A); |
| 341 } |
| 342 |
| 343 TEST(WebTransformationMatrixTest, verifyMatrixMultiplication) |
| 344 { |
| 345 WebTransformationMatrix A; |
| 346 initializeTestMatrix(A); |
| 347 |
| 348 WebTransformationMatrix B; |
| 349 initializeTestMatrix2(B); |
| 350 |
| 351 A.multiply(B); |
| 352 EXPECT_ROW1_EQ(2036, 2292, 2548, 2804, A); |
| 353 EXPECT_ROW2_EQ(2162, 2434, 2706, 2978, A); |
| 354 EXPECT_ROW3_EQ(2288, 2576, 2864, 3152, A); |
| 355 EXPECT_ROW4_EQ(2414, 2718, 3022, 3326, A); |
| 356 } |
| 357 |
| 358 TEST(WebTransformationMatrixTest, verifyMakeIdentiy) |
| 359 { |
| 360 WebTransformationMatrix A; |
| 361 initializeTestMatrix(A); |
| 362 A.makeIdentity(); |
| 363 EXPECT_ROW1_EQ(1, 0, 0, 0, A); |
| 364 EXPECT_ROW2_EQ(0, 1, 0, 0, A); |
| 365 EXPECT_ROW3_EQ(0, 0, 1, 0, A); |
| 366 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 367 EXPECT_TRUE(A.isIdentity()); |
| 368 } |
| 369 |
| 370 TEST(WebTransformationMatrixTest, verifyTranslate) |
| 371 { |
| 372 WebTransformationMatrix A; |
| 373 A.translate(2, 3); |
| 374 EXPECT_ROW1_EQ(1, 0, 0, 2, A); |
| 375 EXPECT_ROW2_EQ(0, 1, 0, 3, A); |
| 376 EXPECT_ROW3_EQ(0, 0, 1, 0, A); |
| 377 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 378 |
| 379 // Verify that translate() post-multiplies the existing matrix. |
| 380 A.makeIdentity(); |
| 381 A.scale(5); |
| 382 A.translate(2, 3); |
| 383 EXPECT_ROW1_EQ(5, 0, 0, 10, A); |
| 384 EXPECT_ROW2_EQ(0, 5, 0, 15, A); |
| 385 EXPECT_ROW3_EQ(0, 0, 1, 0, A); |
| 386 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 387 } |
| 388 |
| 389 TEST(WebTransformationMatrixTest, verifyTranslate3d) |
| 390 { |
| 391 WebTransformationMatrix A; |
| 392 A.translate3d(2, 3, 4); |
| 393 EXPECT_ROW1_EQ(1, 0, 0, 2, A); |
| 394 EXPECT_ROW2_EQ(0, 1, 0, 3, A); |
| 395 EXPECT_ROW3_EQ(0, 0, 1, 4, A); |
| 396 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 397 |
| 398 // Verify that translate3d() post-multiplies the existing matrix. |
| 399 A.makeIdentity(); |
| 400 A.scale3d(6, 7, 8); |
| 401 A.translate3d(2, 3, 4); |
| 402 EXPECT_ROW1_EQ(6, 0, 0, 12, A); |
| 403 EXPECT_ROW2_EQ(0, 7, 0, 21, A); |
| 404 EXPECT_ROW3_EQ(0, 0, 8, 32, A); |
| 405 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 406 } |
| 407 |
| 408 TEST(WebTransformationMatrixTest, verifyTranslateRight3d) |
| 409 { |
| 410 WebTransformationMatrix A; |
| 411 A.translateRight3d(2, 3, 4); |
| 412 EXPECT_ROW1_EQ(1, 0, 0, 2, A); |
| 413 EXPECT_ROW2_EQ(0, 1, 0, 3, A); |
| 414 EXPECT_ROW3_EQ(0, 0, 1, 4, A); |
| 415 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 416 |
| 417 // Note carefully, all other operations do post-multiply, this one is unique
. |
| 418 // Verify that translateRight3d() PRE-multiplies the existing matrix. |
| 419 A.makeIdentity(); |
| 420 A.scale3d(6, 7, 8); |
| 421 A.translateRight3d(2, 3, 4); |
| 422 EXPECT_ROW1_EQ(6, 0, 0, 2, A); |
| 423 EXPECT_ROW2_EQ(0, 7, 0, 3, A); |
| 424 EXPECT_ROW3_EQ(0, 0, 8, 4, A); |
| 425 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 426 } |
| 427 |
| 428 TEST(WebTransformationMatrixTest, verifyScale) |
| 429 { |
| 430 WebTransformationMatrix A; |
| 431 A.scale(5); |
| 432 EXPECT_ROW1_EQ(5, 0, 0, 0, A); |
| 433 EXPECT_ROW2_EQ(0, 5, 0, 0, A); |
| 434 EXPECT_ROW3_EQ(0, 0, 1, 0, A); |
| 435 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 436 |
| 437 // Verify that scale() post-multiplies the existing matrix. |
| 438 A.makeIdentity(); |
| 439 A.translate3d(2, 3, 4); |
| 440 A.scale(5); |
| 441 EXPECT_ROW1_EQ(5, 0, 0, 2, A); |
| 442 EXPECT_ROW2_EQ(0, 5, 0, 3, A); |
| 443 EXPECT_ROW3_EQ(0, 0, 1, 4, A); |
| 444 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 445 } |
| 446 |
| 447 TEST(WebTransformationMatrixTest, verifyNonUniformScale) |
| 448 { |
| 449 WebTransformationMatrix A; |
| 450 A.scaleNonUniform(6, 7); |
| 451 EXPECT_ROW1_EQ(6, 0, 0, 0, A); |
| 452 EXPECT_ROW2_EQ(0, 7, 0, 0, A); |
| 453 EXPECT_ROW3_EQ(0, 0, 1, 0, A); |
| 454 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 455 |
| 456 // Verify that scaleNonUniform() post-multiplies the existing matrix. |
| 457 A.makeIdentity(); |
| 458 A.translate3d(2, 3, 4); |
| 459 A.scaleNonUniform(6, 7); |
| 460 EXPECT_ROW1_EQ(6, 0, 0, 2, A); |
| 461 EXPECT_ROW2_EQ(0, 7, 0, 3, A); |
| 462 EXPECT_ROW3_EQ(0, 0, 1, 4, A); |
| 463 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 464 } |
| 465 |
| 466 TEST(WebTransformationMatrixTest, verifyScale3d) |
| 467 { |
| 468 WebTransformationMatrix A; |
| 469 A.scale3d(6, 7, 8); |
| 470 EXPECT_ROW1_EQ(6, 0, 0, 0, A); |
| 471 EXPECT_ROW2_EQ(0, 7, 0, 0, A); |
| 472 EXPECT_ROW3_EQ(0, 0, 8, 0, A); |
| 473 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 474 |
| 475 // Verify that scale3d() post-multiplies the existing matrix. |
| 476 A.makeIdentity(); |
| 477 A.translate3d(2, 3, 4); |
| 478 A.scale3d(6, 7, 8); |
| 479 EXPECT_ROW1_EQ(6, 0, 0, 2, A); |
| 480 EXPECT_ROW2_EQ(0, 7, 0, 3, A); |
| 481 EXPECT_ROW3_EQ(0, 0, 8, 4, A); |
| 482 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 483 } |
| 484 |
| 485 TEST(WebTransformationMatrixTest, verifyRotate) |
| 486 { |
| 487 WebTransformationMatrix A; |
| 488 A.rotate(90); |
| 489 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD); |
| 490 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD); |
| 491 EXPECT_ROW3_EQ(0, 0, 1, 0, A); |
| 492 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 493 |
| 494 // Verify that rotate() post-multiplies the existing matrix. |
| 495 A.makeIdentity(); |
| 496 A.scale3d(6, 7, 8); |
| 497 A.rotate(90); |
| 498 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD); |
| 499 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD); |
| 500 EXPECT_ROW3_EQ(0, 0, 8, 0, A); |
| 501 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 502 } |
| 503 |
| 504 TEST(WebTransformationMatrixTest, verifyRotate3d) |
| 505 { |
| 506 WebTransformationMatrix A; |
| 507 |
| 508 // Check rotation about z-axis |
| 509 A.makeIdentity(); |
| 510 A.rotate3d(0, 0, 90); |
| 511 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD); |
| 512 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD); |
| 513 EXPECT_ROW3_EQ(0, 0, 1, 0, A); |
| 514 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 515 |
| 516 // Check rotation about x-axis |
| 517 A.makeIdentity(); |
| 518 A.rotate3d(90, 0, 0); |
| 519 EXPECT_ROW1_EQ(1, 0, 0, 0, A); |
| 520 EXPECT_ROW2_NEAR(0, 0, -1, 0, A, ERROR_THRESHOLD); |
| 521 EXPECT_ROW3_NEAR(0, 1, 0, 0, A, ERROR_THRESHOLD); |
| 522 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 523 |
| 524 // Check rotation about y-axis. |
| 525 // Note carefully, the expected pattern is inverted compared to rotating abo
ut x axis or z axis. |
| 526 A.makeIdentity(); |
| 527 A.rotate3d(0, 90, 0); |
| 528 EXPECT_ROW1_NEAR(0, 0, 1, 0, A, ERROR_THRESHOLD); |
| 529 EXPECT_ROW2_EQ(0, 1, 0, 0, A); |
| 530 EXPECT_ROW3_NEAR(-1, 0, 0, 0, A, ERROR_THRESHOLD); |
| 531 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 532 |
| 533 // Verify that rotate3d(rx, ry, rz) post-multiplies the existing matrix. |
| 534 A.makeIdentity(); |
| 535 A.scale3d(6, 7, 8); |
| 536 A.rotate3d(0, 0, 90); |
| 537 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD); |
| 538 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD); |
| 539 EXPECT_ROW3_EQ(0, 0, 8, 0, A); |
| 540 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 541 } |
| 542 |
| 543 TEST(WebTransformationMatrixTest, verifyRotate3dOrderOfCompositeRotations) |
| 544 { |
| 545 // Rotate3d(degreesX, degreesY, degreesZ) is actually composite transform co
nsiting of |
| 546 // three primitive rotations. This test verifies that the ordering of those
three |
| 547 // transforms is the intended ordering. |
| 548 // |
| 549 // The correct ordering for this test case should be: |
| 550 // 1. rotate by 30 degrees about z-axis |
| 551 // 2. rotate by 20 degrees about y-axis |
| 552 // 3. rotate by 10 degrees about x-axis |
| 553 // |
| 554 // Note: there are 6 possible orderings of 3 transforms. For the specific tr
ansforms |
| 555 // used in this test, all 6 combinations produce a unique matrix that is dif
ferent |
| 556 // from the other orderings. That way, this test verifies the exact ordering
. |
| 557 |
| 558 WebTransformationMatrix A; |
| 559 A.makeIdentity(); |
| 560 A.rotate3d(10, 20, 30); |
| 561 |
| 562 EXPECT_ROW1_NEAR(0.8137976813493738026394908, |
| 563 -0.4409696105298823720630708, |
| 564 0.3785223063697923939763257, |
| 565 0, A, ERROR_THRESHOLD); |
| 566 EXPECT_ROW2_NEAR(0.4698463103929541584413698, |
| 567 0.8825641192593856043657752, |
| 568 0.0180283112362972230968694, |
| 569 0, A, ERROR_THRESHOLD); |
| 570 EXPECT_ROW3_NEAR(-0.3420201433256686573969318, |
| 571 0.1631759111665348205288950, |
| 572 0.9254165783983233639631294, |
| 573 0, A, ERROR_THRESHOLD); |
| 574 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 575 } |
| 576 |
| 577 TEST(WebTransformationMatrixTest, verifyRotateAxisAngle3d) |
| 578 { |
| 579 WebTransformationMatrix A; |
| 580 |
| 581 // Check rotation about z-axis |
| 582 A.makeIdentity(); |
| 583 A.rotate3d(0, 0, 1, 90); |
| 584 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD); |
| 585 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD); |
| 586 EXPECT_ROW3_EQ(0, 0, 1, 0, A); |
| 587 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 588 |
| 589 // Check rotation about x-axis |
| 590 A.makeIdentity(); |
| 591 A.rotate3d(1, 0, 0, 90); |
| 592 EXPECT_ROW1_EQ(1, 0, 0, 0, A); |
| 593 EXPECT_ROW2_NEAR(0, 0, -1, 0, A, ERROR_THRESHOLD); |
| 594 EXPECT_ROW3_NEAR(0, 1, 0, 0, A, ERROR_THRESHOLD); |
| 595 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 596 |
| 597 // Check rotation about y-axis. |
| 598 // Note carefully, the expected pattern is inverted compared to rotating abo
ut x axis or z axis. |
| 599 A.makeIdentity(); |
| 600 A.rotate3d(0, 1, 0, 90); |
| 601 EXPECT_ROW1_NEAR(0, 0, 1, 0, A, ERROR_THRESHOLD); |
| 602 EXPECT_ROW2_EQ(0, 1, 0, 0, A); |
| 603 EXPECT_ROW3_NEAR(-1, 0, 0, 0, A, ERROR_THRESHOLD); |
| 604 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 605 |
| 606 // Verify that rotate3d(axis, angle) post-multiplies the existing matrix. |
| 607 A.makeIdentity(); |
| 608 A.scale3d(6, 7, 8); |
| 609 A.rotate3d(0, 0, 1, 90); |
| 610 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD); |
| 611 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD); |
| 612 EXPECT_ROW3_EQ(0, 0, 8, 0, A); |
| 613 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 614 } |
| 615 |
| 616 TEST(WebTransformationMatrixTest, verifyRotateAxisAngle3dForArbitraryAxis) |
| 617 { |
| 618 // Check rotation about an arbitrary non-axis-aligned vector. |
| 619 WebTransformationMatrix A; |
| 620 A.rotate3d(1, 1, 1, 90); |
| 621 EXPECT_ROW1_NEAR(0.3333333333333334258519187, |
| 622 -0.2440169358562924717404030, |
| 623 0.9106836025229592124219380, |
| 624 0, A, ERROR_THRESHOLD); |
| 625 EXPECT_ROW2_NEAR(0.9106836025229592124219380, |
| 626 0.3333333333333334258519187, |
| 627 -0.2440169358562924717404030, |
| 628 0, A, ERROR_THRESHOLD); |
| 629 EXPECT_ROW3_NEAR(-0.2440169358562924717404030, |
| 630 0.9106836025229592124219380, |
| 631 0.3333333333333334258519187, |
| 632 0, A, ERROR_THRESHOLD); |
| 633 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 634 } |
| 635 |
| 636 TEST(WebTransformationMatrixTest, verifyRotateAxisAngle3dForDegenerateAxis) |
| 637 { |
| 638 // Check rotation about a degenerate zero vector. |
| 639 // It is expected to default to rotation about the z-axis. |
| 640 WebTransformationMatrix A; |
| 641 A.rotate3d(0, 0, 0, 90); |
| 642 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD); |
| 643 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD); |
| 644 EXPECT_ROW3_EQ(0, 0, 1, 0, A); |
| 645 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 646 } |
| 647 |
| 648 TEST(WebTransformationMatrixTest, verifySkewX) |
| 649 { |
| 650 WebTransformationMatrix A; |
| 651 A.skewX(45); |
| 652 EXPECT_ROW1_EQ(1, 1, 0, 0, A); |
| 653 EXPECT_ROW2_EQ(0, 1, 0, 0, A); |
| 654 EXPECT_ROW3_EQ(0, 0, 1, 0, A); |
| 655 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 656 |
| 657 // Verify that skewX() post-multiplies the existing matrix. |
| 658 // Row 1, column 2, would incorrectly have value "7" if the matrix is pre-mu
ltiplied instead of post-multiplied. |
| 659 A.makeIdentity(); |
| 660 A.scale3d(6, 7, 8); |
| 661 A.skewX(45); |
| 662 EXPECT_ROW1_EQ(6, 6, 0, 0, A); |
| 663 EXPECT_ROW2_EQ(0, 7, 0, 0, A); |
| 664 EXPECT_ROW3_EQ(0, 0, 8, 0, A); |
| 665 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 666 } |
| 667 |
| 668 TEST(WebTransformationMatrixTest, verifySkewY) |
| 669 { |
| 670 WebTransformationMatrix A; |
| 671 A.skewY(45); |
| 672 EXPECT_ROW1_EQ(1, 0, 0, 0, A); |
| 673 EXPECT_ROW2_EQ(1, 1, 0, 0, A); |
| 674 EXPECT_ROW3_EQ(0, 0, 1, 0, A); |
| 675 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 676 |
| 677 // Verify that skewY() post-multiplies the existing matrix. |
| 678 // Row 2, column 1, would incorrectly have value "6" if the matrix is pre-mu
ltiplied instead of post-multiplied. |
| 679 A.makeIdentity(); |
| 680 A.scale3d(6, 7, 8); |
| 681 A.skewY(45); |
| 682 EXPECT_ROW1_EQ(6, 0, 0, 0, A); |
| 683 EXPECT_ROW2_EQ(7, 7, 0, 0, A); |
| 684 EXPECT_ROW3_EQ(0, 0, 8, 0, A); |
| 685 EXPECT_ROW4_EQ(0, 0, 0, 1, A); |
| 686 } |
| 687 |
| 688 TEST(WebTransformationMatrixTest, verifyApplyPerspective) |
| 689 { |
| 690 WebTransformationMatrix A; |
| 691 A.applyPerspective(1); |
| 692 EXPECT_ROW1_EQ(1, 0, 0, 0, A); |
| 693 EXPECT_ROW2_EQ(0, 1, 0, 0, A); |
| 694 EXPECT_ROW3_EQ(0, 0, 1, 0, A); |
| 695 EXPECT_ROW4_EQ(0, 0, -1, 1, A); |
| 696 |
| 697 // Verify that applyPerspective() post-multiplies the existing matrix. |
| 698 A.makeIdentity(); |
| 699 A.translate3d(2, 3, 4); |
| 700 A.applyPerspective(1); |
| 701 EXPECT_ROW1_EQ(1, 0, -2, 2, A); |
| 702 EXPECT_ROW2_EQ(0, 1, -3, 3, A); |
| 703 EXPECT_ROW3_EQ(0, 0, -3, 4, A); |
| 704 EXPECT_ROW4_EQ(0, 0, -1, 1, A); |
| 705 } |
| 706 |
| 707 TEST(WebTransformationMatrixTest, verifyHasPerspective) |
| 708 { |
| 709 WebTransformationMatrix A; |
| 710 A.applyPerspective(1); |
| 711 EXPECT_TRUE(A.hasPerspective()); |
| 712 |
| 713 A.makeIdentity(); |
| 714 A.applyPerspective(0); |
| 715 EXPECT_FALSE(A.hasPerspective()); |
| 716 |
| 717 A.makeIdentity(); |
| 718 A.setM34(-0.3); |
| 719 EXPECT_TRUE(A.hasPerspective()); |
| 720 |
| 721 // FIXME: WebCore only checkes m34() for perspective, but that is probably |
| 722 // wrong. https://bugs.webkit.org/show_bug.cgi?id=83088. For now, thi
s test |
| 723 // case expects the exact behavior as implemented by WebCore, but thi
s should |
| 724 // probably be changed so that if the entire bottom row is not exactl
y |
| 725 // (0, 0, 0, 1), then hasPerspective should return true. |
| 726 |
| 727 A.makeIdentity(); |
| 728 A.setM14(-1); |
| 729 EXPECT_FALSE(A.hasPerspective()); |
| 730 |
| 731 A.makeIdentity(); |
| 732 A.setM24(-1); |
| 733 EXPECT_FALSE(A.hasPerspective()); |
| 734 |
| 735 A.makeIdentity(); |
| 736 A.setM44(0.5); |
| 737 EXPECT_FALSE(A.hasPerspective()); |
| 738 } |
| 739 |
| 740 TEST(WebTransformationMatrixTest, verifyIsInvertible) |
| 741 { |
| 742 WebTransformationMatrix A; |
| 743 |
| 744 // Translations, rotations, scales, skews and arbitrary combinations of them
are invertible. |
| 745 A.makeIdentity(); |
| 746 EXPECT_TRUE(A.isInvertible()); |
| 747 |
| 748 A.makeIdentity(); |
| 749 A.translate3d(2, 3, 4); |
| 750 EXPECT_TRUE(A.isInvertible()); |
| 751 |
| 752 A.makeIdentity(); |
| 753 A.scale3d(6, 7, 8); |
| 754 EXPECT_TRUE(A.isInvertible()); |
| 755 |
| 756 A.makeIdentity(); |
| 757 A.rotate3d(10, 20, 30); |
| 758 EXPECT_TRUE(A.isInvertible()); |
| 759 |
| 760 A.makeIdentity(); |
| 761 A.skewX(45); |
| 762 EXPECT_TRUE(A.isInvertible()); |
| 763 |
| 764 // A perspective matrix (projection plane at z=0) is invertible. The intuiti
ve |
| 765 // explanation is that perspective is eqivalent to a skew of the w-axis; ske
ws are |
| 766 // invertible. |
| 767 A.makeIdentity(); |
| 768 A.applyPerspective(1); |
| 769 EXPECT_TRUE(A.isInvertible()); |
| 770 |
| 771 // A "pure" perspective matrix derived by similar triangles, with m44() set
to zero |
| 772 // (i.e. camera positioned at the origin), is not invertible. |
| 773 A.makeIdentity(); |
| 774 A.applyPerspective(1); |
| 775 A.setM44(0); |
| 776 EXPECT_FALSE(A.isInvertible()); |
| 777 |
| 778 // Adding more to a non-invertible matrix will not make it invertible in the
general case. |
| 779 A.makeIdentity(); |
| 780 A.applyPerspective(1); |
| 781 A.setM44(0); |
| 782 A.scale3d(6, 7, 8); |
| 783 A.rotate3d(10, 20, 30); |
| 784 A.translate3d(6, 7, 8); |
| 785 EXPECT_FALSE(A.isInvertible()); |
| 786 |
| 787 // A degenerate matrix of all zeros is not invertible. |
| 788 A.makeIdentity(); |
| 789 A.setM11(0); |
| 790 A.setM22(0); |
| 791 A.setM33(0); |
| 792 A.setM44(0); |
| 793 EXPECT_FALSE(A.isInvertible()); |
| 794 } |
| 795 |
| 796 TEST(WebTransformationMatrixTest, verifyIsIdentity) |
| 797 { |
| 798 WebTransformationMatrix A; |
| 799 |
| 800 initializeTestMatrix(A); |
| 801 EXPECT_FALSE(A.isIdentity()); |
| 802 |
| 803 A.makeIdentity(); |
| 804 EXPECT_TRUE(A.isIdentity()); |
| 805 |
| 806 // Modifying any one individual element should cause the matrix to no longer
be identity. |
| 807 A.makeIdentity(); |
| 808 A.setM11(2); |
| 809 EXPECT_FALSE(A.isIdentity()); |
| 810 |
| 811 A.makeIdentity(); |
| 812 A.setM12(2); |
| 813 EXPECT_FALSE(A.isIdentity()); |
| 814 |
| 815 A.makeIdentity(); |
| 816 A.setM13(2); |
| 817 EXPECT_FALSE(A.isIdentity()); |
| 818 |
| 819 A.makeIdentity(); |
| 820 A.setM14(2); |
| 821 EXPECT_FALSE(A.isIdentity()); |
| 822 |
| 823 A.makeIdentity(); |
| 824 A.setM21(2); |
| 825 EXPECT_FALSE(A.isIdentity()); |
| 826 |
| 827 A.makeIdentity(); |
| 828 A.setM22(2); |
| 829 EXPECT_FALSE(A.isIdentity()); |
| 830 |
| 831 A.makeIdentity(); |
| 832 A.setM23(2); |
| 833 EXPECT_FALSE(A.isIdentity()); |
| 834 |
| 835 A.makeIdentity(); |
| 836 A.setM24(2); |
| 837 EXPECT_FALSE(A.isIdentity()); |
| 838 |
| 839 A.makeIdentity(); |
| 840 A.setM31(2); |
| 841 EXPECT_FALSE(A.isIdentity()); |
| 842 |
| 843 A.makeIdentity(); |
| 844 A.setM32(2); |
| 845 EXPECT_FALSE(A.isIdentity()); |
| 846 |
| 847 A.makeIdentity(); |
| 848 A.setM33(2); |
| 849 EXPECT_FALSE(A.isIdentity()); |
| 850 |
| 851 A.makeIdentity(); |
| 852 A.setM34(2); |
| 853 EXPECT_FALSE(A.isIdentity()); |
| 854 |
| 855 A.makeIdentity(); |
| 856 A.setM41(2); |
| 857 EXPECT_FALSE(A.isIdentity()); |
| 858 |
| 859 A.makeIdentity(); |
| 860 A.setM42(2); |
| 861 EXPECT_FALSE(A.isIdentity()); |
| 862 |
| 863 A.makeIdentity(); |
| 864 A.setM43(2); |
| 865 EXPECT_FALSE(A.isIdentity()); |
| 866 |
| 867 A.makeIdentity(); |
| 868 A.setM44(2); |
| 869 EXPECT_FALSE(A.isIdentity()); |
| 870 } |
| 871 |
| 872 TEST(WebTransformationMatrixTest, verifyIsIdentityOrTranslation) |
| 873 { |
| 874 WebTransformationMatrix A; |
| 875 |
| 876 initializeTestMatrix(A); |
| 877 EXPECT_FALSE(A.isIdentityOrTranslation()); |
| 878 |
| 879 A.makeIdentity(); |
| 880 EXPECT_TRUE(A.isIdentityOrTranslation()); |
| 881 |
| 882 // Modifying any non-translation components should cause isIdentityOrTransla
tion() to |
| 883 // return false. NOTE: m41(), m42(), and m43() are the translation component
s, so |
| 884 // modifying them should still return true for isIdentityOrTranslation(). |
| 885 A.makeIdentity(); |
| 886 A.setM11(2); |
| 887 EXPECT_FALSE(A.isIdentityOrTranslation()); |
| 888 |
| 889 A.makeIdentity(); |
| 890 A.setM12(2); |
| 891 EXPECT_FALSE(A.isIdentityOrTranslation()); |
| 892 |
| 893 A.makeIdentity(); |
| 894 A.setM13(2); |
| 895 EXPECT_FALSE(A.isIdentityOrTranslation()); |
| 896 |
| 897 A.makeIdentity(); |
| 898 A.setM14(2); |
| 899 EXPECT_FALSE(A.isIdentityOrTranslation()); |
| 900 |
| 901 A.makeIdentity(); |
| 902 A.setM21(2); |
| 903 EXPECT_FALSE(A.isIdentityOrTranslation()); |
| 904 |
| 905 A.makeIdentity(); |
| 906 A.setM22(2); |
| 907 EXPECT_FALSE(A.isIdentityOrTranslation()); |
| 908 |
| 909 A.makeIdentity(); |
| 910 A.setM23(2); |
| 911 EXPECT_FALSE(A.isIdentityOrTranslation()); |
| 912 |
| 913 A.makeIdentity(); |
| 914 A.setM24(2); |
| 915 EXPECT_FALSE(A.isIdentityOrTranslation()); |
| 916 |
| 917 A.makeIdentity(); |
| 918 A.setM31(2); |
| 919 EXPECT_FALSE(A.isIdentityOrTranslation()); |
| 920 |
| 921 A.makeIdentity(); |
| 922 A.setM32(2); |
| 923 EXPECT_FALSE(A.isIdentityOrTranslation()); |
| 924 |
| 925 A.makeIdentity(); |
| 926 A.setM33(2); |
| 927 EXPECT_FALSE(A.isIdentityOrTranslation()); |
| 928 |
| 929 A.makeIdentity(); |
| 930 A.setM34(2); |
| 931 EXPECT_FALSE(A.isIdentityOrTranslation()); |
| 932 |
| 933 // Note carefully - expecting true here. |
| 934 A.makeIdentity(); |
| 935 A.setM41(2); |
| 936 EXPECT_TRUE(A.isIdentityOrTranslation()); |
| 937 |
| 938 // Note carefully - expecting true here. |
| 939 A.makeIdentity(); |
| 940 A.setM42(2); |
| 941 EXPECT_TRUE(A.isIdentityOrTranslation()); |
| 942 |
| 943 // Note carefully - expecting true here. |
| 944 A.makeIdentity(); |
| 945 A.setM43(2); |
| 946 EXPECT_TRUE(A.isIdentityOrTranslation()); |
| 947 |
| 948 A.makeIdentity(); |
| 949 A.setM44(2); |
| 950 EXPECT_FALSE(A.isIdentityOrTranslation()); |
| 951 } |
| 952 |
| 953 TEST(WebTransformationMatrixTest, verifyIsIntegerTranslation) |
| 954 { |
| 955 WebTransformationMatrix A; |
| 956 |
| 957 A.makeIdentity(); |
| 958 A.translate(2, 3); |
| 959 EXPECT_TRUE(A.isIntegerTranslation()); |
| 960 |
| 961 A.makeIdentity(); |
| 962 A.translate(2, 3); |
| 963 EXPECT_TRUE(A.isIntegerTranslation()); |
| 964 |
| 965 A.makeIdentity(); |
| 966 A.translate(2.00001, 3); |
| 967 EXPECT_FALSE(A.isIntegerTranslation()); |
| 968 |
| 969 A.makeIdentity(); |
| 970 A.translate(2, 2.99999); |
| 971 EXPECT_FALSE(A.isIntegerTranslation()); |
| 972 |
| 973 // Stacking many integer translations should ideally not accumulate any prec
ision error. |
| 974 A.makeIdentity(); |
| 975 for (int i = 0; i < 100000; ++i) |
| 976 A.translate(2, 3); |
| 977 EXPECT_TRUE(A.isIntegerTranslation()); |
| 978 } |
| 979 |
| 980 TEST(WebTransformationMatrixTest, verifyBlendForTranslation) |
| 981 { |
| 982 WebTransformationMatrix from; |
| 983 from.translate3d(100, 200, 100); |
| 984 |
| 985 WebTransformationMatrix to; |
| 986 |
| 987 to.makeIdentity(); |
| 988 to.translate3d(200, 100, 300); |
| 989 to.blend(from, 0); |
| 990 EXPECT_TRANSFORMATION_MATRIX_EQ(from, to); |
| 991 |
| 992 to.makeIdentity(); |
| 993 to.translate3d(200, 100, 300); |
| 994 to.blend(from, 0.25); |
| 995 EXPECT_ROW1_EQ(1, 0, 0, 125, to); |
| 996 EXPECT_ROW2_EQ(0, 1, 0, 175, to); |
| 997 EXPECT_ROW3_EQ(0, 0, 1, 150, to); |
| 998 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 999 |
| 1000 to.makeIdentity(); |
| 1001 to.translate3d(200, 100, 300); |
| 1002 to.blend(from, 0.5); |
| 1003 EXPECT_ROW1_EQ(1, 0, 0, 150, to); |
| 1004 EXPECT_ROW2_EQ(0, 1, 0, 150, to); |
| 1005 EXPECT_ROW3_EQ(0, 0, 1, 200, to); |
| 1006 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1007 |
| 1008 to.makeIdentity(); |
| 1009 to.translate3d(200, 100, 300); |
| 1010 to.blend(from, 1); |
| 1011 EXPECT_ROW1_EQ(1, 0, 0, 200, to); |
| 1012 EXPECT_ROW2_EQ(0, 1, 0, 100, to); |
| 1013 EXPECT_ROW3_EQ(0, 0, 1, 300, to); |
| 1014 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1015 } |
| 1016 |
| 1017 TEST(WebTransformationMatrixTest, verifyBlendForScale) |
| 1018 { |
| 1019 WebTransformationMatrix from; |
| 1020 from.scale3d(100, 200, 100); |
| 1021 |
| 1022 WebTransformationMatrix to; |
| 1023 |
| 1024 to.makeIdentity(); |
| 1025 to.scale3d(200, 100, 300); |
| 1026 to.blend(from, 0); |
| 1027 EXPECT_TRANSFORMATION_MATRIX_EQ(from, to); |
| 1028 |
| 1029 to.makeIdentity(); |
| 1030 to.scale3d(200, 100, 300); |
| 1031 to.blend(from, 0.25); |
| 1032 EXPECT_ROW1_EQ(125, 0, 0, 0, to); |
| 1033 EXPECT_ROW2_EQ(0, 175, 0, 0, to); |
| 1034 EXPECT_ROW3_EQ(0, 0, 150, 0, to); |
| 1035 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1036 |
| 1037 to.makeIdentity(); |
| 1038 to.scale3d(200, 100, 300); |
| 1039 to.blend(from, 0.5); |
| 1040 EXPECT_ROW1_EQ(150, 0, 0, 0, to); |
| 1041 EXPECT_ROW2_EQ(0, 150, 0, 0, to); |
| 1042 EXPECT_ROW3_EQ(0, 0, 200, 0, to); |
| 1043 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1044 |
| 1045 to.makeIdentity(); |
| 1046 to.scale3d(200, 100, 300); |
| 1047 to.blend(from, 1); |
| 1048 EXPECT_ROW1_EQ(200, 0, 0, 0, to); |
| 1049 EXPECT_ROW2_EQ(0, 100, 0, 0, to); |
| 1050 EXPECT_ROW3_EQ(0, 0, 300, 0, to); |
| 1051 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1052 } |
| 1053 |
| 1054 TEST(WebTransformationMatrixTest, verifyBlendForSkewX) |
| 1055 { |
| 1056 WebTransformationMatrix from; |
| 1057 from.skewX(0); |
| 1058 |
| 1059 WebTransformationMatrix to; |
| 1060 |
| 1061 to.makeIdentity(); |
| 1062 to.skewX(45); |
| 1063 to.blend(from, 0); |
| 1064 EXPECT_TRANSFORMATION_MATRIX_EQ(from, to); |
| 1065 |
| 1066 to.makeIdentity(); |
| 1067 to.skewX(45); |
| 1068 to.blend(from, 0.5); |
| 1069 EXPECT_ROW1_EQ(1, 0.5, 0, 0, to); |
| 1070 EXPECT_ROW2_EQ(0, 1, 0, 0, to); |
| 1071 EXPECT_ROW3_EQ(0, 0, 1, 0, to); |
| 1072 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1073 |
| 1074 to.makeIdentity(); |
| 1075 to.skewX(45); |
| 1076 to.blend(from, 0.25); |
| 1077 EXPECT_ROW1_EQ(1, 0.25, 0, 0, to); |
| 1078 EXPECT_ROW2_EQ(0, 1, 0, 0, to); |
| 1079 EXPECT_ROW3_EQ(0, 0, 1, 0, to); |
| 1080 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1081 |
| 1082 to.makeIdentity(); |
| 1083 to.skewX(45); |
| 1084 to.blend(from, 1); |
| 1085 EXPECT_ROW1_EQ(1, 1, 0, 0, to); |
| 1086 EXPECT_ROW2_EQ(0, 1, 0, 0, to); |
| 1087 EXPECT_ROW3_EQ(0, 0, 1, 0, to); |
| 1088 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1089 } |
| 1090 |
| 1091 TEST(WebTransformationMatrixTest, verifyBlendForSkewY) |
| 1092 { |
| 1093 // NOTE CAREFULLY: Decomposition of skew and rotation terms of the matrix is |
| 1094 // inherently underconstrained, and so it does not always compute the origin
ally |
| 1095 // intended skew parameters. The current implementation uses QR decompositio
n, which |
| 1096 // decomposes the shear into a rotation + non-uniform scale. |
| 1097 // |
| 1098 // It is unlikely that the decomposition implementation will need to change
very |
| 1099 // often, so to get any test coverage, the compromise is to verify the exact
matrix |
| 1100 // that the blend() operation produces. |
| 1101 // |
| 1102 // This problem also potentially exists for skewX, but the current QR decomp
osition |
| 1103 // implementation just happens to decompose those test matrices intuitively. |
| 1104 |
| 1105 WebTransformationMatrix from; |
| 1106 from.skewY(0); |
| 1107 |
| 1108 WebTransformationMatrix to; |
| 1109 |
| 1110 to.makeIdentity(); |
| 1111 to.skewY(45); |
| 1112 to.blend(from, 0); |
| 1113 EXPECT_TRANSFORMATION_MATRIX_EQ(from, to); |
| 1114 |
| 1115 to.makeIdentity(); |
| 1116 to.skewY(45); |
| 1117 to.blend(from, 0.25); |
| 1118 EXPECT_ROW1_NEAR(1.0823489449280947471976333, 0.0464370719145053845178239, 0
, 0, to, ERROR_THRESHOLD); |
| 1119 EXPECT_ROW2_NEAR(0.2152925909665224513123150, 0.9541702441750861130032035, 0
, 0, to, ERROR_THRESHOLD); |
| 1120 EXPECT_ROW3_EQ(0, 0, 1, 0, to); |
| 1121 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1122 |
| 1123 to.makeIdentity(); |
| 1124 to.skewY(45); |
| 1125 to.blend(from, 0.5); |
| 1126 EXPECT_ROW1_NEAR(1.1152212925809066312865525, 0.0676495144007326631996335, 0
, 0, to, ERROR_THRESHOLD); |
| 1127 EXPECT_ROW2_NEAR(0.4619397844342648662419037, 0.9519009045724774464858342, 0
, 0, to, ERROR_THRESHOLD); |
| 1128 EXPECT_ROW3_EQ(0, 0, 1, 0, to); |
| 1129 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1130 |
| 1131 // Unfortunately, this case suffers from uncomfortably large precision error
. |
| 1132 to.makeIdentity(); |
| 1133 to.skewY(45); |
| 1134 to.blend(from, 1); |
| 1135 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, LOOSE_ERROR_THRESHOLD); |
| 1136 EXPECT_ROW2_NEAR(1, 1, 0, 0, to, LOOSE_ERROR_THRESHOLD); |
| 1137 EXPECT_ROW3_EQ(0, 0, 1, 0, to); |
| 1138 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1139 } |
| 1140 |
| 1141 TEST(WebTransformationMatrixTest, verifyBlendForRotationAboutX) |
| 1142 { |
| 1143 // Even though blending uses quaternions, axis-aligned rotations should blen
d the same |
| 1144 // with quaternions or Euler angles. So we can test rotation blending by com
paring |
| 1145 // against manually specified matrices from Euler angles. |
| 1146 |
| 1147 WebTransformationMatrix from; |
| 1148 from.rotate3d(1, 0, 0, 0); |
| 1149 |
| 1150 WebTransformationMatrix to; |
| 1151 |
| 1152 to.makeIdentity(); |
| 1153 to.rotate3d(1, 0, 0, 90); |
| 1154 to.blend(from, 0); |
| 1155 EXPECT_TRANSFORMATION_MATRIX_EQ(from, to); |
| 1156 |
| 1157 double expectedRotationAngle = 22.5 * piDouble / 180.0; |
| 1158 to.makeIdentity(); |
| 1159 to.rotate3d(1, 0, 0, 90); |
| 1160 to.blend(from, 0.25); |
| 1161 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); |
| 1162 EXPECT_ROW2_NEAR(0, cos(expectedRotationAngle), -sin(expectedRotationAngle),
0, to, ERROR_THRESHOLD); |
| 1163 EXPECT_ROW3_NEAR(0, sin(expectedRotationAngle), cos(expectedRotationAngle),
0, to, ERROR_THRESHOLD); |
| 1164 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1165 |
| 1166 expectedRotationAngle = 45 * piDouble / 180.0; |
| 1167 to.makeIdentity(); |
| 1168 to.rotate3d(1, 0, 0, 90); |
| 1169 to.blend(from, 0.5); |
| 1170 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); |
| 1171 EXPECT_ROW2_NEAR(0, cos(expectedRotationAngle), -sin(expectedRotationAngle),
0, to, ERROR_THRESHOLD); |
| 1172 EXPECT_ROW3_NEAR(0, sin(expectedRotationAngle), cos(expectedRotationAngle),
0, to, ERROR_THRESHOLD); |
| 1173 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1174 |
| 1175 to.makeIdentity(); |
| 1176 to.rotate3d(1, 0, 0, 90); |
| 1177 to.blend(from, 1); |
| 1178 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); |
| 1179 EXPECT_ROW2_NEAR(0, 0, -1, 0, to, ERROR_THRESHOLD); |
| 1180 EXPECT_ROW3_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); |
| 1181 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1182 } |
| 1183 |
| 1184 TEST(WebTransformationMatrixTest, verifyBlendForRotationAboutY) |
| 1185 { |
| 1186 WebTransformationMatrix from; |
| 1187 from.rotate3d(0, 1, 0, 0); |
| 1188 |
| 1189 WebTransformationMatrix to; |
| 1190 |
| 1191 to.makeIdentity(); |
| 1192 to.rotate3d(0, 1, 0, 90); |
| 1193 to.blend(from, 0); |
| 1194 EXPECT_TRANSFORMATION_MATRIX_EQ(from, to); |
| 1195 |
| 1196 double expectedRotationAngle = 22.5 * piDouble / 180.0; |
| 1197 to.makeIdentity(); |
| 1198 to.rotate3d(0, 1, 0, 90); |
| 1199 to.blend(from, 0.25); |
| 1200 EXPECT_ROW1_NEAR(cos(expectedRotationAngle), 0, sin(expectedRotationAngle),
0, to, ERROR_THRESHOLD); |
| 1201 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); |
| 1202 EXPECT_ROW3_NEAR(-sin(expectedRotationAngle), 0, cos(expectedRotationAngle),
0, to, ERROR_THRESHOLD); |
| 1203 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1204 |
| 1205 expectedRotationAngle = 45 * piDouble / 180.0; |
| 1206 to.makeIdentity(); |
| 1207 to.rotate3d(0, 1, 0, 90); |
| 1208 to.blend(from, 0.5); |
| 1209 EXPECT_ROW1_NEAR(cos(expectedRotationAngle), 0, sin(expectedRotationAngle),
0, to, ERROR_THRESHOLD); |
| 1210 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); |
| 1211 EXPECT_ROW3_NEAR(-sin(expectedRotationAngle), 0, cos(expectedRotationAngle),
0, to, ERROR_THRESHOLD); |
| 1212 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1213 |
| 1214 to.makeIdentity(); |
| 1215 to.rotate3d(0, 1, 0, 90); |
| 1216 to.blend(from, 1); |
| 1217 EXPECT_ROW1_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); |
| 1218 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); |
| 1219 EXPECT_ROW3_NEAR(-1, 0, 0, 0, to, ERROR_THRESHOLD); |
| 1220 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1221 } |
| 1222 |
| 1223 TEST(WebTransformationMatrixTest, verifyBlendForRotationAboutZ) |
| 1224 { |
| 1225 WebTransformationMatrix from; |
| 1226 from.rotate3d(0, 0, 1, 0); |
| 1227 |
| 1228 WebTransformationMatrix to; |
| 1229 |
| 1230 to.makeIdentity(); |
| 1231 to.rotate3d(0, 0, 1, 90); |
| 1232 to.blend(from, 0); |
| 1233 EXPECT_TRANSFORMATION_MATRIX_EQ(from, to); |
| 1234 |
| 1235 double expectedRotationAngle = 22.5 * piDouble / 180.0; |
| 1236 to.makeIdentity(); |
| 1237 to.rotate3d(0, 0, 1, 90); |
| 1238 to.blend(from, 0.25); |
| 1239 EXPECT_ROW1_NEAR(cos(expectedRotationAngle), -sin(expectedRotationAngle), 0,
0, to, ERROR_THRESHOLD); |
| 1240 EXPECT_ROW2_NEAR(sin(expectedRotationAngle), cos(expectedRotationAngle), 0,
0, to, ERROR_THRESHOLD); |
| 1241 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); |
| 1242 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1243 |
| 1244 expectedRotationAngle = 45 * piDouble / 180.0; |
| 1245 to.makeIdentity(); |
| 1246 to.rotate3d(0, 0, 1, 90); |
| 1247 to.blend(from, 0.5); |
| 1248 EXPECT_ROW1_NEAR(cos(expectedRotationAngle), -sin(expectedRotationAngle), 0,
0, to, ERROR_THRESHOLD); |
| 1249 EXPECT_ROW2_NEAR(sin(expectedRotationAngle), cos(expectedRotationAngle), 0,
0, to, ERROR_THRESHOLD); |
| 1250 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); |
| 1251 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1252 |
| 1253 to.makeIdentity(); |
| 1254 to.rotate3d(0, 0, 1, 90); |
| 1255 to.blend(from, 1); |
| 1256 EXPECT_ROW1_NEAR(0, -1, 0, 0, to, ERROR_THRESHOLD); |
| 1257 EXPECT_ROW2_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); |
| 1258 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); |
| 1259 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
| 1260 } |
| 1261 |
| 1262 |
| 1263 TEST(WebTransformationMatrixTest, verifyBlendForCompositeTransform) |
| 1264 { |
| 1265 // Verify that the blending was done with a decomposition in correct order b
y blending |
| 1266 // a composite transform. |
| 1267 // Using matrix x vector notation (Ax = b, where x is column vector), the or
dering should be: |
| 1268 // perspective * translation * rotation * skew * scale |
| 1269 // |
| 1270 // It is not as important (or meaningful) to check intermediate interpolatio
ns; order |
| 1271 // of operations will be tested well enough by the end cases that are easier
to |
| 1272 // specify. |
| 1273 |
| 1274 WebTransformationMatrix from; |
| 1275 WebTransformationMatrix to; |
| 1276 |
| 1277 WebTransformationMatrix expectedEndOfAnimation; |
| 1278 expectedEndOfAnimation.applyPerspective(1); |
| 1279 expectedEndOfAnimation.translate3d(10, 20, 30); |
| 1280 expectedEndOfAnimation.rotate3d(0, 0, 1, 25); |
| 1281 expectedEndOfAnimation.skewY(45); |
| 1282 expectedEndOfAnimation.scale3d(6, 7, 8); |
| 1283 |
| 1284 to = expectedEndOfAnimation; |
| 1285 to.blend(from, 0); |
| 1286 EXPECT_TRANSFORMATION_MATRIX_EQ(from, to); |
| 1287 |
| 1288 to = expectedEndOfAnimation; |
| 1289 to.blend(from, 1); |
| 1290 |
| 1291 // Recomposing the matrix results in a normalized matrix, so to verify we ne
ed to |
| 1292 // normalize the expectedEndOfAnimation before comparing elements. Normalizi
ng means |
| 1293 // dividing everything by expectedEndOfAnimation.m44(). |
| 1294 WebTransformationMatrix normalizedExpectedEndOfAnimation = expectedEndOfAnim
ation; |
| 1295 WebTransformationMatrix normalizationMatrix; |
| 1296 normalizationMatrix.setM11(1 / expectedEndOfAnimation.m44()); |
| 1297 normalizationMatrix.setM22(1 / expectedEndOfAnimation.m44()); |
| 1298 normalizationMatrix.setM33(1 / expectedEndOfAnimation.m44()); |
| 1299 normalizationMatrix.setM44(1 / expectedEndOfAnimation.m44()); |
| 1300 normalizedExpectedEndOfAnimation.multiply(normalizationMatrix); |
| 1301 |
| 1302 EXPECT_TRANSFORMATION_MATRIX_EQ(normalizedExpectedEndOfAnimation, to); |
| 1303 } |
| 1304 |
| 1305 } // namespace |
OLD | NEW |