Flutter Impeller
matrix_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter 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 "gtest/gtest.h"
6 
8 
11 
12 namespace impeller {
13 namespace testing {
14 
15 TEST(MatrixTest, Multiply) {
16  Matrix x(0.0, 0.0, 0.0, 1.0, //
17  1.0, 0.0, 0.0, 1.0, //
18  0.0, 1.0, 0.0, 1.0, //
19  1.0, 1.0, 0.0, 1.0);
20  Matrix translate = Matrix::MakeTranslation({10, 20, 0});
21  Matrix result = translate * x;
22  EXPECT_TRUE(MatrixNear(result, Matrix(10.0, 20.0, 0.0, 1.0, //
23  11.0, 20.0, 0.0, 1.0, //
24  10.0, 21.0, 0.0, 1.0, //
25  11.0, 21.0, 0.0, 1.0)));
26 }
27 
28 TEST(MatrixTest, Equals) {
29  Matrix x;
30  Matrix y = x;
31  EXPECT_TRUE(x.Equals(y));
32 }
33 
34 TEST(MatrixTest, NotEquals) {
35  Matrix x;
36  Matrix y = x.Translate({1, 0, 0});
37  EXPECT_FALSE(x.Equals(y));
38 }
39 
40 TEST(MatrixTest, HasPerspective2D) {
41  EXPECT_FALSE(Matrix().HasPerspective2D());
42 
43  auto test = [](int index, bool expect) {
44  Matrix matrix;
45  EXPECT_FALSE(matrix.HasPerspective2D());
46  matrix.m[index] = 0.5f;
47  EXPECT_EQ(matrix.HasPerspective2D(), expect) << "index: " << index;
48  };
49 
50  // clang-format off
51  test( 0, false); test( 1, false); test( 2, false); test( 3, true);
52  test( 4, false); test( 5, false); test( 6, false); test( 7, true);
53  test( 8, false); test( 9, false); test(10, false); test(11, false);
54  test(12, false); test(13, false); test(14, false); test(15, true);
55  // clang-format on
56 }
57 
58 TEST(MatrixTest, HasPerspective) {
59  EXPECT_FALSE(Matrix().HasPerspective());
60 
61  auto test = [](int index, bool expect) {
62  Matrix matrix;
63  EXPECT_FALSE(matrix.HasPerspective());
64  matrix.m[index] = 0.5f;
65  EXPECT_EQ(matrix.HasPerspective(), expect) << "index: " << index;
66  };
67 
68  // clang-format off
69  test( 0, false); test( 1, false); test( 2, false); test( 3, true);
70  test( 4, false); test( 5, false); test( 6, false); test( 7, true);
71  test( 8, false); test( 9, false); test(10, false); test(11, true);
72  test(12, false); test(13, false); test(14, false); test(15, true);
73  // clang-format on
74 }
75 
76 TEST(MatrixTest, HasTranslation) {
77  EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).HasTranslation());
78  EXPECT_TRUE(Matrix::MakeTranslation({0, 100, 0}).HasTranslation());
79  EXPECT_TRUE(Matrix::MakeTranslation({100, 0, 0}).HasTranslation());
80  EXPECT_FALSE(Matrix().HasTranslation());
81 }
82 
83 TEST(MatrixTest, IsAligned2D) {
84  EXPECT_TRUE(Matrix().IsAligned2D());
85  EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned2D());
86 
87  auto test = [](int index, bool expect) {
88  Matrix matrix;
89  EXPECT_TRUE(matrix.IsAligned2D());
90  matrix.m[index] = 0.5f;
91  EXPECT_EQ(matrix.IsAligned2D(), expect) << "index: " << index;
92  };
93 
94  // clang-format off
95  test( 0, true); test( 1, false); test( 2, true); test( 3, false);
96  test( 4, false); test( 5, true); test( 6, true); test( 7, false);
97  test( 8, true); test( 9, true); test(10, true); test(11, true);
98  test(12, true); test(13, true); test(14, true); test(15, false);
99  // clang-format on
100 
101  // True for quadrant rotations from -250 to +250 full circles
102  for (int i = -1000; i < 1000; i++) {
103  Degrees d = Degrees(i * 90);
104  Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
105  EXPECT_TRUE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
106  }
107 
108  // False for half degree rotations from -999.5 to +1000.5 degrees
109  for (int i = -1000; i < 1000; i++) {
110  Degrees d = Degrees(i + 0.5f);
111  Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
112  EXPECT_FALSE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
113  }
114 }
115 
116 TEST(MatrixTest, IsAligned) {
117  EXPECT_TRUE(Matrix().IsAligned());
118  EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned());
119 
120  // Begin Legacy tests transferred over from geometry_unittests.cc
121  {
122  auto m = Matrix::MakeTranslation({1, 2, 3});
123  bool result = m.IsAligned();
124  ASSERT_TRUE(result);
125  }
126 
127  {
128  auto m = Matrix::MakeRotationZ(Degrees{123});
129  bool result = m.IsAligned();
130  ASSERT_FALSE(result);
131  }
132  // End Legacy tests transferred over from geometry_unittests.cc
133 
134  auto test = [](int index, bool expect) {
135  Matrix matrix;
136  EXPECT_TRUE(matrix.IsAligned());
137  matrix.m[index] = 0.5f;
138  EXPECT_EQ(matrix.IsAligned(), expect) << "index: " << index;
139  };
140 
141  // clang-format off
142  test( 0, true); test( 1, false); test( 2, false); test( 3, false);
143  test( 4, false); test( 5, true); test( 6, false); test( 7, false);
144  test( 8, false); test( 9, false); test(10, true); test(11, false);
145  test(12, true); test(13, true); test(14, true); test(15, false);
146  // clang-format on
147 
148  // True for quadrant rotations from -250 to +250 full circles
149  for (int i = -1000; i < 1000; i++) {
150  Degrees d = Degrees(i * 90);
151  Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
152  EXPECT_TRUE(matrix.IsAligned()) << "degrees: " << d.degrees;
153  }
154 
155  // False for half degree rotations from -999.5 to +1000.5 degrees
156  for (int i = -1000; i < 1000; i++) {
157  Degrees d = Degrees(i + 0.5f);
158  Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
159  EXPECT_FALSE(matrix.IsAligned()) << "degrees: " << d.degrees;
160  }
161 }
162 
163 TEST(MatrixTest, TransformHomogenous) {
164  Matrix matrix = Matrix::MakeColumn(
165  // clang-format off
166  2.0f, 3.0f, 5.0f, 7.0f,
167  11.0f, 13.0f, 17.0f, 19.0f,
168  23.0f, 29.0f, 31.0f, 37.0f,
169  41.0f, 43.0f, 47.0f, 53.0f
170  // clang-format on
171  );
172  EXPECT_EQ(matrix.TransformHomogenous({1.0f, -1.0f}),
173  Vector3(32.0f, 33.0f, 41.0f));
174 }
175 
176 TEST(MatrixTest, GetMaxBasisXYNegativeScale) {
177  Matrix m = Matrix::MakeScale({-2, 1, 1});
178 
179  EXPECT_EQ(m.GetMaxBasisLengthXY(), 2);
180 
181  m = Matrix::MakeScale({1, -3, 1});
182 
183  EXPECT_EQ(m.GetMaxBasisLengthXY(), 3);
184 }
185 
186 // Verifies a translate scale matrix doesn't need to compute sqrt(pow(scale, 2))
187 TEST(MatrixTest, GetMaxBasisXYWithLargeAndSmallScalingFactor) {
188  Matrix m = Matrix::MakeScale({2.625e+20, 2.625e+20, 1});
189  EXPECT_NEAR(m.GetMaxBasisLengthXY(), 2.625e+20, 1e+20);
190 
191  m = Matrix::MakeScale({2.625e-20, 2.625e-20, 1});
192  EXPECT_NEAR(m.GetMaxBasisLengthXY(), 2.625e-20, 1e-20);
193 }
194 
195 TEST(MatrixTest, GetMaxBasisXYWithLargeAndSmallScalingFactorNonScaleTranslate) {
196  Matrix m = Matrix::MakeScale({2.625e+20, 2.625e+20, 1});
197  m.e[0][1] = 2;
198 
199  EXPECT_TRUE(std::isinf(m.GetMaxBasisLengthXY()));
200 }
201 
202 TEST(MatrixTest, TranslateWithPerspective) {
203  Matrix m = Matrix::MakeRow(1.0, 0.0, 0.0, 10.0, //
204  0.0, 1.0, 0.0, 20.0, //
205  0.0, 0.0, 1.0, 0.0, //
206  0.0, 2.0, 0.0, 30.0);
207  Matrix result = m.Translate({100, 200});
208  EXPECT_TRUE(MatrixNear(result, Matrix::MakeRow(1.0, 0.0, 0.0, 110.0, //
209  0.0, 1.0, 0.0, 220.0, //
210  0.0, 0.0, 1.0, 0.0, //
211  0.0, 2.0, 0.0, 430.0)));
212 }
213 
214 } // namespace testing
215 } // namespace impeller
impeller::Matrix::HasPerspective
constexpr bool HasPerspective() const
Definition: matrix.h:335
impeller::Matrix::m
Scalar m[16]
Definition: matrix.h:39
impeller::Matrix::TransformHomogenous
constexpr Vector3 TransformHomogenous(const Point &v) const
Definition: matrix.h:491
impeller::Matrix::Equals
bool Equals(const Matrix &matrix, Scalar epsilon=1e-5f) const
Definition: matrix.h:410
impeller::Degrees::degrees
Scalar degrees
Definition: scalar.h:52
geometry_asserts.h
MatrixNear
inline ::testing::AssertionResult MatrixNear(impeller::Matrix a, impeller::Matrix b)
Definition: geometry_asserts.h:56
impeller::Matrix::MakeRow
static constexpr Matrix MakeRow(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
Definition: matrix.h:83
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
impeller::Matrix::e
Scalar e[4][4]
Definition: matrix.h:40
matrix.h
impeller::Matrix::Translate
constexpr Matrix Translate(const Vector3 &t) const
Definition: matrix.h:240
impeller::Matrix::MakeColumn
static constexpr Matrix MakeColumn(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
Definition: matrix.h:69
impeller::Matrix::MakeRotationZ
static Matrix MakeRotationZ(Radians r)
Definition: matrix.h:213
impeller::Matrix::GetMaxBasisLengthXY
constexpr Scalar GetMaxBasisLengthXY() const
Definition: matrix.h:298
constants.h
impeller::Degrees
Definition: scalar.h:51
impeller
Definition: allocation.cc:12
impeller::Matrix::MakeScale
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
impeller::testing::TEST
TEST(AllocationSizeTest, CanCreateTypedAllocations)
Definition: allocation_size_unittests.cc:10
impeller::Matrix::IsAligned2D
constexpr bool IsAligned2D(Scalar tolerance=0) const
Definition: matrix.h:341
impeller::Matrix::HasPerspective2D
constexpr bool HasPerspective2D() const
Definition: matrix.h:331
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Vector3
Definition: vector.h:20
impeller::Matrix::IsAligned
constexpr bool IsAligned(Scalar tolerance=0) const
Definition: matrix.h:356