Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: cc/math_util_unittest.cc

Issue 11316043: Implement unit tests and temporary MathUtil wrappers for transform functionality (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/math_util.h" 5 #include "cc/math_util.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "cc/test/geometry_test_utils.h" 9 #include "cc/test/geometry_test_utils.h"
10 #include "testing/gmock/include/gmock/gmock.h" 10 #include "testing/gmock/include/gmock/gmock.h"
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, testVector.y()), MathUtil::projectVector( testVector, y)); 173 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, testVector.y()), MathUtil::projectVector( testVector, y));
174 174
175 // Finally check than an arbitrary vector projected to another one gives a v ector parallel to 175 // Finally check than an arbitrary vector projected to another one gives a v ector parallel to
176 // the second vector. 176 // the second vector.
177 gfx::Vector2dF targetVector(0.5, 0.2f); 177 gfx::Vector2dF targetVector(0.5, 0.2f);
178 gfx::Vector2dF projectedVector = MathUtil::projectVector(testVector, targetV ector); 178 gfx::Vector2dF projectedVector = MathUtil::projectVector(testVector, targetV ector);
179 EXPECT_EQ(projectedVector.x() / targetVector.x(), 179 EXPECT_EQ(projectedVector.x() / targetVector.x(),
180 projectedVector.y() / targetVector.y()); 180 projectedVector.y() / targetVector.y());
181 } 181 }
182 182
183 // TODO(shawnsingh): these macros are redundant with those from
184 // web_transformation_matrix_unittests, but for now they
185 // are different enough to be appropriate here.
186
187 #define EXPECT_ROW1_EQ(a, b, c, d, transform) \
188 EXPECT_FLOAT_EQ((a), (transform).matrix().get(0, 0)); \
189 EXPECT_FLOAT_EQ((b), (transform).matrix().get(0, 1)); \
190 EXPECT_FLOAT_EQ((c), (transform).matrix().get(0, 2)); \
191 EXPECT_FLOAT_EQ((d), (transform).matrix().get(0, 3));
192
193 #define EXPECT_ROW2_EQ(a, b, c, d, transform) \
194 EXPECT_FLOAT_EQ((a), (transform).matrix().get(1, 0)); \
195 EXPECT_FLOAT_EQ((b), (transform).matrix().get(1, 1)); \
196 EXPECT_FLOAT_EQ((c), (transform).matrix().get(1, 2)); \
197 EXPECT_FLOAT_EQ((d), (transform).matrix().get(1, 3));
198
199 #define EXPECT_ROW3_EQ(a, b, c, d, transform) \
200 EXPECT_FLOAT_EQ((a), (transform).matrix().get(2, 0)); \
201 EXPECT_FLOAT_EQ((b), (transform).matrix().get(2, 1)); \
202 EXPECT_FLOAT_EQ((c), (transform).matrix().get(2, 2)); \
203 EXPECT_FLOAT_EQ((d), (transform).matrix().get(2, 3));
204
205 #define EXPECT_ROW4_EQ(a, b, c, d, transform) \
206 EXPECT_FLOAT_EQ((a), (transform).matrix().get(3, 0)); \
207 EXPECT_FLOAT_EQ((b), (transform).matrix().get(3, 1)); \
208 EXPECT_FLOAT_EQ((c), (transform).matrix().get(3, 2)); \
209 EXPECT_FLOAT_EQ((d), (transform).matrix().get(3, 3));
210
211 // Checking float values for equality close to zero is not robust using EXPECT_F LOAT_EQ
212 // (see gtest documentation). So, to verify rotation matrices, we must use a loo ser
213 // absolute error threshold in some places.
214 #define EXPECT_ROW1_NEAR(a, b, c, d, transform, errorThreshold) \
215 EXPECT_NEAR((a), (transform).matrix().get(0, 0), (errorThreshold)); \
216 EXPECT_NEAR((b), (transform).matrix().get(0, 1), (errorThreshold)); \
217 EXPECT_NEAR((c), (transform).matrix().get(0, 2), (errorThreshold)); \
218 EXPECT_NEAR((d), (transform).matrix().get(0, 3), (errorThreshold));
219
220 #define EXPECT_ROW2_NEAR(a, b, c, d, transform, errorThreshold) \
221 EXPECT_NEAR((a), (transform).matrix().get(1, 0), (errorThreshold)); \
222 EXPECT_NEAR((b), (transform).matrix().get(1, 1), (errorThreshold)); \
223 EXPECT_NEAR((c), (transform).matrix().get(1, 2), (errorThreshold)); \
224 EXPECT_NEAR((d), (transform).matrix().get(1, 3), (errorThreshold));
225
226 #define EXPECT_ROW3_NEAR(a, b, c, d, transform, errorThreshold) \
227 EXPECT_NEAR((a), (transform).matrix().get(2, 0), (errorThreshold)); \
228 EXPECT_NEAR((b), (transform).matrix().get(2, 1), (errorThreshold)); \
229 EXPECT_NEAR((c), (transform).matrix().get(2, 2), (errorThreshold)); \
230 EXPECT_NEAR((d), (transform).matrix().get(2, 3), (errorThreshold));
231
232 #define ERROR_THRESHOLD 1e-14
233 #define LOOSE_ERROR_THRESHOLD 1e-7
234
235 static void initializeTestMatrix(gfx::Transform* transform)
236 {
237 SkMatrix44& matrix = transform->matrix();
238 matrix.set(0, 0, 10);
Ian Vollick 2012/11/16 13:44:46 setDouble -- here and below. Also, I think that ch
239 matrix.set(1, 0, 11);
240 matrix.set(2, 0, 12);
241 matrix.set(3, 0, 13);
242 matrix.set(0, 1, 14);
243 matrix.set(1, 1, 15);
244 matrix.set(2, 1, 16);
245 matrix.set(3, 1, 17);
246 matrix.set(0, 2, 18);
247 matrix.set(1, 2, 19);
248 matrix.set(2, 2, 20);
249 matrix.set(3, 2, 21);
250 matrix.set(0, 3, 22);
251 matrix.set(1, 3, 23);
252 matrix.set(2, 3, 24);
253 matrix.set(3, 3, 25);
254
255 // Sanity check
256 EXPECT_ROW1_EQ(10, 14, 18, 22, (*transform));
257 EXPECT_ROW2_EQ(11, 15, 19, 23, (*transform));
258 EXPECT_ROW3_EQ(12, 16, 20, 24, (*transform));
259 EXPECT_ROW4_EQ(13, 17, 21, 25, (*transform));
260 }
261
262 static void initializeTestMatrix2(gfx::Transform* transform)
263 {
264 SkMatrix44& matrix = transform->matrix();
265 matrix.set(0, 0, 30);
266 matrix.set(1, 0, 31);
267 matrix.set(2, 0, 32);
268 matrix.set(3, 0, 33);
269 matrix.set(0, 1, 34);
270 matrix.set(1, 1, 35);
271 matrix.set(2, 1, 36);
272 matrix.set(3, 1, 37);
273 matrix.set(0, 2, 38);
274 matrix.set(1, 2, 39);
275 matrix.set(2, 2, 40);
276 matrix.set(3, 2, 41);
277 matrix.set(0, 3, 42);
278 matrix.set(1, 3, 43);
279 matrix.set(2, 3, 44);
280 matrix.set(3, 3, 45);
281
282 // Sanity check
283 EXPECT_ROW1_EQ(30, 34, 38, 42, (*transform));
284 EXPECT_ROW2_EQ(31, 35, 39, 43, (*transform));
285 EXPECT_ROW3_EQ(32, 36, 40, 44, (*transform));
286 EXPECT_ROW4_EQ(33, 37, 41, 45, (*transform));
287 }
288
289 TEST(MathUtilGfxTransformTest, verifyDefaultConstructorCreatesIdentityMatrix)
290 {
291 gfx::Transform A;
292 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
293 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
294 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
295 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
296 EXPECT_TRUE(MathUtil::isIdentity(A));
297 }
298
299 TEST(MathUtilGfxTransformTest, verifyCreateGfxTransformFor2dElements)
300 {
301 gfx::Transform A = MathUtil::createGfxTransform(1, 2, 3, 4, 5, 6);
302 EXPECT_ROW1_EQ(1, 3, 0, 5, A);
303 EXPECT_ROW2_EQ(2, 4, 0, 6, A);
304 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
305 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
306 }
307
308 TEST(MathUtilGfxTransformTest, verifyCreateGfxTransformForAllElements)
309 {
310 gfx::Transform A = MathUtil::createGfxTransform(1, 2, 3, 4, 5, 6, 7, 8, 9, 1 0, 11, 12, 13, 14, 15, 16);
311 EXPECT_ROW1_EQ(1, 5, 9, 13, A);
312 EXPECT_ROW2_EQ(2, 6, 10, 14, A);
313 EXPECT_ROW3_EQ(3, 7, 11, 15, A);
314 EXPECT_ROW4_EQ(4, 8, 12, 16, A);
315 }
316
317 TEST(MathUtilGfxTransformTest, verifyCopyConstructor)
318 {
319 gfx::Transform A;
320 initializeTestMatrix(&A);
321
322 // Copy constructor should produce exact same elements as matrix A.
323 gfx::Transform B(A);
324 EXPECT_ROW1_EQ(10, 14, 18, 22, B);
325 EXPECT_ROW2_EQ(11, 15, 19, 23, B);
326 EXPECT_ROW3_EQ(12, 16, 20, 24, B);
327 EXPECT_ROW4_EQ(13, 17, 21, 25, B);
328 }
329
330 TEST(MathUtilGfxTransformTest, verifyMatrixInversion)
331 {
332 // Invert a translation
333 gfx::Transform translation;
334 translation.PreconcatTranslate3d(2, 3, 4);
335 EXPECT_TRUE(MathUtil::isInvertible(translation));
336
337 gfx::Transform inverseTranslation = MathUtil::inverse(translation);
338 EXPECT_ROW1_EQ(1, 0, 0, -2, inverseTranslation);
339 EXPECT_ROW2_EQ(0, 1, 0, -3, inverseTranslation);
340 EXPECT_ROW3_EQ(0, 0, 1, -4, inverseTranslation);
341 EXPECT_ROW4_EQ(0, 0, 0, 1, inverseTranslation);
342
343 // Note that inversion should not have changed the original matrix.
344 EXPECT_ROW1_EQ(1, 0, 0, 2, translation);
345 EXPECT_ROW2_EQ(0, 1, 0, 3, translation);
346 EXPECT_ROW3_EQ(0, 0, 1, 4, translation);
347 EXPECT_ROW4_EQ(0, 0, 0, 1, translation);
348
349 // Invert a non-uniform scale
350 gfx::Transform scale;
351 scale.PreconcatScale3d(4, 10, 100);
352 EXPECT_TRUE(MathUtil::isInvertible(scale));
353
354 gfx::Transform inverseScale = MathUtil::inverse(scale);
355 EXPECT_ROW1_EQ(0.25, 0, 0, 0, inverseScale);
356 EXPECT_ROW2_EQ(0, .1f, 0, 0, inverseScale);
357 EXPECT_ROW3_EQ(0, 0, .01f, 0, inverseScale);
358 EXPECT_ROW4_EQ(0, 0, 0, 1, inverseScale);
359
360 // Try to invert a matrix that is not invertible.
361 // The inverse() function should simply return an identity matrix.
362 gfx::Transform notInvertible;
363 notInvertible.matrix().set(0, 0, 0);
364 notInvertible.matrix().set(1, 1, 0);
365 notInvertible.matrix().set(2, 2, 0);
366 notInvertible.matrix().set(3, 3, 0);
367 EXPECT_FALSE(MathUtil::isInvertible(notInvertible));
368
369 gfx::Transform inverseOfNotInvertible;
370 initializeTestMatrix(&inverseOfNotInvertible); // initialize this to somethi ng non-identity, to make sure that assignment below actually took place.
371 inverseOfNotInvertible = MathUtil::inverse(notInvertible);
372 EXPECT_TRUE(MathUtil::isIdentity(inverseOfNotInvertible));
373 }
374
375 TEST(MathUtilGfxTransformTest, verifyTo2DTransform)
376 {
377 gfx::Transform A;
378 initializeTestMatrix(&A);
379
380 gfx::Transform B = MathUtil::to2dTransform(A);
381
382 EXPECT_ROW1_EQ(10, 14, 0, 22, B);
383 EXPECT_ROW2_EQ(11, 15, 0, 23, B);
384 EXPECT_ROW3_EQ(0, 0, 1, 0, B);
385 EXPECT_ROW4_EQ(13, 17, 0, 25, B);
386
387 // Note that to2DTransform should not have changed the original matrix.
388 EXPECT_ROW1_EQ(10, 14, 18, 22, A);
389 EXPECT_ROW2_EQ(11, 15, 19, 23, A);
390 EXPECT_ROW3_EQ(12, 16, 20, 24, A);
391 EXPECT_ROW4_EQ(13, 17, 21, 25, A);
392 }
393
394 TEST(MathUtilGfxTransformTest, verifyAssignmentOperator)
395 {
396 gfx::Transform A;
397 initializeTestMatrix(&A);
398 gfx::Transform B;
399 initializeTestMatrix2(&B);
400 gfx::Transform C;
401 initializeTestMatrix2(&C);
402 C = B = A;
403
404 // Both B and C should now have been re-assigned to the value of A.
405 EXPECT_ROW1_EQ(10, 14, 18, 22, B);
406 EXPECT_ROW2_EQ(11, 15, 19, 23, B);
407 EXPECT_ROW3_EQ(12, 16, 20, 24, B);
408 EXPECT_ROW4_EQ(13, 17, 21, 25, B);
409
410 EXPECT_ROW1_EQ(10, 14, 18, 22, C);
411 EXPECT_ROW2_EQ(11, 15, 19, 23, C);
412 EXPECT_ROW3_EQ(12, 16, 20, 24, C);
413 EXPECT_ROW4_EQ(13, 17, 21, 25, C);
414 }
415
416 TEST(MathUtilGfxTransformTest, verifyEqualsBooleanOperator)
417 {
418 gfx::Transform A;
419 initializeTestMatrix(&A);
420
421 gfx::Transform B;
422 initializeTestMatrix(&B);
423 EXPECT_TRUE(A == B);
Ian Vollick 2012/11/16 13:44:46 EXPECT_EQ?
shawnsingh 2012/11/17 00:38:31 I wanted to explicitly make sure the == operator w
424
425 // Modifying multiple elements should cause equals operator to return false.
426 gfx::Transform C;
427 initializeTestMatrix2(&C);
428 EXPECT_FALSE(A == C);
429
430 // Modifying any one individual element should cause equals operator to retu rn false.
431 gfx::Transform D;
432 D = A;
433 D.matrix().set(0, 0, 0);
434 EXPECT_FALSE(A == D);
435
436 D = A;
437 D.matrix().set(1, 0, 0);
438 EXPECT_FALSE(A == D);
439
440 D = A;
441 D.matrix().set(2, 0, 0);
442 EXPECT_FALSE(A == D);
443
444 D = A;
445 D.matrix().set(3, 0, 0);
446 EXPECT_FALSE(A == D);
447
448 D = A;
449 D.matrix().set(0, 1, 0);
450 EXPECT_FALSE(A == D);
451
452 D = A;
453 D.matrix().set(1, 1, 0);
454 EXPECT_FALSE(A == D);
455
456 D = A;
457 D.matrix().set(2, 1, 0);
458 EXPECT_FALSE(A == D);
459
460 D = A;
461 D.matrix().set(3, 1, 0);
462 EXPECT_FALSE(A == D);
463
464 D = A;
465 D.matrix().set(0, 2, 0);
466 EXPECT_FALSE(A == D);
467
468 D = A;
469 D.matrix().set(1, 2, 0);
470 EXPECT_FALSE(A == D);
471
472 D = A;
473 D.matrix().set(2, 2, 0);
474 EXPECT_FALSE(A == D);
475
476 D = A;
477 D.matrix().set(3, 2, 0);
478 EXPECT_FALSE(A == D);
479
480 D = A;
481 D.matrix().set(0, 3, 0);
482 EXPECT_FALSE(A == D);
483
484 D = A;
485 D.matrix().set(1, 3, 0);
486 EXPECT_FALSE(A == D);
487
488 D = A;
489 D.matrix().set(2, 3, 0);
490 EXPECT_FALSE(A == D);
491
492 D = A;
493 D.matrix().set(3, 3, 0);
494 EXPECT_FALSE(A == D);
495 }
496
497 TEST(MathUtilGfxTransformTest, verifyMultiplyOperator)
498 {
499 gfx::Transform A;
500 initializeTestMatrix(&A);
501
502 gfx::Transform B;
503 initializeTestMatrix2(&B);
504
505 gfx::Transform C = A * B;
506 EXPECT_ROW1_EQ(2036, 2292, 2548, 2804, C);
507 EXPECT_ROW2_EQ(2162, 2434, 2706, 2978, C);
508 EXPECT_ROW3_EQ(2288, 2576, 2864, 3152, C);
509 EXPECT_ROW4_EQ(2414, 2718, 3022, 3326, C);
510
511 // Just an additional sanity check; matrix multiplication is not commutative .
512 EXPECT_FALSE(A * B == B * A);
513 }
514
515 TEST(MathUtilGfxTransformTest, verifyMatrixMultiplication)
516 {
517 gfx::Transform A;
518 initializeTestMatrix(&A);
519
520 gfx::Transform B;
521 initializeTestMatrix2(&B);
522
523 A.PreconcatTransform(B);
524 EXPECT_ROW1_EQ(2036, 2292, 2548, 2804, A);
525 EXPECT_ROW2_EQ(2162, 2434, 2706, 2978, A);
526 EXPECT_ROW3_EQ(2288, 2576, 2864, 3152, A);
527 EXPECT_ROW4_EQ(2414, 2718, 3022, 3326, A);
528 }
529
530 TEST(MathUtilGfxTransformTest, verifyMakeIdentiy)
531 {
532 gfx::Transform A;
533 initializeTestMatrix(&A);
534 MathUtil::makeIdentity(&A);
535 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
536 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
537 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
538 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
539 EXPECT_TRUE(MathUtil::isIdentity(A));
540 }
541
542 TEST(MathUtilGfxTransformTest, verifyTranslate)
543 {
544 gfx::Transform A;
545 A.PreconcatTranslate(2, 3);
546 EXPECT_ROW1_EQ(1, 0, 0, 2, A);
547 EXPECT_ROW2_EQ(0, 1, 0, 3, A);
548 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
549 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
550
551 // Verify that PreconcatTranslate() post-multiplies the existing matrix.
552 MathUtil::makeIdentity(&A);
553 A.PreconcatScale(5, 5);
554 A.PreconcatTranslate(2, 3);
555 EXPECT_ROW1_EQ(5, 0, 0, 10, A);
556 EXPECT_ROW2_EQ(0, 5, 0, 15, A);
557 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
558 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
559 }
560
561 TEST(MathUtilGfxTransformTest, verifyTranslate3d)
562 {
563 gfx::Transform A;
564 A.PreconcatTranslate3d(2, 3, 4);
565 EXPECT_ROW1_EQ(1, 0, 0, 2, A);
566 EXPECT_ROW2_EQ(0, 1, 0, 3, A);
567 EXPECT_ROW3_EQ(0, 0, 1, 4, A);
568 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
569
570 // Verify that PreconcatTranslate3d() post-multiplies the existing matrix.
571 MathUtil::makeIdentity(&A);
572 A.PreconcatScale3d(6, 7, 8);
573 A.PreconcatTranslate3d(2, 3, 4);
574 EXPECT_ROW1_EQ(6, 0, 0, 12, A);
575 EXPECT_ROW2_EQ(0, 7, 0, 21, A);
576 EXPECT_ROW3_EQ(0, 0, 8, 32, A);
577 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
578 }
579
580 TEST(MathUtilGfxTransformTest, verifyScale)
581 {
582 gfx::Transform A;
583 A.PreconcatScale(6, 7);
584 EXPECT_ROW1_EQ(6, 0, 0, 0, A);
585 EXPECT_ROW2_EQ(0, 7, 0, 0, A);
586 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
587 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
588
589 // Verify that PreconcatScale() post-multiplies the existing matrix.
590 MathUtil::makeIdentity(&A);
591 A.PreconcatTranslate3d(2, 3, 4);
592 A.PreconcatScale(6, 7);
593 EXPECT_ROW1_EQ(6, 0, 0, 2, A);
594 EXPECT_ROW2_EQ(0, 7, 0, 3, A);
595 EXPECT_ROW3_EQ(0, 0, 1, 4, A);
596 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
597 }
598
599 TEST(MathUtilGfxTransformTest, verifyScale3d)
600 {
601 gfx::Transform A;
602 A.PreconcatScale3d(6, 7, 8);
603 EXPECT_ROW1_EQ(6, 0, 0, 0, A);
604 EXPECT_ROW2_EQ(0, 7, 0, 0, A);
605 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
606 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
607
608 // Verify that scale3d() post-multiplies the existing matrix.
609 MathUtil::makeIdentity(&A);
610 A.PreconcatTranslate3d(2, 3, 4);
611 A.PreconcatScale3d(6, 7, 8);
612 EXPECT_ROW1_EQ(6, 0, 0, 2, A);
613 EXPECT_ROW2_EQ(0, 7, 0, 3, A);
614 EXPECT_ROW3_EQ(0, 0, 8, 4, A);
615 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
616 }
617
618 TEST(MathUtilGfxTransformTest, verifyRotate)
619 {
620 gfx::Transform A;
621 A.PreconcatRotate(90);
622 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD);
623 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD);
624 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
625 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
626
627 // Verify that PreconcatRotate() post-multiplies the existing matrix.
628 MathUtil::makeIdentity(&A);
629 A.PreconcatScale3d(6, 7, 8);
630 A.PreconcatRotate(90);
631 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD);
632 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD);
633 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
634 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
635 }
636
637 TEST(MathUtilGfxTransformTest, verifyRotateEulerAngles)
638 {
639 gfx::Transform A;
640
641 // Check rotation about z-axis
642 MathUtil::makeIdentity(&A);
643 MathUtil::rotateEulerAngles(&A, 0, 0, 90);
644 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD);
645 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD);
646 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
647 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
648
649 // Check rotation about x-axis
650 MathUtil::makeIdentity(&A);
651 MathUtil::rotateEulerAngles(&A, 90, 0, 0);
652 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
653 EXPECT_ROW2_NEAR(0, 0, -1, 0, A, ERROR_THRESHOLD);
654 EXPECT_ROW3_NEAR(0, 1, 0, 0, A, ERROR_THRESHOLD);
655 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
656
657 // Check rotation about y-axis.
658 // Note carefully, the expected pattern is inverted compared to rotating abo ut x axis or z axis.
659 MathUtil::makeIdentity(&A);
660 MathUtil::rotateEulerAngles(&A, 0, 90, 0);
661 EXPECT_ROW1_NEAR(0, 0, 1, 0, A, ERROR_THRESHOLD);
662 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
663 EXPECT_ROW3_NEAR(-1, 0, 0, 0, A, ERROR_THRESHOLD);
664 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
665
666 // Verify that rotate3d(rx, ry, rz) post-multiplies the existing matrix.
667 MathUtil::makeIdentity(&A);
668 A.PreconcatScale3d(6, 7, 8);
669 MathUtil::rotateEulerAngles(&A, 0, 0, 90);
670 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD);
671 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD);
672 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
673 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
674 }
675
676 TEST(MathUtilGfxTransformTest, verifyRotateEulerAnglesOrderOfCompositeRotations)
677 {
678 // Rotate3d(degreesX, degreesY, degreesZ) is actually composite transform co nsiting of
679 // three primitive rotations. This test verifies that the ordering of those three
680 // transforms is the intended ordering.
681 //
682 // The correct ordering for this test case should be:
683 // 1. rotate by 30 degrees about z-axis
684 // 2. rotate by 20 degrees about y-axis
685 // 3. rotate by 10 degrees about x-axis
686 //
687 // Note: there are 6 possible orderings of 3 transforms. For the specific tr ansforms
688 // used in this test, all 6 combinations produce a unique matrix that is dif ferent
689 // from the other orderings. That way, this test verifies the exact ordering .
690
691 gfx::Transform A;
692 MathUtil::makeIdentity(&A);
693 MathUtil::rotateEulerAngles(&A, 10, 20, 30);
694
695 EXPECT_ROW1_NEAR(0.8137976813493738026394908,
696 -0.4409696105298823720630708,
697 0.3785223063697923939763257,
698 0, A, ERROR_THRESHOLD);
699 EXPECT_ROW2_NEAR(0.4698463103929541584413698,
700 0.8825641192593856043657752,
701 0.0180283112362972230968694,
702 0, A, ERROR_THRESHOLD);
703 EXPECT_ROW3_NEAR(-0.3420201433256686573969318,
704 0.1631759111665348205288950,
705 0.9254165783983233639631294,
706 0, A, ERROR_THRESHOLD);
707 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
708 }
709
710 TEST(MathUtilGfxTransformTest, verifyRotateAxisAngleForAlignedAxes)
711 {
712 gfx::Transform A;
713
714 // Check rotation about z-axis
715 MathUtil::makeIdentity(&A);
716 MathUtil::rotateAxisAngle(&A, 0, 0, 1, 90);
717 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD);
718 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD);
719 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
720 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
721
722 // Check rotation about x-axis
723 MathUtil::makeIdentity(&A);
724 MathUtil::rotateAxisAngle(&A, 1, 0, 0, 90);
725 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
726 EXPECT_ROW2_NEAR(0, 0, -1, 0, A, ERROR_THRESHOLD);
727 EXPECT_ROW3_NEAR(0, 1, 0, 0, A, ERROR_THRESHOLD);
728 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
729
730 // Check rotation about y-axis.
731 // Note carefully, the expected pattern is inverted compared to rotating abo ut x axis or z axis.
732 MathUtil::makeIdentity(&A);
733 MathUtil::rotateAxisAngle(&A, 0, 1, 0, 90);
734 EXPECT_ROW1_NEAR(0, 0, 1, 0, A, ERROR_THRESHOLD);
735 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
736 EXPECT_ROW3_NEAR(-1, 0, 0, 0, A, ERROR_THRESHOLD);
737 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
738
739 // Verify that rotate3d(axis, angle) post-multiplies the existing matrix.
740 MathUtil::makeIdentity(&A);
741 A.PreconcatScale3d(6, 7, 8);
742 MathUtil::rotateAxisAngle(&A, 0, 0, 1, 90);
743 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD);
744 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD);
745 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
746 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
747 }
748
749 TEST(MathUtilGfxTransformTest, verifyRotateAxisAngleForArbitraryAxis)
750 {
751 // Check rotation about an arbitrary non-axis-aligned vector.
752 gfx::Transform A;
753 MathUtil::rotateAxisAngle(&A, 1, 1, 1, 90);
754 EXPECT_ROW1_NEAR(0.3333333333333334258519187,
755 -0.2440169358562924717404030,
756 0.9106836025229592124219380,
757 0, A, ERROR_THRESHOLD);
758 EXPECT_ROW2_NEAR(0.9106836025229592124219380,
759 0.3333333333333334258519187,
760 -0.2440169358562924717404030,
761 0, A, ERROR_THRESHOLD);
762 EXPECT_ROW3_NEAR(-0.2440169358562924717404030,
763 0.9106836025229592124219380,
764 0.3333333333333334258519187,
765 0, A, ERROR_THRESHOLD);
766 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
767 }
768
769 TEST(MathUtilGfxTransformTest, verifyRotateAxisAngleForDegenerateAxis)
770 {
771 // Check rotation about a degenerate zero vector.
772 // It is expected to skip applying the rotation.
773 gfx::Transform A;
774
775 MathUtil::rotateAxisAngle(&A, 0, 0, 0, 45);
776 // Verify that A remains unchanged.
777 EXPECT_TRUE(MathUtil::isIdentity(A));
778
779 initializeTestMatrix(&A);
780 MathUtil::rotateAxisAngle(&A, 0, 0, 0, 35);
781
782 // Verify that A remains unchanged.
783 EXPECT_ROW1_EQ(10, 14, 18, 22, A);
784 EXPECT_ROW2_EQ(11, 15, 19, 23, A);
785 EXPECT_ROW3_EQ(12, 16, 20, 24, A);
786 EXPECT_ROW4_EQ(13, 17, 21, 25, A);
787 }
788
789 TEST(MathUtilGfxTransformTest, verifySkewX)
790 {
791 gfx::Transform A;
792 A.PreconcatSkewX(45);
793 EXPECT_ROW1_EQ(1, 1, 0, 0, A);
794 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
795 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
796 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
797
798 // Verify that skewX() post-multiplies the existing matrix.
799 // Row 1, column 2, would incorrectly have value "7" if the matrix is pre-mu ltiplied instead of post-multiplied.
800 MathUtil::makeIdentity(&A);
801 A.PreconcatScale3d(6, 7, 8);
802 A.PreconcatSkewX(45);
803 EXPECT_ROW1_EQ(6, 6, 0, 0, A);
804 EXPECT_ROW2_EQ(0, 7, 0, 0, A);
805 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
806 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
807 }
808
809 TEST(MathUtilGfxTransformTest, verifySkewY)
810 {
811 gfx::Transform A;
812 A.PreconcatSkewY(45);
813 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
814 EXPECT_ROW2_EQ(1, 1, 0, 0, A);
815 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
816 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
817
818 // Verify that skewY() post-multiplies the existing matrix.
819 // Row 2, column 1, would incorrectly have value "6" if the matrix is pre-mu ltiplied instead of post-multiplied.
820 MathUtil::makeIdentity(&A);
821 A.PreconcatScale3d(6, 7, 8);
822 A.PreconcatSkewY(45);
823 EXPECT_ROW1_EQ(6, 0, 0, 0, A);
824 EXPECT_ROW2_EQ(7, 7, 0, 0, A);
825 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
826 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
827 }
828
829 TEST(MathUtilGfxTransformTest, verifyPerspectiveDepth)
830 {
831 gfx::Transform A;
832 A.PreconcatPerspectiveDepth(1);
833 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
834 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
835 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
836 EXPECT_ROW4_EQ(0, 0, -1, 1, A);
837
838 // Verify that PreconcatPerspectiveDepth() post-multiplies the existing matr ix.
839 MathUtil::makeIdentity(&A);
840 A.PreconcatTranslate3d(2, 3, 4);
841 A.PreconcatPerspectiveDepth(1);
842 EXPECT_ROW1_EQ(1, 0, -2, 2, A);
843 EXPECT_ROW2_EQ(0, 1, -3, 3, A);
844 EXPECT_ROW3_EQ(0, 0, -3, 4, A);
845 EXPECT_ROW4_EQ(0, 0, -1, 1, A);
846 }
847
848 TEST(MathUtilGfxTransformTest, verifyHasPerspective)
849 {
850 gfx::Transform A;
851 A.PreconcatPerspectiveDepth(1);
852 EXPECT_TRUE(MathUtil::hasPerspective(A));
853
854 MathUtil::makeIdentity(&A);
855 A.PreconcatPerspectiveDepth(0);
856 EXPECT_FALSE(MathUtil::hasPerspective(A));
857
858 MathUtil::makeIdentity(&A);
859 A.matrix().set(3, 0, -1);
860 EXPECT_TRUE(MathUtil::hasPerspective(A));
861
862 MathUtil::makeIdentity(&A);
863 A.matrix().set(3, 1, -1);
864 EXPECT_TRUE(MathUtil::hasPerspective(A));
865
866 MathUtil::makeIdentity(&A);
867 A.matrix().set(3, 2, -0.3);
868 EXPECT_TRUE(MathUtil::hasPerspective(A));
869
870 MathUtil::makeIdentity(&A);
871 A.matrix().set(3, 3, 0.5);
872 EXPECT_TRUE(MathUtil::hasPerspective(A));
873
874 MathUtil::makeIdentity(&A);
875 A.matrix().set(3, 3, 0);
876 EXPECT_TRUE(MathUtil::hasPerspective(A));
877 }
878
879 TEST(MathUtilGfxTransformTest, verifyIsInvertible)
880 {
881 gfx::Transform A;
882
883 // Translations, rotations, scales, skews and arbitrary combinations of them are invertible.
884 MathUtil::makeIdentity(&A);
885 EXPECT_TRUE(MathUtil::isInvertible(A));
886
887 MathUtil::makeIdentity(&A);
888 A.PreconcatTranslate3d(2, 3, 4);
889 EXPECT_TRUE(MathUtil::isInvertible(A));
890
891 MathUtil::makeIdentity(&A);
892 A.PreconcatScale3d(6, 7, 8);
893 EXPECT_TRUE(MathUtil::isInvertible(A));
894
895 MathUtil::makeIdentity(&A);
896 MathUtil::rotateEulerAngles(&A, 10, 20, 30);
897 EXPECT_TRUE(MathUtil::isInvertible(A));
898
899 MathUtil::makeIdentity(&A);
900 A.PreconcatSkewX(45);
901 EXPECT_TRUE(MathUtil::isInvertible(A));
902
903 // A perspective matrix (projection plane at z=0) is invertible. The intuiti ve
904 // explanation is that perspective is eqivalent to a skew of the w-axis; ske ws are
905 // invertible.
906 MathUtil::makeIdentity(&A);
907 A.PreconcatPerspectiveDepth(1);
908 EXPECT_TRUE(MathUtil::isInvertible(A));
909
910 // A "pure" perspective matrix derived by similar triangles, with m44() set to zero
911 // (i.e. camera positioned at the origin), is not invertible.
912 MathUtil::makeIdentity(&A);
913 A.PreconcatPerspectiveDepth(1);
914 A.matrix().set(3, 3, 0);
915 EXPECT_FALSE(MathUtil::isInvertible(A));
916
917 // Adding more to a non-invertible matrix will not make it invertible in the general case.
918 MathUtil::makeIdentity(&A);
919 A.PreconcatPerspectiveDepth(1);
920 A.matrix().set(3, 3, 0);
921 A.PreconcatScale3d(6, 7, 8);
922 MathUtil::rotateEulerAngles(&A, 10, 20, 30);
923 A.PreconcatTranslate3d(6, 7, 8);
924 EXPECT_FALSE(MathUtil::isInvertible(A));
925
926 // A degenerate matrix of all zeros is not invertible.
927 MathUtil::makeIdentity(&A);
928 A.matrix().set(0, 0, 0);
929 A.matrix().set(1, 1, 0);
930 A.matrix().set(2, 2, 0);
931 A.matrix().set(3, 3, 0);
932 EXPECT_FALSE(MathUtil::isInvertible(A));
933 }
934
935 TEST(MathUtilGfxTransformTest, verifyIsIdentity)
936 {
937 gfx::Transform A;
938
939 initializeTestMatrix(&A);
940 EXPECT_FALSE(MathUtil::isIdentity(A));
941
942 MathUtil::makeIdentity(&A);
943 EXPECT_TRUE(MathUtil::isIdentity(A));
944
945 // Modifying any one individual element should cause the matrix to no longer be identity.
946 MathUtil::makeIdentity(&A);
947 A.matrix().set(0, 0, 2);
948 EXPECT_FALSE(MathUtil::isIdentity(A));
949
950 MathUtil::makeIdentity(&A);
951 A.matrix().set(1, 0, 2);
952 EXPECT_FALSE(MathUtil::isIdentity(A));
953
954 MathUtil::makeIdentity(&A);
955 A.matrix().set(2, 0, 2);
956 EXPECT_FALSE(MathUtil::isIdentity(A));
957
958 MathUtil::makeIdentity(&A);
959 A.matrix().set(3, 0, 2);
960 EXPECT_FALSE(MathUtil::isIdentity(A));
961
962 MathUtil::makeIdentity(&A);
963 A.matrix().set(0, 1, 2);
964 EXPECT_FALSE(MathUtil::isIdentity(A));
965
966 MathUtil::makeIdentity(&A);
967 A.matrix().set(1, 1, 2);
968 EXPECT_FALSE(MathUtil::isIdentity(A));
969
970 MathUtil::makeIdentity(&A);
971 A.matrix().set(2, 1, 2);
972 EXPECT_FALSE(MathUtil::isIdentity(A));
973
974 MathUtil::makeIdentity(&A);
975 A.matrix().set(3, 1, 2);
976 EXPECT_FALSE(MathUtil::isIdentity(A));
977
978 MathUtil::makeIdentity(&A);
979 A.matrix().set(0, 2, 2);
980 EXPECT_FALSE(MathUtil::isIdentity(A));
981
982 MathUtil::makeIdentity(&A);
983 A.matrix().set(1, 2, 2);
984 EXPECT_FALSE(MathUtil::isIdentity(A));
985
986 MathUtil::makeIdentity(&A);
987 A.matrix().set(2, 2, 2);
988 EXPECT_FALSE(MathUtil::isIdentity(A));
989
990 MathUtil::makeIdentity(&A);
991 A.matrix().set(3, 2, 2);
992 EXPECT_FALSE(MathUtil::isIdentity(A));
993
994 MathUtil::makeIdentity(&A);
995 A.matrix().set(0, 3, 2);
996 EXPECT_FALSE(MathUtil::isIdentity(A));
997
998 MathUtil::makeIdentity(&A);
999 A.matrix().set(1, 3, 2);
1000 EXPECT_FALSE(MathUtil::isIdentity(A));
1001
1002 MathUtil::makeIdentity(&A);
1003 A.matrix().set(2, 3, 2);
1004 EXPECT_FALSE(MathUtil::isIdentity(A));
1005
1006 MathUtil::makeIdentity(&A);
1007 A.matrix().set(3, 3, 2);
1008 EXPECT_FALSE(MathUtil::isIdentity(A));
1009 }
1010
1011 TEST(MathUtilGfxTransformTest, verifyIsIdentityOrTranslation)
1012 {
1013 gfx::Transform A;
1014
1015 initializeTestMatrix(&A);
1016 EXPECT_FALSE(MathUtil::isIdentityOrTranslation(A));
1017
1018 MathUtil::makeIdentity(&A);
1019 EXPECT_TRUE(MathUtil::isIdentityOrTranslation(A));
1020
1021 // Modifying any non-translation components should cause isIdentityOrTransla tion() to
1022 // return false. NOTE: (0, 3), (1, 3), and (2, 3) are the translation compon ents, so
1023 // modifying them should still return true for isIdentityOrTranslation().
1024 MathUtil::makeIdentity(&A);
1025 A.matrix().set(0, 0, 2);
1026 EXPECT_FALSE(MathUtil::isIdentityOrTranslation(A));
1027
1028 MathUtil::makeIdentity(&A);
1029 A.matrix().set(1, 0, 2);
1030 EXPECT_FALSE(MathUtil::isIdentityOrTranslation(A));
1031
1032 MathUtil::makeIdentity(&A);
1033 A.matrix().set(2, 0, 2);
1034 EXPECT_FALSE(MathUtil::isIdentityOrTranslation(A));
1035
1036 MathUtil::makeIdentity(&A);
1037 A.matrix().set(3, 0, 2);
1038 EXPECT_FALSE(MathUtil::isIdentityOrTranslation(A));
1039
1040 MathUtil::makeIdentity(&A);
1041 A.matrix().set(0, 0, 2);
1042 EXPECT_FALSE(MathUtil::isIdentityOrTranslation(A));
1043
1044 MathUtil::makeIdentity(&A);
1045 A.matrix().set(1, 1, 2);
1046 EXPECT_FALSE(MathUtil::isIdentityOrTranslation(A));
1047
1048 MathUtil::makeIdentity(&A);
1049 A.matrix().set(2, 1, 2);
1050 EXPECT_FALSE(MathUtil::isIdentityOrTranslation(A));
1051
1052 MathUtil::makeIdentity(&A);
1053 A.matrix().set(3, 1, 2);
1054 EXPECT_FALSE(MathUtil::isIdentityOrTranslation(A));
1055
1056 MathUtil::makeIdentity(&A);
1057 A.matrix().set(0, 2, 2);
1058 EXPECT_FALSE(MathUtil::isIdentityOrTranslation(A));
1059
1060 MathUtil::makeIdentity(&A);
1061 A.matrix().set(1, 2, 2);
1062 EXPECT_FALSE(MathUtil::isIdentityOrTranslation(A));
1063
1064 MathUtil::makeIdentity(&A);
1065 A.matrix().set(2, 2, 2);
1066 EXPECT_FALSE(MathUtil::isIdentityOrTranslation(A));
1067
1068 MathUtil::makeIdentity(&A);
1069 A.matrix().set(3, 2, 2);
1070 EXPECT_FALSE(MathUtil::isIdentityOrTranslation(A));
1071
1072 // Note carefully - expecting true here.
1073 MathUtil::makeIdentity(&A);
1074 A.matrix().set(0, 3, 2);
1075 EXPECT_TRUE(MathUtil::isIdentityOrTranslation(A));
1076
1077 // Note carefully - expecting true here.
1078 MathUtil::makeIdentity(&A);
1079 A.matrix().set(1, 3, 2);
1080 EXPECT_TRUE(MathUtil::isIdentityOrTranslation(A));
1081
1082 // Note carefully - expecting true here.
1083 MathUtil::makeIdentity(&A);
1084 A.matrix().set(2, 3, 2);
1085 EXPECT_TRUE(MathUtil::isIdentityOrTranslation(A));
1086
1087 MathUtil::makeIdentity(&A);
1088 A.matrix().set(3, 3, 2);
1089 EXPECT_FALSE(MathUtil::isIdentityOrTranslation(A));
1090 }
1091
183 } // namespace 1092 } // namespace
184 } // namespace cc 1093 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698