Chromium Code Reviews| Index: tests/Matrix44Test.cpp |
| diff --git a/tests/Matrix44Test.cpp b/tests/Matrix44Test.cpp |
| index 443086dbef5a298c394e5aa230586231b2fb5bff..3bb4c5591e3cc9c18b5d4c794f01bfcd22f9b9ab 100644 |
| --- a/tests/Matrix44Test.cpp |
| +++ b/tests/Matrix44Test.cpp |
| @@ -521,6 +521,226 @@ static void test_3x3_conversion(skiatest::Reporter* reporter) { |
| REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[3], vec4transformed2[3])); |
| } |
| +static bool is_rectilinear (SkVector4& p1, SkVector4& p2, SkVector4& p3, SkVector4& p4) { |
| + return (p1.fData[0] == p2.fData[0] && p2.fData[1] == p3.fData[1] && |
|
danakj
2014/09/03 19:59:22
The gfx unit test uses within-std::epsilon<float>
|
| + p3.fData[0] == p4.fData[0] && p4.fData[1] == p1.fData[1]) || |
| + (p1.fData[1] == p2.fData[1] && p2.fData[0] == p3.fData[0] && |
| + p3.fData[1] == p4.fData[1] && p4.fData[0] == p1.fData[0]); |
| +} |
| + |
| +static bool empirically_preserves_2d_axis_alignment(skiatest::Reporter* reporter, |
| + const SkMatrix44& transform) { |
| + SkVector4 p1(5.0f, 5.0f, 0.0f); |
| + SkVector4 p2(10.0f, 5.0f, 0.0f); |
| + SkVector4 p3(10.0f, 20.0f, 0.0f); |
| + SkVector4 p4(5.0f, 20.0f, 0.0f); |
| + |
| + REPORTER_ASSERT(reporter, is_rectilinear(p1, p2, p3, p4)); |
| + |
| + p1 = transform * p1; |
|
danakj
2014/09/03 19:59:22
The gfx TransformPoint() method does something mor
Ian Vollick
2014/09/05 15:05:27
I wonder if dividing through by w to get the persp
|
| + p2 = transform * p2; |
| + p3 = transform * p3; |
| + p4 = transform * p4; |
| + |
| +SkDebugf("p1 %f %f %f %f\n", p1.fData[0], p1.fData[1], p1.fData[2], p1.fData[3]); |
| +SkDebugf("p2 %f %f %f %f\n", p2.fData[0], p2.fData[1], p2.fData[2], p2.fData[3]); |
| +SkDebugf("p3 %f %f %f %f\n", p3.fData[0], p3.fData[1], p3.fData[2], p3.fData[3]); |
| +SkDebugf("p4 %f %f %f %f\n", p4.fData[0], p4.fData[1], p4.fData[2], p4.fData[3]); |
| + |
| + return is_rectilinear(p1, p2, p3, p4); |
| +} |
| + |
| +static void test_preserves_2d_axis_alignment(skiatest::Reporter* reporter) { |
| + SkMatrix44 transform(SkMatrix44::kUninitialized_Constructor); |
| + SkMatrix44 transform2(SkMatrix44::kUninitialized_Constructor); |
| + |
| +/* |
| + static const struct TestCase { |
| + SkMScalar a; // row 1, column 1 |
| + SkMScalar b; // row 1, column 2 |
| + SkMScalar c; // row 2, column 1 |
| + SkMScalar d; // row 2, column 2 |
| + bool expected; |
| + } test_cases[] = { |
| + { 3.f, 0.f, |
| + 0.f, 4.f, true }, // basic case |
| + { 0.f, 4.f, |
| + 3.f, 0.f, true }, // rotate by 90 |
| + { 0.f, 0.f, |
| + 0.f, 4.f, true }, // degenerate x |
| + { 3.f, 0.f, |
| + 0.f, 0.f, true }, // degenerate y |
| + { 0.f, 0.f, |
| + 3.f, 0.f, true }, // degenerate x + rotate by 90 |
| + { 0.f, 4.f, |
| + 0.f, 0.f, true }, // degenerate y + rotate by 90 |
| + { 3.f, 4.f, |
| + 0.f, 0.f, false }, |
| + { 0.f, 0.f, |
| + 3.f, 4.f, false }, |
| + { 0.f, 3.f, |
| + 0.f, 4.f, false }, |
| + { 3.f, 0.f, |
| + 4.f, 0.f, false }, |
| + { 3.f, 4.f, |
| + 5.f, 0.f, false }, |
| + { 3.f, 4.f, |
| + 0.f, 5.f, false }, |
| + { 3.f, 0.f, |
| + 4.f, 5.f, false }, |
| + { 0.f, 3.f, |
| + 4.f, 5.f, false }, |
| + { 2.f, 3.f, |
| + 4.f, 5.f, false }, |
| + }; |
| + |
| + for (size_t i = 0; i < sizeof(test_cases)/sizeof(TestCase); ++i) { |
| + const TestCase& value = test_cases[i]; |
| + transform.setIdentity(); |
| + transform.set(0, 0, value.a); |
| + transform.set(0, 1, value.b); |
| + transform.set(1, 0, value.c); |
| + transform.set(1, 1, value.d); |
| + |
| + if (value.expected) { |
| + REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); |
| + } else { |
| + REPORTER_ASSERT(reporter, !empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, !transform.preserves2dAxisAlignment()); |
| + } |
| + } |
| + |
| + // Try the same test cases again, but this time make sure that other matrix |
| + // elements (except perspective) have entries, to test that they are ignored. |
| + for (size_t i = 0; i < sizeof(test_cases)/sizeof(TestCase); ++i) { |
| + const TestCase& value = test_cases[i]; |
| + transform.setIdentity(); |
| + transform.set(0, 0, value.a); |
| + transform.set(0, 1, value.b); |
| + transform.set(1, 0, value.c); |
| + transform.set(1, 1, value.d); |
| + |
| + transform.set(0, 2, 1.f); |
| + transform.set(0, 3, 2.f); |
| + transform.set(1, 2, 3.f); |
| + transform.set(1, 3, 4.f); |
| + transform.set(2, 0, 5.f); |
| + transform.set(2, 1, 6.f); |
| + transform.set(2, 2, 7.f); |
| + transform.set(2, 3, 8.f); |
| + |
| + if (value.expected) { |
| + REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); |
| + } else { |
| + REPORTER_ASSERT(reporter, !empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, !transform.preserves2dAxisAlignment()); |
| + } |
| + } |
| + |
| + // Try the same test cases again, but this time add perspective which is |
| + // always assumed to not-preserve axis alignment. |
| + for (size_t i = 0; i < sizeof(test_cases)/sizeof(TestCase); ++i) { |
| + const TestCase& value = test_cases[i]; |
| + transform.setIdentity(); |
| + transform.set(0, 0, value.a); |
| + transform.set(0, 1, value.b); |
| + transform.set(1, 0, value.c); |
| + transform.set(1, 1, value.d); |
| + |
| + transform.set(0, 2, 1.f); |
| + transform.set(0, 3, 2.f); |
| + transform.set(1, 2, 3.f); |
| + transform.set(1, 3, 4.f); |
| + transform.set(2, 0, 5.f); |
| + transform.set(2, 1, 6.f); |
| + transform.set(2, 2, 7.f); |
| + transform.set(2, 3, 8.f); |
| + transform.set(3, 0, 9.f); |
| + transform.set(3, 1, 10.f); |
| + transform.set(3, 2, 11.f); |
| + transform.set(3, 3, 12.f); |
| + |
| + REPORTER_ASSERT(reporter, !empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, !transform.preserves2dAxisAlignment()); |
| + } |
| + |
| + // Try a few more practical situations to check precision |
| + transform.setRotateDegreesAbout(0.0, 0.0, 1.0, 90.0); |
| + REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); |
| + |
| + transform.setRotateDegreesAbout(0.0, 0.0, 1.0, 180.0); |
| + REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); |
| + |
| + transform.setRotateDegreesAbout(0.0, 0.0, 1.0, 270.0); |
| + REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); |
| + |
| + transform.setRotateDegreesAbout(0.0, 1.0, 0.0, 90.0); |
| + REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); |
| + |
| + transform.setRotateDegreesAbout(1.0, 0.0, 0.0, 90.0); |
| + REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); |
| + |
| + transform.setRotateDegreesAbout(0.0, 0.0, 1.0, 90.0); |
| + transform2.setRotateDegreesAbout(0.0, 1.0, 0.0, 90.0); |
| + transform.postConcat(transform2); |
| + REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); |
| + |
| + transform.setRotateDegreesAbout(0.0, 0.0, 1.0, 90.0); |
| + transform2.setRotateDegreesAbout(1.0, 0.0, 0.0, 90.0); |
| + transform.postConcat(transform2); |
| + REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); |
| + |
| + transform.setRotateDegreesAbout(0.0, 1.0, 0.0, 90.0); |
| + transform2.setRotateDegreesAbout(0.0, 0.0, 1.0, 90.0); |
| + transform.postConcat(transform2); |
| + REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); |
| + |
| + transform.setRotateDegreesAbout(0.0, 0.0, 1.0, 45.0); |
| + REPORTER_ASSERT(reporter, !empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, !transform.preserves2dAxisAlignment()); |
| + |
| + // 3-d case; In 2d after an orthographic projection, this case does |
| + // preserve 2d axis alignment. But in 3d, it does not preserve axis |
| + // alignment. |
| + transform.setRotateDegreesAbout(0.0, 1.0, 0.0, 45.0); |
| + REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); |
| + |
| + transform.setRotateDegreesAbout(1.0, 0.0, 0.0, 45.0); |
| + REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); |
| +*/ |
| + |
| + // Perspective cases. |
| + transform.setIdentity(); |
| + transform.set(3, 2, -0.1); |
| + transform2.setRotateDegreesAbout(0.0, 1.0, 0.0, 45.0); |
| + transform.preConcat(transform2); |
| + |
| +transform.dump(); |
| + |
| + REPORTER_ASSERT(reporter, !empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, !transform.preserves2dAxisAlignment()); |
| + |
| + transform.setIdentity(); |
| + transform.set(3, 2, -0.1); |
| + transform2.setRotateDegreesAbout(0.0, 0.0, 1.0, 90.0); |
| + transform.preConcat(transform2); |
| + REPORTER_ASSERT(reporter, empirically_preserves_2d_axis_alignment(reporter, transform)); |
| + REPORTER_ASSERT(reporter, transform.preserves2dAxisAlignment()); |
| +} |
| + |
| + |
| DEF_TEST(Matrix44, reporter) { |
| SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); |
| SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor); |
| @@ -626,4 +846,5 @@ DEF_TEST(Matrix44, reporter) { |
| test_scale(reporter); |
| test_map2(reporter); |
| test_3x3_conversion(reporter); |
| + test_preserves_2d_axis_alignment(reporter); |
| } |