Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkMatrix44.h" | 8 #include "SkMatrix44.h" |
| 9 #include "Test.h" | 9 #include "Test.h" |
| 10 | 10 |
| (...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 543 | 543 |
| 544 transform.reset(); | 544 transform.reset(); |
| 545 transform.set(3, 3, 0.5); | 545 transform.set(3, 3, 0.5); |
| 546 REPORTER_ASSERT(reporter, transform.hasPerspective()); | 546 REPORTER_ASSERT(reporter, transform.hasPerspective()); |
| 547 | 547 |
| 548 transform.reset(); | 548 transform.reset(); |
| 549 transform.set(3, 3, 0.0); | 549 transform.set(3, 3, 0.0); |
| 550 REPORTER_ASSERT(reporter, transform.hasPerspective()); | 550 REPORTER_ASSERT(reporter, transform.hasPerspective()); |
| 551 } | 551 } |
| 552 | 552 |
| 553 static bool is_rectilinear (SkVector4& p1, SkVector4& p2, SkVector4& p3, SkVecto r4& p4) { | |
| 554 return (SkScalarNearlyEqual(p1.fData[0], p2.fData[0]) && | |
| 555 SkScalarNearlyEqual(p2.fData[1], p3.fData[1]) && | |
| 556 SkScalarNearlyEqual(p3.fData[0], p4.fData[0]) && | |
| 557 SkScalarNearlyEqual(p4.fData[1], p1.fData[1])) || | |
| 558 (SkScalarNearlyEqual(p1.fData[1], p2.fData[1]) && | |
| 559 SkScalarNearlyEqual(p2.fData[0], p3.fData[0]) && | |
| 560 SkScalarNearlyEqual(p3.fData[1], p4.fData[1]) && | |
| 561 SkScalarNearlyEqual(p4.fData[0], p1.fData[0])); | |
| 562 } | |
| 563 | |
| 564 static SkVector4 mul_with_persp_divide(const SkMatrix44& transform, const SkVect or4& target) { | |
| 565 SkVector4 result = transform * target; | |
| 566 if (result.fData[3] != 0.0f && result.fData[3] != SK_Scalar1) { | |
| 567 float wInverse = SK_Scalar1 / result.fData[3]; | |
| 568 result.set(result.fData[0] * wInverse, | |
| 569 result.fData[1] * wInverse, | |
| 570 result.fData[2] * wInverse, | |
| 571 SK_Scalar1); | |
| 572 } | |
| 573 return result; | |
| 574 } | |
| 575 | |
| 576 static bool empirically_preserves_2d_axis_alignment(skiatest::Reporter* reporter , | |
| 577 const SkMatrix44& transform) { | |
| 578 SkVector4 p1(5.0f, 5.0f, 0.0f); | |
| 579 SkVector4 p2(10.0f, 5.0f, 0.0f); | |
| 580 SkVector4 p3(10.0f, 20.0f, 0.0f); | |
| 581 SkVector4 p4(5.0f, 20.0f, 0.0f); | |
| 582 | |
| 583 REPORTER_ASSERT(reporter, is_rectilinear(p1, p2, p3, p4)); | |
| 584 | |
| 585 p1 = mul_with_persp_divide(transform, p1); | |
| 586 p2 = mul_with_persp_divide(transform, p2); | |
| 587 p3 = mul_with_persp_divide(transform, p3); | |
| 588 p4 = mul_with_persp_divide(transform, p4); | |
| 589 | |
| 590 return is_rectilinear(p1, p2, p3, p4); | |
| 591 } | |
| 592 | |
| 593 static void test_preserves_2d_axis_alignment(skiatest::Reporter* reporter) { | |
| 594 SkMatrix44 transform(SkMatrix44::kUninitialized_Constructor); | |
| 595 SkMatrix44 transform2(SkMatrix44::kUninitialized_Constructor); | |
| 596 | |
| 597 static const struct TestCase { | |
| 598 SkMScalar a; // row 1, column 1 | |
| 599 SkMScalar b; // row 1, column 2 | |
| 600 SkMScalar c; // row 2, column 1 | |
| 601 SkMScalar d; // row 2, column 2 | |
| 602 bool expected; | |
| 603 } test_cases[] = { | |
| 604 { 3.f, 0.f, | |
| 605 0.f, 4.f, true }, // basic case | |
| 606 { 0.f, 4.f, | |
| 607 3.f, 0.f, true }, // rotate by 90 | |
| 608 { 0.f, 0.f, | |
| 609 0.f, 4.f, true }, // degenerate x | |
| 610 { 3.f, 0.f, | |
| 611 0.f, 0.f, true }, // degenerate y | |
| 612 { 0.f, 0.f, | |
| 613 3.f, 0.f, true }, // degenerate x + rotate by 90 | |
| 614 { 0.f, 4.f, | |
| 615 0.f, 0.f, true }, // degenerate y + rotate by 90 | |
| 616 { 3.f, 4.f, | |
| 617 0.f, 0.f, false }, | |
| 618 { 0.f, 0.f, | |
| 619 3.f, 4.f, false }, | |
| 620 { 0.f, 3.f, | |
| 621 0.f, 4.f, false }, | |
| 622 { 3.f, 0.f, | |
| 623 4.f, 0.f, false }, | |
| 624 { 3.f, 4.f, | |
| 625 5.f, 0.f, false }, | |
| 626 { 3.f, 4.f, | |
| 627 0.f, 5.f, false }, | |
| 628 { 3.f, 0.f, | |
| 629 4.f, 5.f, false }, | |
| 630 { 0.f, 3.f, | |
| 631 4.f, 5.f, false }, | |
| 632 { 2.f, 3.f, | |
| 633 4.f, 5.f, false }, | |
| 634 }; | |
| 635 | |
| 636 for (size_t i = 0; i < sizeof(test_cases)/sizeof(TestCase); ++i) { | |
| 637 const TestCase& value = test_cases[i]; | |
| 638 transform.setIdentity(); | |
| 639 transform.set(0, 0, value.a); | |
| 640 transform.set(0, 1, value.b); | |
| 641 transform.set(1, 0, value.c); | |
| 642 transform.set(1, 1, value.d); | |
| 643 | |
| 644 if (value.expected) { | |
| 645 REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter , transform)); | |
| 646 REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); | |
| 647 } else { | |
| 648 REPORTER_ASSERT(reporter, !empirically_preserves_2d_axis_alignment(reporte r, transform)); | |
| 649 REPORTER_ASSERT(reporter, !transform.preserves2dAxisAlignment()); | |
| 650 } | |
| 651 } | |
| 652 | |
| 653 // Try the same test cases again, but this time make sure that other matrix | |
| 654 // elements (except perspective) have entries, to test that they are ignored. | |
| 655 for (size_t i = 0; i < sizeof(test_cases)/sizeof(TestCase); ++i) { | |
| 656 const TestCase& value = test_cases[i]; | |
| 657 transform.setIdentity(); | |
| 658 transform.set(0, 0, value.a); | |
| 659 transform.set(0, 1, value.b); | |
| 660 transform.set(1, 0, value.c); | |
| 661 transform.set(1, 1, value.d); | |
| 662 | |
| 663 transform.set(0, 2, 1.f); | |
| 664 transform.set(0, 3, 2.f); | |
| 665 transform.set(1, 2, 3.f); | |
| 666 transform.set(1, 3, 4.f); | |
| 667 transform.set(2, 0, 5.f); | |
| 668 transform.set(2, 1, 6.f); | |
| 669 transform.set(2, 2, 7.f); | |
| 670 transform.set(2, 3, 8.f); | |
| 671 | |
| 672 if (value.expected) { | |
| 673 REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter , transform)); | |
| 674 REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); | |
| 675 } else { | |
| 676 REPORTER_ASSERT(reporter, !empirically_preserves_2d_axis_alignment(reporte r, transform)); | |
| 677 REPORTER_ASSERT(reporter, !transform.preserves2dAxisAlignment()); | |
| 678 } | |
| 679 } | |
| 680 | |
| 681 // Try the same test cases again, but this time add perspective which is | |
| 682 // always assumed to not-preserve axis alignment. | |
| 683 for (size_t i = 0; i < sizeof(test_cases)/sizeof(TestCase); ++i) { | |
| 684 const TestCase& value = test_cases[i]; | |
| 685 transform.setIdentity(); | |
| 686 transform.set(0, 0, value.a); | |
| 687 transform.set(0, 1, value.b); | |
| 688 transform.set(1, 0, value.c); | |
| 689 transform.set(1, 1, value.d); | |
| 690 | |
| 691 transform.set(0, 2, 1.f); | |
| 692 transform.set(0, 3, 2.f); | |
| 693 transform.set(1, 2, 3.f); | |
| 694 transform.set(1, 3, 4.f); | |
| 695 transform.set(2, 0, 5.f); | |
| 696 transform.set(2, 1, 6.f); | |
| 697 transform.set(2, 2, 7.f); | |
| 698 transform.set(2, 3, 8.f); | |
| 699 transform.set(3, 0, 9.f); | |
| 700 transform.set(3, 1, 10.f); | |
| 701 transform.set(3, 2, 11.f); | |
| 702 transform.set(3, 3, 12.f); | |
| 703 | |
| 704 REPORTER_ASSERT(reporter, !empirically_preserves_2d_axis_alignment(reporter, transform)); | |
| 705 REPORTER_ASSERT(reporter, !transform.preserves2dAxisAlignment()); | |
| 706 } | |
| 707 | |
| 708 // Try a few more practical situations to check precision | |
|
reed1
2014/09/19 16:45:14
can these be refactored into some sort of table? A
tomhudson
2014/09/19 18:21:19
Done.
Doesn't save much line count, but should be
| |
| 709 transform.setRotateDegreesAbout(0.0, 0.0, 1.0, 90.0); | |
| 710 REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, tr ansform)); | |
| 711 REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); | |
| 712 | |
| 713 transform.setRotateDegreesAbout(0.0, 0.0, 1.0, 180.0); | |
| 714 REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, tr ansform)); | |
| 715 REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); | |
| 716 | |
| 717 transform.setRotateDegreesAbout(0.0, 0.0, 1.0, 270.0); | |
| 718 REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, tr ansform)); | |
| 719 REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); | |
| 720 | |
| 721 transform.setRotateDegreesAbout(0.0, 1.0, 0.0, 90.0); | |
| 722 REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, tr ansform)); | |
| 723 REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); | |
| 724 | |
| 725 transform.setRotateDegreesAbout(1.0, 0.0, 0.0, 90.0); | |
| 726 REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, tr ansform)); | |
| 727 REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); | |
| 728 | |
| 729 transform.setRotateDegreesAbout(0.0, 0.0, 1.0, 90.0); | |
| 730 transform2.setRotateDegreesAbout(0.0, 1.0, 0.0, 90.0); | |
| 731 transform.postConcat(transform2); | |
| 732 REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, tr ansform)); | |
| 733 REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); | |
| 734 | |
| 735 transform.setRotateDegreesAbout(0.0, 0.0, 1.0, 90.0); | |
| 736 transform2.setRotateDegreesAbout(1.0, 0.0, 0.0, 90.0); | |
| 737 transform.postConcat(transform2); | |
| 738 REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, tr ansform)); | |
| 739 REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); | |
| 740 | |
| 741 transform.setRotateDegreesAbout(0.0, 1.0, 0.0, 90.0); | |
| 742 transform2.setRotateDegreesAbout(0.0, 0.0, 1.0, 90.0); | |
| 743 transform.postConcat(transform2); | |
| 744 REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, tr ansform)); | |
| 745 REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); | |
| 746 | |
| 747 transform.setRotateDegreesAbout(0.0, 0.0, 1.0, 45.0); | |
| 748 REPORTER_ASSERT(reporter, !empirically_preserves_2d_axis_alignment(reporter, t ransform)); | |
| 749 REPORTER_ASSERT(reporter, !transform.preserves2dAxisAlignment()); | |
| 750 | |
| 751 // 3-d case; In 2d after an orthographic projection, this case does | |
| 752 // preserve 2d axis alignment. But in 3d, it does not preserve axis | |
| 753 // alignment. | |
| 754 transform.setRotateDegreesAbout(0.0, 1.0, 0.0, 45.0); | |
| 755 REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, tr ansform)); | |
| 756 REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); | |
| 757 | |
| 758 transform.setRotateDegreesAbout(1.0, 0.0, 0.0, 45.0); | |
| 759 REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, tr ansform)); | |
| 760 REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); | |
| 761 | |
| 762 // Perspective cases. | |
| 763 transform.setIdentity(); | |
| 764 transform.set(3, 2, -0.1); | |
|
danakj
2014/09/19 16:29:47
can you "// Perspective depth 10" here?
tomhudson
2014/09/19 18:21:19
Done.
| |
| 765 transform2.setRotateDegreesAbout(0.0, 1.0, 0.0, 45.0); | |
| 766 transform.preConcat(transform2); | |
| 767 REPORTER_ASSERT(reporter, !empirically_preserves_2d_axis_alignment(reporter, t ransform)); | |
| 768 REPORTER_ASSERT(reporter, !transform.preserves2dAxisAlignment()); | |
| 769 | |
| 770 transform.setIdentity(); | |
| 771 transform.set(3, 2, -0.1); | |
|
danakj
2014/09/19 16:29:47
and here?
tomhudson
2014/09/19 18:21:19
Done.
| |
| 772 transform2.setRotateDegreesAbout(0.0, 0.0, 1.0, 90.0); | |
| 773 transform.preConcat(transform2); | |
| 774 REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, tr ansform)); | |
| 775 REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); | |
| 776 } | |
| 777 | |
| 778 | |
| 553 DEF_TEST(Matrix44, reporter) { | 779 DEF_TEST(Matrix44, reporter) { |
| 554 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); | 780 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); |
| 555 SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor); | 781 SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor); |
| 556 SkMatrix44 iden1(SkMatrix44::kUninitialized_Constructor); | 782 SkMatrix44 iden1(SkMatrix44::kUninitialized_Constructor); |
| 557 SkMatrix44 iden2(SkMatrix44::kUninitialized_Constructor); | 783 SkMatrix44 iden2(SkMatrix44::kUninitialized_Constructor); |
| 558 SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor); | 784 SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor); |
| 559 | 785 |
| 560 mat.setTranslate(1, 1, 1); | 786 mat.setTranslate(1, 1, 1); |
| 561 mat.invert(&inverse); | 787 mat.invert(&inverse); |
| 562 iden1.setConcat(mat, inverse); | 788 iden1.setConcat(mat, inverse); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 649 test_determinant(reporter); | 875 test_determinant(reporter); |
| 650 test_invert(reporter); | 876 test_invert(reporter); |
| 651 test_transpose(reporter); | 877 test_transpose(reporter); |
| 652 test_get_set_double(reporter); | 878 test_get_set_double(reporter); |
| 653 test_set_row_col_major(reporter); | 879 test_set_row_col_major(reporter); |
| 654 test_translate(reporter); | 880 test_translate(reporter); |
| 655 test_scale(reporter); | 881 test_scale(reporter); |
| 656 test_map2(reporter); | 882 test_map2(reporter); |
| 657 test_3x3_conversion(reporter); | 883 test_3x3_conversion(reporter); |
| 658 test_has_perspective(reporter); | 884 test_has_perspective(reporter); |
| 885 test_preserves_2d_axis_alignment(reporter); | |
| 659 } | 886 } |
| OLD | NEW |