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, IsTranslationOnly) {
84  EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsTranslationOnly());
85  EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsTranslationScaleOnly());
86  EXPECT_TRUE(Matrix::MakeTranslation({0, 100, 0}).IsTranslationOnly());
87  EXPECT_TRUE(Matrix::MakeTranslation({0, 100, 0}).IsTranslationScaleOnly());
88  EXPECT_TRUE(Matrix::MakeTranslation({100, 0, 0}).IsTranslationOnly());
89  EXPECT_TRUE(Matrix::MakeTranslation({100, 0, 0}).IsTranslationScaleOnly());
90  EXPECT_TRUE(Matrix().IsTranslationOnly());
91  EXPECT_TRUE(Matrix().IsTranslationScaleOnly());
92 }
93 
94 TEST(MatrixTest, IsTranslationScaleOnly) {
95  EXPECT_FALSE(Matrix::MakeScale({100, 100, 1}).IsTranslationOnly());
96  EXPECT_TRUE(Matrix::MakeScale({100, 100, 1}).IsTranslationScaleOnly());
97  EXPECT_FALSE(Matrix::MakeScale({1, 100, 1}).IsTranslationOnly());
98  EXPECT_TRUE(Matrix::MakeScale({1, 100, 1}).IsTranslationScaleOnly());
99  EXPECT_FALSE(Matrix::MakeScale({100, 1, 1}).IsTranslationOnly());
100  EXPECT_TRUE(Matrix::MakeScale({100, 1, 1}).IsTranslationScaleOnly());
101  EXPECT_TRUE(Matrix().IsTranslationOnly());
102  EXPECT_TRUE(Matrix().IsTranslationScaleOnly());
103 }
104 
105 TEST(MatrixTest, IsInvertibleGetDeterminant) {
106  EXPECT_TRUE(Matrix().IsInvertible());
107  EXPECT_NE(Matrix().GetDeterminant(), 0.0f);
108 
109  EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsInvertible());
110  EXPECT_NE(Matrix::MakeTranslation({100, 100, 0}).GetDeterminant(), 0.0f);
111 
112  EXPECT_TRUE(Matrix::MakeScale({100, 100, 1}).IsInvertible());
113  EXPECT_NE(Matrix::MakeScale({100, 100, 1}).GetDeterminant(), 0.0f);
114 
115  EXPECT_TRUE(Matrix::MakeRotationX(Degrees(30)).IsInvertible());
116  EXPECT_NE(Matrix::MakeRotationX(Degrees(30)).GetDeterminant(), 0.0f);
117 
118  EXPECT_TRUE(Matrix::MakeRotationY(Degrees(30)).IsInvertible());
119  EXPECT_NE(Matrix::MakeRotationY(Degrees(30)).GetDeterminant(), 0.0f);
120 
121  EXPECT_TRUE(Matrix::MakeRotationZ(Degrees(30)).IsInvertible());
122  EXPECT_NE(Matrix::MakeRotationZ(Degrees(30)).GetDeterminant(), 0.0f);
123 
124  EXPECT_FALSE(Matrix::MakeScale({0, 1, 1}).IsInvertible());
125  EXPECT_EQ(Matrix::MakeScale({0, 1, 1}).GetDeterminant(), 0.0f);
126  EXPECT_FALSE(Matrix::MakeScale({1, 0, 1}).IsInvertible());
127  EXPECT_EQ(Matrix::MakeScale({1, 0, 1}).GetDeterminant(), 0.0f);
128  EXPECT_FALSE(Matrix::MakeScale({1, 1, 0}).IsInvertible());
129  EXPECT_EQ(Matrix::MakeScale({1, 1, 0}).GetDeterminant(), 0.0f);
130 }
131 
132 TEST(MatrixTest, IsFinite) {
133  EXPECT_TRUE(Matrix().IsFinite());
134 
135  EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsFinite());
136  EXPECT_TRUE(Matrix::MakeScale({100, 100, 1}).IsFinite());
137 
138  EXPECT_TRUE(Matrix::MakeRotationX(Degrees(30)).IsFinite());
139  EXPECT_TRUE(Matrix::MakeRotationY(Degrees(30)).IsFinite());
140  EXPECT_TRUE(Matrix::MakeRotationZ(Degrees(30)).IsFinite());
141 
142  EXPECT_TRUE(Matrix::MakeScale({0, 1, 1}).IsFinite());
143  EXPECT_TRUE(Matrix::MakeScale({1, 0, 1}).IsFinite());
144  EXPECT_TRUE(Matrix::MakeScale({1, 1, 0}).IsFinite());
145 
146  for (int i = 0; i < 16; i++) {
147  {
148  Matrix matrix;
149  ASSERT_TRUE(matrix.IsFinite());
150  matrix.m[i] = std::numeric_limits<Scalar>::infinity();
151  ASSERT_FALSE(matrix.IsFinite());
152  }
153 
154  {
155  Matrix matrix;
156  ASSERT_TRUE(matrix.IsFinite());
157  matrix.m[i] = -std::numeric_limits<Scalar>::infinity();
158  ASSERT_FALSE(matrix.IsFinite());
159  }
160 
161  {
162  Matrix matrix;
163  ASSERT_TRUE(matrix.IsFinite());
164  matrix.m[i] = -std::numeric_limits<Scalar>::quiet_NaN();
165  ASSERT_FALSE(matrix.IsFinite());
166  }
167  }
168 }
169 
170 TEST(MatrixTest, IsAligned2D) {
171  EXPECT_TRUE(Matrix().IsAligned2D());
172  EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned2D());
173 
174  auto test = [](int index, bool expect) {
175  Matrix matrix;
176  EXPECT_TRUE(matrix.IsAligned2D());
177  matrix.m[index] = 0.5f;
178  EXPECT_EQ(matrix.IsAligned2D(), expect) << "index: " << index;
179  };
180 
181  // clang-format off
182  test( 0, true); test( 1, false); test( 2, true); test( 3, false);
183  test( 4, false); test( 5, true); test( 6, true); test( 7, false);
184  test( 8, true); test( 9, true); test(10, true); test(11, true);
185  test(12, true); test(13, true); test(14, true); test(15, false);
186  // clang-format on
187 
188  // True for quadrant rotations from -250 to +250 full circles
189  for (int i = -1000; i < 1000; i++) {
190  Degrees d = Degrees(i * 90);
191  Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
192  EXPECT_TRUE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
193  }
194 
195  // False for half degree rotations from -999.5 to +1000.5 degrees
196  for (int i = -1000; i < 1000; i++) {
197  Degrees d = Degrees(i + 0.5f);
198  Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
199  EXPECT_FALSE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
200  }
201 }
202 
203 TEST(MatrixTest, IsAligned) {
204  EXPECT_TRUE(Matrix().IsAligned());
205  EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned());
206 
207  // Begin Legacy tests transferred over from geometry_unittests.cc
208  {
209  auto m = Matrix::MakeTranslation({1, 2, 3});
210  bool result = m.IsAligned();
211  ASSERT_TRUE(result);
212  }
213 
214  {
215  auto m = Matrix::MakeRotationZ(Degrees{123});
216  bool result = m.IsAligned();
217  ASSERT_FALSE(result);
218  }
219  // End Legacy tests transferred over from geometry_unittests.cc
220 
221  auto test = [](int index, bool expect) {
222  Matrix matrix;
223  EXPECT_TRUE(matrix.IsAligned());
224  matrix.m[index] = 0.5f;
225  EXPECT_EQ(matrix.IsAligned(), expect) << "index: " << index;
226  };
227 
228  // clang-format off
229  test( 0, true); test( 1, false); test( 2, false); test( 3, false);
230  test( 4, false); test( 5, true); test( 6, false); test( 7, false);
231  test( 8, false); test( 9, false); test(10, true); test(11, false);
232  test(12, true); test(13, true); test(14, true); test(15, false);
233  // clang-format on
234 
235  // True for quadrant rotations from -250 to +250 full circles
236  for (int i = -1000; i < 1000; i++) {
237  Degrees d = Degrees(i * 90);
238  Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
239  EXPECT_TRUE(matrix.IsAligned()) << "degrees: " << d.degrees;
240  }
241 
242  // False for half degree rotations from -999.5 to +1000.5 degrees
243  for (int i = -1000; i < 1000; i++) {
244  Degrees d = Degrees(i + 0.5f);
245  Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
246  EXPECT_FALSE(matrix.IsAligned()) << "degrees: " << d.degrees;
247  }
248 }
249 
250 TEST(MatrixTest, TransformHomogenous) {
251  Matrix matrix = Matrix::MakeColumn(
252  // clang-format off
253  2.0f, 3.0f, 5.0f, 7.0f,
254  11.0f, 13.0f, 17.0f, 19.0f,
255  23.0f, 29.0f, 31.0f, 37.0f,
256  41.0f, 43.0f, 47.0f, 53.0f
257  // clang-format on
258  );
259  EXPECT_EQ(matrix.TransformHomogenous({1.0f, -1.0f}),
260  Vector3(32.0f, 33.0f, 41.0f));
261 }
262 
263 TEST(MatrixTest, GetMaxBasisXYNegativeScale) {
264  Matrix m = Matrix::MakeScale({-2, 1, 1});
265 
266  EXPECT_EQ(m.GetMaxBasisLengthXY(), 2);
267 
268  m = Matrix::MakeScale({1, -3, 1});
269 
270  EXPECT_EQ(m.GetMaxBasisLengthXY(), 3);
271 }
272 
273 // Verifies a translate scale matrix doesn't need to compute sqrt(pow(scale, 2))
274 TEST(MatrixTest, GetMaxBasisXYWithLargeAndSmallScalingFactor) {
275  Matrix m = Matrix::MakeScale({2.625e+20, 2.625e+20, 1});
276  EXPECT_NEAR(m.GetMaxBasisLengthXY(), 2.625e+20, 1e+20);
277 
278  m = Matrix::MakeScale({2.625e-20, 2.625e-20, 1});
279  EXPECT_NEAR(m.GetMaxBasisLengthXY(), 2.625e-20, 1e-20);
280 }
281 
282 TEST(MatrixTest, GetMaxBasisXYWithLargeAndSmallScalingFactorNonScaleTranslate) {
283  Matrix m = Matrix::MakeScale({2.625e+20, 2.625e+20, 1});
284  m.e[0][1] = 2;
285 
286  EXPECT_TRUE(std::isinf(m.GetMaxBasisLengthXY()));
287 }
288 
289 TEST(MatrixTest, TranslateWithPerspective) {
290  Matrix m = Matrix::MakeRow(1.0, 0.0, 0.0, 10.0, //
291  0.0, 1.0, 0.0, 20.0, //
292  0.0, 0.0, 1.0, 0.0, //
293  0.0, 2.0, 0.0, 30.0);
294  Matrix result = m.Translate({100, 200});
295  EXPECT_TRUE(MatrixNear(result, Matrix::MakeRow(1.0, 0.0, 0.0, 110.0, //
296  0.0, 1.0, 0.0, 220.0, //
297  0.0, 0.0, 1.0, 0.0, //
298  0.0, 2.0, 0.0, 430.0)));
299 }
300 
301 TEST(MatrixTest, MakeScaleTranslate) {
302  EXPECT_TRUE(MatrixNear(
303  Matrix::MakeTranslateScale({1, 1, 1.0 / 1024}, {10, 10, 1.0 / 1024}),
304  Matrix::MakeTranslation({10, 10, 1.0 / 1024}) *
305  Matrix::MakeScale({1, 1, 1.0 / 1024})));
306 
307  EXPECT_TRUE(MatrixNear(
308  Matrix::MakeTranslateScale({2, 2, 2}, {10, 10, 0}),
309  Matrix::MakeTranslation({10, 10, 0}) * Matrix::MakeScale({2, 2, 2})));
310 
311  EXPECT_TRUE(MatrixNear(
312  Matrix::MakeTranslateScale({0, 0, 0}, {0, 0, 0}),
313  Matrix::MakeTranslation({0, 0, 0}) * Matrix::MakeScale({0, 0, 0})));
314 }
315 
316 TEST(MatrixTest, To3x3) {
317  Matrix x(1.0, 0.0, 4.0, 0.0, //
318  0.0, 1.0, 4.0, 0.0, //
319  6.0, 5.0, 111.0, 7.0, //
320  0.0, 0.0, 9.0, 1.0);
321 
322  EXPECT_TRUE(MatrixNear(x.To3x3(), Matrix()));
323 }
324 
325 TEST(MatrixTest, MinMaxScales2D) {
326  // The GetScales2D() method is allowed to return the scales in any
327  // order so we need to take special care in verifying the return
328  // value to test them in either order.
329  auto check_pair = [](const Matrix& matrix, Scalar scale1, Scalar scale2) {
330  auto pair = matrix.GetScales2D();
331  EXPECT_TRUE(pair.has_value())
332  << "Scales: " << scale1 << ", " << scale2 << ", " << matrix;
333  if (ScalarNearlyEqual(pair->first, scale1)) {
334  EXPECT_FLOAT_EQ(pair->first, scale1) << matrix;
335  EXPECT_FLOAT_EQ(pair->second, scale2) << matrix;
336  } else {
337  EXPECT_FLOAT_EQ(pair->first, scale2) << matrix;
338  EXPECT_FLOAT_EQ(pair->second, scale1) << matrix;
339  }
340  };
341 
342  for (int i = 1; i < 10; i++) {
343  Scalar xScale = static_cast<Scalar>(i);
344  for (int j = 1; j < 10; j++) {
345  Scalar yScale = static_cast<Scalar>(j);
346  Scalar minScale = std::min(xScale, yScale);
347  Scalar maxScale = std::max(xScale, yScale);
348 
349  {
350  // Simple scale
351  Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
352  EXPECT_TRUE(matrix.GetMinScale2D().has_value());
353  EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
354  EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
355  EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
356  check_pair(matrix, xScale, yScale);
357  }
358 
359  {
360  // Simple scale with Z scale
361  Matrix matrix = Matrix::MakeScale({xScale, yScale, 5.0f});
362  EXPECT_TRUE(matrix.GetMinScale2D().has_value());
363  EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
364  EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
365  EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
366  check_pair(matrix, xScale, yScale);
367  }
368 
369  {
370  // Simple scale + translate
371  Matrix matrix = Matrix::MakeTranslateScale({xScale, yScale, 1.0f},
372  {10.0f, 15.0f, 2.0f});
373  EXPECT_TRUE(matrix.GetMinScale2D().has_value());
374  EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
375  EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
376  EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
377  check_pair(matrix, xScale, yScale);
378  }
379 
380  for (int d = 45; d < 360; d += 45) {
381  {
382  // Rotation * Scale
383  Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f}) *
385  EXPECT_TRUE(matrix.GetMinScale2D().has_value());
386  EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
387  EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
388  EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
389  check_pair(matrix, xScale, yScale);
390  }
391 
392  {
393  // Scale * Rotation
394  Matrix matrix = Matrix::MakeRotationZ(Degrees(d)) *
395  Matrix::MakeScale({xScale, yScale, 1.0f});
396  EXPECT_TRUE(matrix.GetMinScale2D().has_value());
397  EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
398  EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
399  EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
400  check_pair(matrix, xScale, yScale);
401  }
402  }
403 
404  {
405  // Scale + PerspectiveX (returns invalid values)
406  Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
407  matrix.m[3] = 0.1;
408  EXPECT_FALSE(matrix.GetMinScale2D().has_value());
409  EXPECT_FALSE(matrix.GetMaxScale2D().has_value());
410  EXPECT_FALSE(matrix.GetScales2D().has_value());
411  }
412 
413  {
414  // Scale + PerspectiveY (returns invalid values)
415  Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
416  matrix.m[7] = 0.1;
417  EXPECT_FALSE(matrix.GetMinScale2D().has_value());
418  EXPECT_FALSE(matrix.GetMaxScale2D().has_value());
419  EXPECT_FALSE(matrix.GetScales2D().has_value());
420  }
421 
422  {
423  // Scale + PerspectiveZ (Z ignored; returns actual scales)
424  Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
425  matrix.m[11] = 0.1;
426  EXPECT_TRUE(matrix.GetMinScale2D().has_value());
427  EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
428  EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
429  EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
430  check_pair(matrix, xScale, yScale);
431  }
432 
433  {
434  // Scale + PerspectiveW (returns invalid values)
435  Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
436  matrix.m[15] = 0.1;
437  EXPECT_FALSE(matrix.GetMinScale2D().has_value());
438  EXPECT_FALSE(matrix.GetMaxScale2D().has_value());
439  EXPECT_FALSE(matrix.GetScales2D().has_value());
440  }
441  }
442  }
443 }
444 
445 } // namespace testing
446 } // namespace impeller
int32_t x
inline ::testing::AssertionResult MatrixNear(impeller::Matrix a, impeller::Matrix b)
TEST(AllocationSizeTest, CanCreateTypedAllocations)
float Scalar
Definition: scalar.h:19
constexpr bool ScalarNearlyEqual(Scalar x, Scalar y, Scalar tolerance=kEhCloseEnough)
Definition: scalar.h:36
Scalar degrees
Definition: scalar.h:67
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
Scalar m[16]
Definition: matrix.h:39
constexpr Matrix Translate(const Vector3 &t) const
Definition: matrix.h:263
std::optional< Scalar > GetMinScale2D() const
Return the smaller of the two non-negative scales that will be applied to 2D coordinates by this matr...
Definition: matrix.h:356
constexpr bool IsAligned(Scalar tolerance=0) const
Definition: matrix.h:439
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
static Matrix MakeRotationY(Radians r)
Definition: matrix.h:208
constexpr bool HasPerspective2D() const
Definition: matrix.h:414
bool IsFinite() const
Definition: matrix.h:404
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
constexpr Vector3 TransformHomogenous(const Point &v) const
Definition: matrix.h:601
static constexpr Matrix MakeTranslateScale(const Vector3 &s, const Vector3 &t)
Definition: matrix.h:113
Scalar e[4][4]
Definition: matrix.h:40
static Matrix MakeRotationZ(Radians r)
Definition: matrix.h:223
std::optional< std::pair< Scalar, Scalar > > GetScales2D() const
Compute the two non-negative scales applied by this matrix to 2D coordinates and return them as an op...
Definition: matrix.cc:363
std::optional< Scalar > GetMaxScale2D() const
Return the smaller of the two non-negative scales that will be applied to 2D coordinates by this matr...
Definition: matrix.h:380
constexpr bool HasPerspective() const
Definition: matrix.h:418
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
constexpr bool IsAligned2D(Scalar tolerance=0) const
Definition: matrix.h:424
Scalar GetMaxBasisLengthXY() const
Return the maximum scale applied specifically to either the X axis or Y axis unit vectors (the bases)...
Definition: matrix.h:328
static Matrix MakeRotationX(Radians r)
Definition: matrix.h:193