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

Side by Side Diff: tests/Matrix44Test.cpp

Issue 508303005: SkMatrix44::preserves2dAxisAlignment() (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Use approximate math, perspective divide Created 6 years, 3 months 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
« src/utils/SkMatrix44.cpp ('K') | « src/utils/SkMatrix44.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« src/utils/SkMatrix44.cpp ('K') | « src/utils/SkMatrix44.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698