Add intro to any Chrome app API with no overview docs.
[chromium-blink-merge.git] / cc / math_util_unittest.cc
blob0aa05234bb0bc0a1954ff670faba50eaa5d9298e
1 // Copyright 2012 The Chromium 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.
5 #include "cc/math_util.h"
7 #include <cmath>
9 #include "cc/test/geometry_test_utils.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gfx/rect.h"
13 #include "ui/gfx/rect_f.h"
14 #include "ui/gfx/transform.h"
16 namespace cc {
17 namespace {
19 TEST(MathUtilTest, verifyBackfaceVisibilityBasicCases)
21 gfx::Transform transform;
23 transform.MakeIdentity();
24 EXPECT_FALSE(transform.IsBackFaceVisible());
26 transform.MakeIdentity();
27 MathUtil::rotateEulerAngles(&transform, 0, 80, 0);
28 EXPECT_FALSE(transform.IsBackFaceVisible());
30 transform.MakeIdentity();
31 MathUtil::rotateEulerAngles(&transform, 0, 100, 0);
32 EXPECT_TRUE(transform.IsBackFaceVisible());
34 // Edge case, 90 degree rotation should return false.
35 transform.MakeIdentity();
36 MathUtil::rotateEulerAngles(&transform, 0, 90, 0);
37 EXPECT_FALSE(transform.IsBackFaceVisible());
40 TEST(MathUtilTest, verifyBackfaceVisibilityForPerspective)
42 gfx::Transform layerSpaceToProjectionPlane;
44 // This tests if IsBackFaceVisible works properly under perspective transforms.
45 // Specifically, layers that may have their back face visible in orthographic
46 // projection, may not actually have back face visible under perspective projection.
48 // Case 1: Layer is rotated by slightly more than 90 degrees, at the center of the
49 // prespective projection. In this case, the layer's back-side is visible to
50 // the camera.
51 layerSpaceToProjectionPlane.MakeIdentity();
52 layerSpaceToProjectionPlane.ApplyPerspectiveDepth(1);
53 layerSpaceToProjectionPlane.Translate3d(0, 0, 0);
54 MathUtil::rotateEulerAngles(&layerSpaceToProjectionPlane, 0, 100, 0);
55 EXPECT_TRUE(layerSpaceToProjectionPlane.IsBackFaceVisible());
57 // Case 2: Layer is rotated by slightly more than 90 degrees, but shifted off to the
58 // side of the camera. Because of the wide field-of-view, the layer's front
59 // side is still visible.
61 // |<-- front side of layer is visible to perspective camera
62 // \ | /
63 // \ | /
64 // \| /
65 // | /
66 // |\ /<-- camera field of view
67 // | \ /
68 // back side of layer -->| \ /
69 // \./ <-- camera origin
71 layerSpaceToProjectionPlane.MakeIdentity();
72 layerSpaceToProjectionPlane.ApplyPerspectiveDepth(1);
73 layerSpaceToProjectionPlane.Translate3d(-10, 0, 0);
74 MathUtil::rotateEulerAngles(&layerSpaceToProjectionPlane, 0, 100, 0);
75 EXPECT_FALSE(layerSpaceToProjectionPlane.IsBackFaceVisible());
77 // Case 3: Additionally rotating the layer by 180 degrees should of course show the
78 // opposite result of case 2.
79 MathUtil::rotateEulerAngles(&layerSpaceToProjectionPlane, 0, 180, 0);
80 EXPECT_TRUE(layerSpaceToProjectionPlane.IsBackFaceVisible());
83 TEST(MathUtilTest, verifyProjectionOfPerpendicularPlane)
85 // In this case, the m33() element of the transform becomes zero, which could cause a
86 // divide-by-zero when projecting points/quads.
88 gfx::Transform transform;
89 transform.MakeIdentity();
90 transform.matrix().setDouble(2, 2, 0);
92 gfx::RectF rect = gfx::RectF(0, 0, 1, 1);
93 gfx::RectF projectedRect = MathUtil::projectClippedRect(transform, rect);
95 EXPECT_EQ(0, projectedRect.x());
96 EXPECT_EQ(0, projectedRect.y());
97 EXPECT_TRUE(projectedRect.IsEmpty());
100 TEST(MathUtilTest, verifyEnclosingClippedRectUsesCorrectInitialBounds)
102 HomogeneousCoordinate h1(-100, -100, 0, 1);
103 HomogeneousCoordinate h2(-10, -10, 0, 1);
104 HomogeneousCoordinate h3(10, 10, 0, -1);
105 HomogeneousCoordinate h4(100, 100, 0, -1);
107 // The bounds of the enclosing clipped rect should be -100 to -10 for both x and y.
108 // However, if there is a bug where the initial xmin/xmax/ymin/ymax are initialized to
109 // numeric_limits<float>::min() (which is zero, not -flt_max) then the enclosing
110 // clipped rect will be computed incorrectly.
111 gfx::RectF result = MathUtil::computeEnclosingClippedRect(h1, h2, h3, h4);
113 EXPECT_FLOAT_RECT_EQ(gfx::RectF(gfx::PointF(-100, -100), gfx::SizeF(90, 90)), result);
116 TEST(MathUtilTest, verifyEnclosingRectOfVerticesUsesCorrectInitialBounds)
118 gfx::PointF vertices[3];
119 int numVertices = 3;
121 vertices[0] = gfx::PointF(-10, -100);
122 vertices[1] = gfx::PointF(-100, -10);
123 vertices[2] = gfx::PointF(-30, -30);
125 // The bounds of the enclosing rect should be -100 to -10 for both x and y. However,
126 // if there is a bug where the initial xmin/xmax/ymin/ymax are initialized to
127 // numeric_limits<float>::min() (which is zero, not -flt_max) then the enclosing
128 // clipped rect will be computed incorrectly.
129 gfx::RectF result = MathUtil::computeEnclosingRectOfVertices(vertices, numVertices);
131 EXPECT_FLOAT_RECT_EQ(gfx::RectF(gfx::PointF(-100, -100), gfx::SizeF(90, 90)), result);
134 TEST(MathUtilTest, smallestAngleBetweenVectors)
136 gfx::Vector2dF x(1, 0);
137 gfx::Vector2dF y(0, 1);
138 gfx::Vector2dF testVector(0.5, 0.5);
140 // Orthogonal vectors are at an angle of 90 degress.
141 EXPECT_EQ(90, MathUtil::smallestAngleBetweenVectors(x, y));
143 // A vector makes a zero angle with itself.
144 EXPECT_EQ(0, MathUtil::smallestAngleBetweenVectors(x, x));
145 EXPECT_EQ(0, MathUtil::smallestAngleBetweenVectors(y, y));
146 EXPECT_EQ(0, MathUtil::smallestAngleBetweenVectors(testVector, testVector));
148 // Parallel but reversed vectors are at 180 degrees.
149 EXPECT_FLOAT_EQ(180, MathUtil::smallestAngleBetweenVectors(x, -x));
150 EXPECT_FLOAT_EQ(180, MathUtil::smallestAngleBetweenVectors(y, -y));
151 EXPECT_FLOAT_EQ(180, MathUtil::smallestAngleBetweenVectors(testVector, -testVector));
153 // The test vector is at a known angle.
154 EXPECT_FLOAT_EQ(45, std::floor(MathUtil::smallestAngleBetweenVectors(testVector, x)));
155 EXPECT_FLOAT_EQ(45, std::floor(MathUtil::smallestAngleBetweenVectors(testVector, y)));
158 TEST(MathUtilTest, vectorProjection)
160 gfx::Vector2dF x(1, 0);
161 gfx::Vector2dF y(0, 1);
162 gfx::Vector2dF testVector(0.3f, 0.7f);
164 // Orthogonal vectors project to a zero vector.
165 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), MathUtil::projectVector(x, y));
166 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), MathUtil::projectVector(y, x));
168 // Projecting a vector onto the orthonormal basis gives the corresponding component of the
169 // vector.
170 EXPECT_VECTOR_EQ(gfx::Vector2dF(testVector.x(), 0), MathUtil::projectVector(testVector, x));
171 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, testVector.y()), MathUtil::projectVector(testVector, y));
173 // Finally check than an arbitrary vector projected to another one gives a vector parallel to
174 // the second vector.
175 gfx::Vector2dF targetVector(0.5, 0.2f);
176 gfx::Vector2dF projectedVector = MathUtil::projectVector(testVector, targetVector);
177 EXPECT_EQ(projectedVector.x() / targetVector.x(),
178 projectedVector.y() / targetVector.y());
181 // TODO(shawnsingh): these macros are redundant with those from
182 // web_transformation_matrix_unittests, but for now they
183 // are different enough to be appropriate here.
185 #define EXPECT_ROW1_EQ(a, b, c, d, transform) \
186 EXPECT_FLOAT_EQ((a), (transform).matrix().getDouble(0, 0)); \
187 EXPECT_FLOAT_EQ((b), (transform).matrix().getDouble(0, 1)); \
188 EXPECT_FLOAT_EQ((c), (transform).matrix().getDouble(0, 2)); \
189 EXPECT_FLOAT_EQ((d), (transform).matrix().getDouble(0, 3));
191 #define EXPECT_ROW2_EQ(a, b, c, d, transform) \
192 EXPECT_FLOAT_EQ((a), (transform).matrix().getDouble(1, 0)); \
193 EXPECT_FLOAT_EQ((b), (transform).matrix().getDouble(1, 1)); \
194 EXPECT_FLOAT_EQ((c), (transform).matrix().getDouble(1, 2)); \
195 EXPECT_FLOAT_EQ((d), (transform).matrix().getDouble(1, 3));
197 #define EXPECT_ROW3_EQ(a, b, c, d, transform) \
198 EXPECT_FLOAT_EQ((a), (transform).matrix().getDouble(2, 0)); \
199 EXPECT_FLOAT_EQ((b), (transform).matrix().getDouble(2, 1)); \
200 EXPECT_FLOAT_EQ((c), (transform).matrix().getDouble(2, 2)); \
201 EXPECT_FLOAT_EQ((d), (transform).matrix().getDouble(2, 3));
203 #define EXPECT_ROW4_EQ(a, b, c, d, transform) \
204 EXPECT_FLOAT_EQ((a), (transform).matrix().getDouble(3, 0)); \
205 EXPECT_FLOAT_EQ((b), (transform).matrix().getDouble(3, 1)); \
206 EXPECT_FLOAT_EQ((c), (transform).matrix().getDouble(3, 2)); \
207 EXPECT_FLOAT_EQ((d), (transform).matrix().getDouble(3, 3));
209 // Checking float values for equality close to zero is not robust using EXPECT_FLOAT_EQ
210 // (see gtest documentation). So, to verify rotation matrices, we must use a looser
211 // absolute error threshold in some places.
212 #define EXPECT_ROW1_NEAR(a, b, c, d, transform, errorThreshold) \
213 EXPECT_NEAR((a), (transform).matrix().getDouble(0, 0), (errorThreshold)); \
214 EXPECT_NEAR((b), (transform).matrix().getDouble(0, 1), (errorThreshold)); \
215 EXPECT_NEAR((c), (transform).matrix().getDouble(0, 2), (errorThreshold)); \
216 EXPECT_NEAR((d), (transform).matrix().getDouble(0, 3), (errorThreshold));
218 #define EXPECT_ROW2_NEAR(a, b, c, d, transform, errorThreshold) \
219 EXPECT_NEAR((a), (transform).matrix().getDouble(1, 0), (errorThreshold)); \
220 EXPECT_NEAR((b), (transform).matrix().getDouble(1, 1), (errorThreshold)); \
221 EXPECT_NEAR((c), (transform).matrix().getDouble(1, 2), (errorThreshold)); \
222 EXPECT_NEAR((d), (transform).matrix().getDouble(1, 3), (errorThreshold));
224 #define EXPECT_ROW3_NEAR(a, b, c, d, transform, errorThreshold) \
225 EXPECT_NEAR((a), (transform).matrix().getDouble(2, 0), (errorThreshold)); \
226 EXPECT_NEAR((b), (transform).matrix().getDouble(2, 1), (errorThreshold)); \
227 EXPECT_NEAR((c), (transform).matrix().getDouble(2, 2), (errorThreshold)); \
228 EXPECT_NEAR((d), (transform).matrix().getDouble(2, 3), (errorThreshold));
230 #define ERROR_THRESHOLD 1e-14
231 #define LOOSE_ERROR_THRESHOLD 1e-7
233 static void initializeTestMatrix(gfx::Transform* transform)
235 SkMatrix44& matrix = transform->matrix();
236 matrix.setDouble(0, 0, 10);
237 matrix.setDouble(1, 0, 11);
238 matrix.setDouble(2, 0, 12);
239 matrix.setDouble(3, 0, 13);
240 matrix.setDouble(0, 1, 14);
241 matrix.setDouble(1, 1, 15);
242 matrix.setDouble(2, 1, 16);
243 matrix.setDouble(3, 1, 17);
244 matrix.setDouble(0, 2, 18);
245 matrix.setDouble(1, 2, 19);
246 matrix.setDouble(2, 2, 20);
247 matrix.setDouble(3, 2, 21);
248 matrix.setDouble(0, 3, 22);
249 matrix.setDouble(1, 3, 23);
250 matrix.setDouble(2, 3, 24);
251 matrix.setDouble(3, 3, 25);
253 // Sanity check
254 EXPECT_ROW1_EQ(10, 14, 18, 22, (*transform));
255 EXPECT_ROW2_EQ(11, 15, 19, 23, (*transform));
256 EXPECT_ROW3_EQ(12, 16, 20, 24, (*transform));
257 EXPECT_ROW4_EQ(13, 17, 21, 25, (*transform));
260 static void initializeTestMatrix2(gfx::Transform* transform)
262 SkMatrix44& matrix = transform->matrix();
263 matrix.setDouble(0, 0, 30);
264 matrix.setDouble(1, 0, 31);
265 matrix.setDouble(2, 0, 32);
266 matrix.setDouble(3, 0, 33);
267 matrix.setDouble(0, 1, 34);
268 matrix.setDouble(1, 1, 35);
269 matrix.setDouble(2, 1, 36);
270 matrix.setDouble(3, 1, 37);
271 matrix.setDouble(0, 2, 38);
272 matrix.setDouble(1, 2, 39);
273 matrix.setDouble(2, 2, 40);
274 matrix.setDouble(3, 2, 41);
275 matrix.setDouble(0, 3, 42);
276 matrix.setDouble(1, 3, 43);
277 matrix.setDouble(2, 3, 44);
278 matrix.setDouble(3, 3, 45);
280 // Sanity check
281 EXPECT_ROW1_EQ(30, 34, 38, 42, (*transform));
282 EXPECT_ROW2_EQ(31, 35, 39, 43, (*transform));
283 EXPECT_ROW3_EQ(32, 36, 40, 44, (*transform));
284 EXPECT_ROW4_EQ(33, 37, 41, 45, (*transform));
287 TEST(MathUtilGfxTransformTest, verifyDefaultConstructorCreatesIdentityMatrix)
289 gfx::Transform A;
290 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
291 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
292 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
293 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
294 EXPECT_TRUE(A.IsIdentity());
297 TEST(MathUtilGfxTransformTest, verifyCreateGfxTransformFor2dElements)
299 gfx::Transform A = MathUtil::createGfxTransform(1, 2, 3, 4, 5, 6);
300 EXPECT_ROW1_EQ(1, 3, 0, 5, A);
301 EXPECT_ROW2_EQ(2, 4, 0, 6, A);
302 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
303 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
306 TEST(MathUtilGfxTransformTest, verifyCreateGfxTransformForAllElements)
308 gfx::Transform A = MathUtil::createGfxTransform(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
309 EXPECT_ROW1_EQ(1, 5, 9, 13, A);
310 EXPECT_ROW2_EQ(2, 6, 10, 14, A);
311 EXPECT_ROW3_EQ(3, 7, 11, 15, A);
312 EXPECT_ROW4_EQ(4, 8, 12, 16, A);
315 TEST(MathUtilGfxTransformTest, verifyCopyConstructor)
317 gfx::Transform A;
318 initializeTestMatrix(&A);
320 // Copy constructor should produce exact same elements as matrix A.
321 gfx::Transform B(A);
322 EXPECT_ROW1_EQ(10, 14, 18, 22, B);
323 EXPECT_ROW2_EQ(11, 15, 19, 23, B);
324 EXPECT_ROW3_EQ(12, 16, 20, 24, B);
325 EXPECT_ROW4_EQ(13, 17, 21, 25, B);
328 TEST(MathUtilGfxTransformTest, verifyMatrixInversion)
330 // Invert a translation
331 gfx::Transform translation;
332 translation.Translate3d(2, 3, 4);
333 EXPECT_TRUE(translation.IsInvertible());
335 gfx::Transform inverseTranslation = MathUtil::inverse(translation);
336 EXPECT_ROW1_EQ(1, 0, 0, -2, inverseTranslation);
337 EXPECT_ROW2_EQ(0, 1, 0, -3, inverseTranslation);
338 EXPECT_ROW3_EQ(0, 0, 1, -4, inverseTranslation);
339 EXPECT_ROW4_EQ(0, 0, 0, 1, inverseTranslation);
341 // Note that inversion should not have changed the original matrix.
342 EXPECT_ROW1_EQ(1, 0, 0, 2, translation);
343 EXPECT_ROW2_EQ(0, 1, 0, 3, translation);
344 EXPECT_ROW3_EQ(0, 0, 1, 4, translation);
345 EXPECT_ROW4_EQ(0, 0, 0, 1, translation);
347 // Invert a non-uniform scale
348 gfx::Transform scale;
349 scale.Scale3d(4, 10, 100);
350 EXPECT_TRUE(scale.IsInvertible());
352 gfx::Transform inverseScale = MathUtil::inverse(scale);
353 EXPECT_ROW1_EQ(0.25, 0, 0, 0, inverseScale);
354 EXPECT_ROW2_EQ(0, .1f, 0, 0, inverseScale);
355 EXPECT_ROW3_EQ(0, 0, .01f, 0, inverseScale);
356 EXPECT_ROW4_EQ(0, 0, 0, 1, inverseScale);
358 // Try to invert a matrix that is not invertible.
359 // The inverse() function should simply return an identity matrix.
360 gfx::Transform notInvertible;
361 notInvertible.matrix().setDouble(0, 0, 0);
362 notInvertible.matrix().setDouble(1, 1, 0);
363 notInvertible.matrix().setDouble(2, 2, 0);
364 notInvertible.matrix().setDouble(3, 3, 0);
365 EXPECT_FALSE(notInvertible.IsInvertible());
367 gfx::Transform inverseOfNotInvertible;
368 initializeTestMatrix(&inverseOfNotInvertible); // initialize this to something non-identity, to make sure that assignment below actually took place.
369 inverseOfNotInvertible = MathUtil::inverse(notInvertible);
370 EXPECT_TRUE(inverseOfNotInvertible.IsIdentity());
373 TEST(MathUtilGfxTransformTest, verifyTo2DTransform)
375 gfx::Transform A;
376 initializeTestMatrix(&A);
378 gfx::Transform B = MathUtil::to2dTransform(A);
380 EXPECT_ROW1_EQ(10, 14, 0, 22, B);
381 EXPECT_ROW2_EQ(11, 15, 0, 23, B);
382 EXPECT_ROW3_EQ(0, 0, 1, 0, B);
383 EXPECT_ROW4_EQ(13, 17, 0, 25, B);
385 // Note that to2DTransform should not have changed the original matrix.
386 EXPECT_ROW1_EQ(10, 14, 18, 22, A);
387 EXPECT_ROW2_EQ(11, 15, 19, 23, A);
388 EXPECT_ROW3_EQ(12, 16, 20, 24, A);
389 EXPECT_ROW4_EQ(13, 17, 21, 25, A);
392 TEST(MathUtilGfxTransformTest, verifyAssignmentOperator)
394 gfx::Transform A;
395 initializeTestMatrix(&A);
396 gfx::Transform B;
397 initializeTestMatrix2(&B);
398 gfx::Transform C;
399 initializeTestMatrix2(&C);
400 C = B = A;
402 // Both B and C should now have been re-assigned to the value of A.
403 EXPECT_ROW1_EQ(10, 14, 18, 22, B);
404 EXPECT_ROW2_EQ(11, 15, 19, 23, B);
405 EXPECT_ROW3_EQ(12, 16, 20, 24, B);
406 EXPECT_ROW4_EQ(13, 17, 21, 25, B);
408 EXPECT_ROW1_EQ(10, 14, 18, 22, C);
409 EXPECT_ROW2_EQ(11, 15, 19, 23, C);
410 EXPECT_ROW3_EQ(12, 16, 20, 24, C);
411 EXPECT_ROW4_EQ(13, 17, 21, 25, C);
414 TEST(MathUtilGfxTransformTest, verifyEqualsBooleanOperator)
416 gfx::Transform A;
417 initializeTestMatrix(&A);
419 gfx::Transform B;
420 initializeTestMatrix(&B);
421 EXPECT_TRUE(A == B);
423 // Modifying multiple elements should cause equals operator to return false.
424 gfx::Transform C;
425 initializeTestMatrix2(&C);
426 EXPECT_FALSE(A == C);
428 // Modifying any one individual element should cause equals operator to return false.
429 gfx::Transform D;
430 D = A;
431 D.matrix().setDouble(0, 0, 0);
432 EXPECT_FALSE(A == D);
434 D = A;
435 D.matrix().setDouble(1, 0, 0);
436 EXPECT_FALSE(A == D);
438 D = A;
439 D.matrix().setDouble(2, 0, 0);
440 EXPECT_FALSE(A == D);
442 D = A;
443 D.matrix().setDouble(3, 0, 0);
444 EXPECT_FALSE(A == D);
446 D = A;
447 D.matrix().setDouble(0, 1, 0);
448 EXPECT_FALSE(A == D);
450 D = A;
451 D.matrix().setDouble(1, 1, 0);
452 EXPECT_FALSE(A == D);
454 D = A;
455 D.matrix().setDouble(2, 1, 0);
456 EXPECT_FALSE(A == D);
458 D = A;
459 D.matrix().setDouble(3, 1, 0);
460 EXPECT_FALSE(A == D);
462 D = A;
463 D.matrix().setDouble(0, 2, 0);
464 EXPECT_FALSE(A == D);
466 D = A;
467 D.matrix().setDouble(1, 2, 0);
468 EXPECT_FALSE(A == D);
470 D = A;
471 D.matrix().setDouble(2, 2, 0);
472 EXPECT_FALSE(A == D);
474 D = A;
475 D.matrix().setDouble(3, 2, 0);
476 EXPECT_FALSE(A == D);
478 D = A;
479 D.matrix().setDouble(0, 3, 0);
480 EXPECT_FALSE(A == D);
482 D = A;
483 D.matrix().setDouble(1, 3, 0);
484 EXPECT_FALSE(A == D);
486 D = A;
487 D.matrix().setDouble(2, 3, 0);
488 EXPECT_FALSE(A == D);
490 D = A;
491 D.matrix().setDouble(3, 3, 0);
492 EXPECT_FALSE(A == D);
495 TEST(MathUtilGfxTransformTest, verifyMultiplyOperator)
497 gfx::Transform A;
498 initializeTestMatrix(&A);
500 gfx::Transform B;
501 initializeTestMatrix2(&B);
503 gfx::Transform C = A * B;
504 EXPECT_ROW1_EQ(2036, 2292, 2548, 2804, C);
505 EXPECT_ROW2_EQ(2162, 2434, 2706, 2978, C);
506 EXPECT_ROW3_EQ(2288, 2576, 2864, 3152, C);
507 EXPECT_ROW4_EQ(2414, 2718, 3022, 3326, C);
509 // Just an additional sanity check; matrix multiplication is not commutative.
510 EXPECT_FALSE(A * B == B * A);
513 TEST(MathUtilGfxTransformTest, verifyMultiplyAndAssignOperator)
515 gfx::Transform A;
516 initializeTestMatrix(&A);
518 gfx::Transform B;
519 initializeTestMatrix2(&B);
521 A *= B;
522 EXPECT_ROW1_EQ(2036, 2292, 2548, 2804, A);
523 EXPECT_ROW2_EQ(2162, 2434, 2706, 2978, A);
524 EXPECT_ROW3_EQ(2288, 2576, 2864, 3152, A);
525 EXPECT_ROW4_EQ(2414, 2718, 3022, 3326, A);
527 // Just an additional sanity check; matrix multiplication is not commutative.
528 gfx::Transform C = A;
529 C *= B;
530 gfx::Transform D = B;
531 D *= A;
532 EXPECT_FALSE(C == D);
535 TEST(MathUtilGfxTransformTest, verifyMatrixMultiplication)
537 gfx::Transform A;
538 initializeTestMatrix(&A);
540 gfx::Transform B;
541 initializeTestMatrix2(&B);
543 A.PreconcatTransform(B);
544 EXPECT_ROW1_EQ(2036, 2292, 2548, 2804, A);
545 EXPECT_ROW2_EQ(2162, 2434, 2706, 2978, A);
546 EXPECT_ROW3_EQ(2288, 2576, 2864, 3152, A);
547 EXPECT_ROW4_EQ(2414, 2718, 3022, 3326, A);
550 TEST(MathUtilGfxTransformTest, verifyMakeIdentiy)
552 gfx::Transform A;
553 initializeTestMatrix(&A);
554 A.MakeIdentity();
555 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
556 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
557 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
558 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
559 EXPECT_TRUE(A.IsIdentity());
562 TEST(MathUtilGfxTransformTest, verifyTranslate)
564 gfx::Transform A;
565 A.Translate(2, 3);
566 EXPECT_ROW1_EQ(1, 0, 0, 2, A);
567 EXPECT_ROW2_EQ(0, 1, 0, 3, A);
568 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
569 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
571 // Verify that Translate() post-multiplies the existing matrix.
572 A.MakeIdentity();
573 A.Scale(5, 5);
574 A.Translate(2, 3);
575 EXPECT_ROW1_EQ(5, 0, 0, 10, A);
576 EXPECT_ROW2_EQ(0, 5, 0, 15, A);
577 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
578 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
581 TEST(MathUtilGfxTransformTest, verifyTranslate3d)
583 gfx::Transform A;
584 A.Translate3d(2, 3, 4);
585 EXPECT_ROW1_EQ(1, 0, 0, 2, A);
586 EXPECT_ROW2_EQ(0, 1, 0, 3, A);
587 EXPECT_ROW3_EQ(0, 0, 1, 4, A);
588 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
590 // Verify that Translate3d() post-multiplies the existing matrix.
591 A.MakeIdentity();
592 A.Scale3d(6, 7, 8);
593 A.Translate3d(2, 3, 4);
594 EXPECT_ROW1_EQ(6, 0, 0, 12, A);
595 EXPECT_ROW2_EQ(0, 7, 0, 21, A);
596 EXPECT_ROW3_EQ(0, 0, 8, 32, A);
597 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
600 TEST(MathUtilGfxTransformTest, verifyScale)
602 gfx::Transform A;
603 A.Scale(6, 7);
604 EXPECT_ROW1_EQ(6, 0, 0, 0, A);
605 EXPECT_ROW2_EQ(0, 7, 0, 0, A);
606 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
607 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
609 // Verify that Scale() post-multiplies the existing matrix.
610 A.MakeIdentity();
611 A.Translate3d(2, 3, 4);
612 A.Scale(6, 7);
613 EXPECT_ROW1_EQ(6, 0, 0, 2, A);
614 EXPECT_ROW2_EQ(0, 7, 0, 3, A);
615 EXPECT_ROW3_EQ(0, 0, 1, 4, A);
616 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
619 TEST(MathUtilGfxTransformTest, verifyScale3d)
621 gfx::Transform A;
622 A.Scale3d(6, 7, 8);
623 EXPECT_ROW1_EQ(6, 0, 0, 0, A);
624 EXPECT_ROW2_EQ(0, 7, 0, 0, A);
625 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
626 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
628 // Verify that scale3d() post-multiplies the existing matrix.
629 A.MakeIdentity();
630 A.Translate3d(2, 3, 4);
631 A.Scale3d(6, 7, 8);
632 EXPECT_ROW1_EQ(6, 0, 0, 2, A);
633 EXPECT_ROW2_EQ(0, 7, 0, 3, A);
634 EXPECT_ROW3_EQ(0, 0, 8, 4, A);
635 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
638 TEST(MathUtilGfxTransformTest, verifyRotate)
640 gfx::Transform A;
641 A.Rotate(90);
642 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD);
643 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD);
644 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
645 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
647 // Verify that Rotate() post-multiplies the existing matrix.
648 A.MakeIdentity();
649 A.Scale3d(6, 7, 8);
650 A.Rotate(90);
651 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD);
652 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD);
653 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
654 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
657 TEST(MathUtilGfxTransformTest, verifyRotateEulerAngles)
659 gfx::Transform A;
661 // Check rotation about z-axis
662 A.MakeIdentity();
663 MathUtil::rotateEulerAngles(&A, 0, 0, 90);
664 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD);
665 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD);
666 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
667 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
669 // Check rotation about x-axis
670 A.MakeIdentity();
671 MathUtil::rotateEulerAngles(&A, 90, 0, 0);
672 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
673 EXPECT_ROW2_NEAR(0, 0, -1, 0, A, ERROR_THRESHOLD);
674 EXPECT_ROW3_NEAR(0, 1, 0, 0, A, ERROR_THRESHOLD);
675 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
677 // Check rotation about y-axis.
678 // Note carefully, the expected pattern is inverted compared to rotating about x axis or z axis.
679 A.MakeIdentity();
680 MathUtil::rotateEulerAngles(&A, 0, 90, 0);
681 EXPECT_ROW1_NEAR(0, 0, 1, 0, A, ERROR_THRESHOLD);
682 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
683 EXPECT_ROW3_NEAR(-1, 0, 0, 0, A, ERROR_THRESHOLD);
684 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
686 // Verify that rotate3d(rx, ry, rz) post-multiplies the existing matrix.
687 A.MakeIdentity();
688 A.Scale3d(6, 7, 8);
689 MathUtil::rotateEulerAngles(&A, 0, 0, 90);
690 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD);
691 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD);
692 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
693 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
696 TEST(MathUtilGfxTransformTest, verifyRotateEulerAnglesOrderOfCompositeRotations)
698 // Rotate3d(degreesX, degreesY, degreesZ) is actually composite transform consiting of
699 // three primitive rotations. This test verifies that the ordering of those three
700 // transforms is the intended ordering.
702 // The correct ordering for this test case should be:
703 // 1. rotate by 30 degrees about z-axis
704 // 2. rotate by 20 degrees about y-axis
705 // 3. rotate by 10 degrees about x-axis
707 // Note: there are 6 possible orderings of 3 transforms. For the specific transforms
708 // used in this test, all 6 combinations produce a unique matrix that is different
709 // from the other orderings. That way, this test verifies the exact ordering.
711 gfx::Transform A;
712 A.MakeIdentity();
713 MathUtil::rotateEulerAngles(&A, 10, 20, 30);
715 EXPECT_ROW1_NEAR(0.8137976813493738026394908,
716 -0.4409696105298823720630708,
717 0.3785223063697923939763257,
718 0, A, ERROR_THRESHOLD);
719 EXPECT_ROW2_NEAR(0.4698463103929541584413698,
720 0.8825641192593856043657752,
721 0.0180283112362972230968694,
722 0, A, ERROR_THRESHOLD);
723 EXPECT_ROW3_NEAR(-0.3420201433256686573969318,
724 0.1631759111665348205288950,
725 0.9254165783983233639631294,
726 0, A, ERROR_THRESHOLD);
727 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
730 TEST(MathUtilGfxTransformTest, verifyRotateAboutXAxis)
732 gfx::Transform A;
733 double sin45 = 0.5 * sqrt(2.0);
734 double cos45 = sin45;
736 A.MakeIdentity();
737 A.RotateAboutXAxis(90);
738 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
739 EXPECT_ROW2_NEAR(0, 0, -1, 0, A, ERROR_THRESHOLD);
740 EXPECT_ROW3_NEAR(0, 1, 0, 0, A, ERROR_THRESHOLD);
741 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
743 A.MakeIdentity();
744 A.RotateAboutXAxis(45);
745 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
746 EXPECT_ROW2_NEAR(0, cos45, -sin45, 0, A, ERROR_THRESHOLD);
747 EXPECT_ROW3_NEAR(0, sin45, cos45, 0, A, ERROR_THRESHOLD);
748 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
750 // Verify that rotateAboutXAxis(angle) post-multiplies the existing matrix.
751 A.MakeIdentity();
752 A.Scale3d(6, 7, 8);
753 A.RotateAboutXAxis(90);
754 EXPECT_ROW1_NEAR(6, 0, 0, 0, A, ERROR_THRESHOLD);
755 EXPECT_ROW2_NEAR(0, 0, -7, 0, A, ERROR_THRESHOLD);
756 EXPECT_ROW3_NEAR(0, 8, 0, 0, A, ERROR_THRESHOLD);
757 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
760 TEST(MathUtilGfxTransformTest, verifyRotateAboutYAxis)
762 gfx::Transform A;
763 double sin45 = 0.5 * sqrt(2.0);
764 double cos45 = sin45;
766 // Note carefully, the expected pattern is inverted compared to rotating about x axis or z axis.
767 A.MakeIdentity();
768 A.RotateAboutYAxis(90);
769 EXPECT_ROW1_NEAR(0, 0, 1, 0, A, ERROR_THRESHOLD);
770 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
771 EXPECT_ROW3_NEAR(-1, 0, 0, 0, A, ERROR_THRESHOLD);
772 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
774 A.MakeIdentity();
775 A.RotateAboutYAxis(45);
776 EXPECT_ROW1_NEAR(cos45, 0, sin45, 0, A, ERROR_THRESHOLD);
777 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
778 EXPECT_ROW3_NEAR(-sin45, 0, cos45, 0, A, ERROR_THRESHOLD);
779 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
781 // Verify that rotateAboutYAxis(angle) post-multiplies the existing matrix.
782 A.MakeIdentity();
783 A.Scale3d(6, 7, 8);
784 A.RotateAboutYAxis(90);
785 EXPECT_ROW1_NEAR(0, 0, 6, 0, A, ERROR_THRESHOLD);
786 EXPECT_ROW2_NEAR(0, 7, 0, 0, A, ERROR_THRESHOLD);
787 EXPECT_ROW3_NEAR(-8, 0, 0, 0, A, ERROR_THRESHOLD);
788 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
791 TEST(MathUtilGfxTransformTest, verifyRotateAboutZAxis)
793 gfx::Transform A;
794 double sin45 = 0.5 * sqrt(2.0);
795 double cos45 = sin45;
797 A.MakeIdentity();
798 A.RotateAboutZAxis(90);
799 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD);
800 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD);
801 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
802 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
804 A.MakeIdentity();
805 A.RotateAboutZAxis(45);
806 EXPECT_ROW1_NEAR(cos45, -sin45, 0, 0, A, ERROR_THRESHOLD);
807 EXPECT_ROW2_NEAR(sin45, cos45, 0, 0, A, ERROR_THRESHOLD);
808 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
809 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
811 // Verify that rotateAboutZAxis(angle) post-multiplies the existing matrix.
812 A.MakeIdentity();
813 A.Scale3d(6, 7, 8);
814 A.RotateAboutZAxis(90);
815 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD);
816 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD);
817 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
818 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
821 TEST(MathUtilGfxTransformTest, verifyRotateAboutForAlignedAxes)
823 gfx::Transform A;
825 // Check rotation about z-axis
826 A.MakeIdentity();
827 A.RotateAbout(gfx::Vector3dF(0, 0, 1), 90);
828 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD);
829 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD);
830 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
831 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
833 // Check rotation about x-axis
834 A.MakeIdentity();
835 A.RotateAbout(gfx::Vector3dF(1, 0, 0), 90);
836 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
837 EXPECT_ROW2_NEAR(0, 0, -1, 0, A, ERROR_THRESHOLD);
838 EXPECT_ROW3_NEAR(0, 1, 0, 0, A, ERROR_THRESHOLD);
839 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
841 // Check rotation about y-axis.
842 // Note carefully, the expected pattern is inverted compared to rotating about x axis or z axis.
843 A.MakeIdentity();
844 A.RotateAbout(gfx::Vector3dF(0, 1, 0), 90);
845 EXPECT_ROW1_NEAR(0, 0, 1, 0, A, ERROR_THRESHOLD);
846 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
847 EXPECT_ROW3_NEAR(-1, 0, 0, 0, A, ERROR_THRESHOLD);
848 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
850 // Verify that rotate3d(axis, angle) post-multiplies the existing matrix.
851 A.MakeIdentity();
852 A.Scale3d(6, 7, 8);
853 A.RotateAboutZAxis(90);
854 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD);
855 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD);
856 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
857 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
860 TEST(MathUtilGfxTransformTest, verifyRotateAboutForArbitraryAxis)
862 // Check rotation about an arbitrary non-axis-aligned vector.
863 gfx::Transform A;
864 A.RotateAbout(gfx::Vector3dF(1, 1, 1), 90);
865 EXPECT_ROW1_NEAR(0.3333333333333334258519187,
866 -0.2440169358562924717404030,
867 0.9106836025229592124219380,
868 0, A, ERROR_THRESHOLD);
869 EXPECT_ROW2_NEAR(0.9106836025229592124219380,
870 0.3333333333333334258519187,
871 -0.2440169358562924717404030,
872 0, A, ERROR_THRESHOLD);
873 EXPECT_ROW3_NEAR(-0.2440169358562924717404030,
874 0.9106836025229592124219380,
875 0.3333333333333334258519187,
876 0, A, ERROR_THRESHOLD);
877 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
880 TEST(MathUtilGfxTransformTest, verifyRotateAboutForDegenerateAxis)
882 // Check rotation about a degenerate zero vector.
883 // It is expected to skip applying the rotation.
884 gfx::Transform A;
886 A.RotateAbout(gfx::Vector3dF(0, 0, 0), 45);
887 // Verify that A remains unchanged.
888 EXPECT_TRUE(A.IsIdentity());
890 initializeTestMatrix(&A);
891 A.RotateAbout(gfx::Vector3dF(0, 0, 0), 35);
893 // Verify that A remains unchanged.
894 EXPECT_ROW1_EQ(10, 14, 18, 22, A);
895 EXPECT_ROW2_EQ(11, 15, 19, 23, A);
896 EXPECT_ROW3_EQ(12, 16, 20, 24, A);
897 EXPECT_ROW4_EQ(13, 17, 21, 25, A);
900 TEST(MathUtilGfxTransformTest, verifySkewX)
902 gfx::Transform A;
903 A.SkewX(45);
904 EXPECT_ROW1_EQ(1, 1, 0, 0, A);
905 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
906 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
907 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
909 // Verify that skewX() post-multiplies the existing matrix.
910 // Row 1, column 2, would incorrectly have value "7" if the matrix is pre-multiplied instead of post-multiplied.
911 A.MakeIdentity();
912 A.Scale3d(6, 7, 8);
913 A.SkewX(45);
914 EXPECT_ROW1_EQ(6, 6, 0, 0, A);
915 EXPECT_ROW2_EQ(0, 7, 0, 0, A);
916 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
917 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
920 TEST(MathUtilGfxTransformTest, verifySkewY)
922 gfx::Transform A;
923 A.SkewY(45);
924 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
925 EXPECT_ROW2_EQ(1, 1, 0, 0, A);
926 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
927 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
929 // Verify that skewY() post-multiplies the existing matrix.
930 // Row 2, column 1, would incorrectly have value "6" if the matrix is pre-multiplied instead of post-multiplied.
931 A.MakeIdentity();
932 A.Scale3d(6, 7, 8);
933 A.SkewY(45);
934 EXPECT_ROW1_EQ(6, 0, 0, 0, A);
935 EXPECT_ROW2_EQ(7, 7, 0, 0, A);
936 EXPECT_ROW3_EQ(0, 0, 8, 0, A);
937 EXPECT_ROW4_EQ(0, 0, 0, 1, A);
940 TEST(MathUtilGfxTransformTest, verifyPerspectiveDepth)
942 gfx::Transform A;
943 A.ApplyPerspectiveDepth(1);
944 EXPECT_ROW1_EQ(1, 0, 0, 0, A);
945 EXPECT_ROW2_EQ(0, 1, 0, 0, A);
946 EXPECT_ROW3_EQ(0, 0, 1, 0, A);
947 EXPECT_ROW4_EQ(0, 0, -1, 1, A);
949 // Verify that PerspectiveDepth() post-multiplies the existing matrix.
950 A.MakeIdentity();
951 A.Translate3d(2, 3, 4);
952 A.ApplyPerspectiveDepth(1);
953 EXPECT_ROW1_EQ(1, 0, -2, 2, A);
954 EXPECT_ROW2_EQ(0, 1, -3, 3, A);
955 EXPECT_ROW3_EQ(0, 0, -3, 4, A);
956 EXPECT_ROW4_EQ(0, 0, -1, 1, A);
959 TEST(MathUtilGfxTransformTest, verifyHasPerspective)
961 gfx::Transform A;
962 A.ApplyPerspectiveDepth(1);
963 EXPECT_TRUE(A.HasPerspective());
965 A.MakeIdentity();
966 A.ApplyPerspectiveDepth(0);
967 EXPECT_FALSE(A.HasPerspective());
969 A.MakeIdentity();
970 A.matrix().setDouble(3, 0, -1);
971 EXPECT_TRUE(A.HasPerspective());
973 A.MakeIdentity();
974 A.matrix().setDouble(3, 1, -1);
975 EXPECT_TRUE(A.HasPerspective());
977 A.MakeIdentity();
978 A.matrix().setDouble(3, 2, -0.3);
979 EXPECT_TRUE(A.HasPerspective());
981 A.MakeIdentity();
982 A.matrix().setDouble(3, 3, 0.5);
983 EXPECT_TRUE(A.HasPerspective());
985 A.MakeIdentity();
986 A.matrix().setDouble(3, 3, 0);
987 EXPECT_TRUE(A.HasPerspective());
990 TEST(MathUtilGfxTransformTest, verifyIsInvertible)
992 gfx::Transform A;
994 // Translations, rotations, scales, skews and arbitrary combinations of them are invertible.
995 A.MakeIdentity();
996 EXPECT_TRUE(A.IsInvertible());
998 A.MakeIdentity();
999 A.Translate3d(2, 3, 4);
1000 EXPECT_TRUE(A.IsInvertible());
1002 A.MakeIdentity();
1003 A.Scale3d(6, 7, 8);
1004 EXPECT_TRUE(A.IsInvertible());
1006 A.MakeIdentity();
1007 MathUtil::rotateEulerAngles(&A, 10, 20, 30);
1008 EXPECT_TRUE(A.IsInvertible());
1010 A.MakeIdentity();
1011 A.SkewX(45);
1012 EXPECT_TRUE(A.IsInvertible());
1014 // A perspective matrix (projection plane at z=0) is invertible. The intuitive
1015 // explanation is that perspective is eqivalent to a skew of the w-axis; skews are
1016 // invertible.
1017 A.MakeIdentity();
1018 A.ApplyPerspectiveDepth(1);
1019 EXPECT_TRUE(A.IsInvertible());
1021 // A "pure" perspective matrix derived by similar triangles, with m44() set to zero
1022 // (i.e. camera positioned at the origin), is not invertible.
1023 A.MakeIdentity();
1024 A.ApplyPerspectiveDepth(1);
1025 A.matrix().setDouble(3, 3, 0);
1026 EXPECT_FALSE(A.IsInvertible());
1028 // Adding more to a non-invertible matrix will not make it invertible in the general case.
1029 A.MakeIdentity();
1030 A.ApplyPerspectiveDepth(1);
1031 A.matrix().setDouble(3, 3, 0);
1032 A.Scale3d(6, 7, 8);
1033 MathUtil::rotateEulerAngles(&A, 10, 20, 30);
1034 A.Translate3d(6, 7, 8);
1035 EXPECT_FALSE(A.IsInvertible());
1037 // A degenerate matrix of all zeros is not invertible.
1038 A.MakeIdentity();
1039 A.matrix().setDouble(0, 0, 0);
1040 A.matrix().setDouble(1, 1, 0);
1041 A.matrix().setDouble(2, 2, 0);
1042 A.matrix().setDouble(3, 3, 0);
1043 EXPECT_FALSE(A.IsInvertible());
1046 TEST(MathUtilGfxTransformTest, verifyIsIdentity)
1048 gfx::Transform A;
1050 initializeTestMatrix(&A);
1051 EXPECT_FALSE(A.IsIdentity());
1053 A.MakeIdentity();
1054 EXPECT_TRUE(A.IsIdentity());
1056 // Modifying any one individual element should cause the matrix to no longer be identity.
1057 A.MakeIdentity();
1058 A.matrix().setDouble(0, 0, 2);
1059 EXPECT_FALSE(A.IsIdentity());
1061 A.MakeIdentity();
1062 A.matrix().setDouble(1, 0, 2);
1063 EXPECT_FALSE(A.IsIdentity());
1065 A.MakeIdentity();
1066 A.matrix().setDouble(2, 0, 2);
1067 EXPECT_FALSE(A.IsIdentity());
1069 A.MakeIdentity();
1070 A.matrix().setDouble(3, 0, 2);
1071 EXPECT_FALSE(A.IsIdentity());
1073 A.MakeIdentity();
1074 A.matrix().setDouble(0, 1, 2);
1075 EXPECT_FALSE(A.IsIdentity());
1077 A.MakeIdentity();
1078 A.matrix().setDouble(1, 1, 2);
1079 EXPECT_FALSE(A.IsIdentity());
1081 A.MakeIdentity();
1082 A.matrix().setDouble(2, 1, 2);
1083 EXPECT_FALSE(A.IsIdentity());
1085 A.MakeIdentity();
1086 A.matrix().setDouble(3, 1, 2);
1087 EXPECT_FALSE(A.IsIdentity());
1089 A.MakeIdentity();
1090 A.matrix().setDouble(0, 2, 2);
1091 EXPECT_FALSE(A.IsIdentity());
1093 A.MakeIdentity();
1094 A.matrix().setDouble(1, 2, 2);
1095 EXPECT_FALSE(A.IsIdentity());
1097 A.MakeIdentity();
1098 A.matrix().setDouble(2, 2, 2);
1099 EXPECT_FALSE(A.IsIdentity());
1101 A.MakeIdentity();
1102 A.matrix().setDouble(3, 2, 2);
1103 EXPECT_FALSE(A.IsIdentity());
1105 A.MakeIdentity();
1106 A.matrix().setDouble(0, 3, 2);
1107 EXPECT_FALSE(A.IsIdentity());
1109 A.MakeIdentity();
1110 A.matrix().setDouble(1, 3, 2);
1111 EXPECT_FALSE(A.IsIdentity());
1113 A.MakeIdentity();
1114 A.matrix().setDouble(2, 3, 2);
1115 EXPECT_FALSE(A.IsIdentity());
1117 A.MakeIdentity();
1118 A.matrix().setDouble(3, 3, 2);
1119 EXPECT_FALSE(A.IsIdentity());
1122 TEST(MathUtilGfxTransformTest, verifyIsIdentityOrTranslation)
1124 gfx::Transform A;
1126 initializeTestMatrix(&A);
1127 EXPECT_FALSE(A.IsIdentityOrTranslation());
1129 A.MakeIdentity();
1130 EXPECT_TRUE(A.IsIdentityOrTranslation());
1132 // Modifying any non-translation components should cause IsIdentityOrTranslation() to
1133 // return false. NOTE: (0, 3), (1, 3), and (2, 3) are the translation components, so
1134 // modifying them should still return true.
1135 A.MakeIdentity();
1136 A.matrix().setDouble(0, 0, 2);
1137 EXPECT_FALSE(A.IsIdentityOrTranslation());
1139 A.MakeIdentity();
1140 A.matrix().setDouble(1, 0, 2);
1141 EXPECT_FALSE(A.IsIdentityOrTranslation());
1143 A.MakeIdentity();
1144 A.matrix().setDouble(2, 0, 2);
1145 EXPECT_FALSE(A.IsIdentityOrTranslation());
1147 A.MakeIdentity();
1148 A.matrix().setDouble(3, 0, 2);
1149 EXPECT_FALSE(A.IsIdentityOrTranslation());
1151 A.MakeIdentity();
1152 A.matrix().setDouble(0, 1, 2);
1153 EXPECT_FALSE(A.IsIdentityOrTranslation());
1155 A.MakeIdentity();
1156 A.matrix().setDouble(1, 1, 2);
1157 EXPECT_FALSE(A.IsIdentityOrTranslation());
1159 A.MakeIdentity();
1160 A.matrix().setDouble(2, 1, 2);
1161 EXPECT_FALSE(A.IsIdentityOrTranslation());
1163 A.MakeIdentity();
1164 A.matrix().setDouble(3, 1, 2);
1165 EXPECT_FALSE(A.IsIdentityOrTranslation());
1167 A.MakeIdentity();
1168 A.matrix().setDouble(0, 2, 2);
1169 EXPECT_FALSE(A.IsIdentityOrTranslation());
1171 A.MakeIdentity();
1172 A.matrix().setDouble(1, 2, 2);
1173 EXPECT_FALSE(A.IsIdentityOrTranslation());
1175 A.MakeIdentity();
1176 A.matrix().setDouble(2, 2, 2);
1177 EXPECT_FALSE(A.IsIdentityOrTranslation());
1179 A.MakeIdentity();
1180 A.matrix().setDouble(3, 2, 2);
1181 EXPECT_FALSE(A.IsIdentityOrTranslation());
1183 // Note carefully - expecting true here.
1184 A.MakeIdentity();
1185 A.matrix().setDouble(0, 3, 2);
1186 EXPECT_TRUE(A.IsIdentityOrTranslation());
1188 // Note carefully - expecting true here.
1189 A.MakeIdentity();
1190 A.matrix().setDouble(1, 3, 2);
1191 EXPECT_TRUE(A.IsIdentityOrTranslation());
1193 // Note carefully - expecting true here.
1194 A.MakeIdentity();
1195 A.matrix().setDouble(2, 3, 2);
1196 EXPECT_TRUE(A.IsIdentityOrTranslation());
1198 A.MakeIdentity();
1199 A.matrix().setDouble(3, 3, 2);
1200 EXPECT_FALSE(A.IsIdentityOrTranslation());
1203 TEST(MathUtilGfxTransformTest, verifyIsScaleOrTranslation)
1205 gfx::Transform A;
1207 initializeTestMatrix(&A);
1208 EXPECT_FALSE(A.IsScaleOrTranslation());
1210 A.MakeIdentity();
1211 EXPECT_TRUE(A.IsScaleOrTranslation());
1213 // Modifying any non-scale or non-translation components should cause
1214 // IsScaleOrTranslation() to return false. (0, 0), (1, 1), (2, 2), (0, 3),
1215 // (1, 3), and (2, 3) are the scale and translation components, so
1216 // modifying them should still return true.
1218 // Note carefully - expecting true here.
1219 A.MakeIdentity();
1220 A.matrix().setDouble(0, 0, 2);
1221 EXPECT_TRUE(A.IsScaleOrTranslation());
1223 A.MakeIdentity();
1224 A.matrix().setDouble(1, 0, 2);
1225 EXPECT_FALSE(A.IsScaleOrTranslation());
1227 A.MakeIdentity();
1228 A.matrix().setDouble(2, 0, 2);
1229 EXPECT_FALSE(A.IsScaleOrTranslation());
1231 A.MakeIdentity();
1232 A.matrix().setDouble(3, 0, 2);
1233 EXPECT_FALSE(A.IsScaleOrTranslation());
1235 A.MakeIdentity();
1236 A.matrix().setDouble(0, 1, 2);
1237 EXPECT_FALSE(A.IsScaleOrTranslation());
1239 // Note carefully - expecting true here.
1240 A.MakeIdentity();
1241 A.matrix().setDouble(1, 1, 2);
1242 EXPECT_TRUE(A.IsScaleOrTranslation());
1244 A.MakeIdentity();
1245 A.matrix().setDouble(2, 1, 2);
1246 EXPECT_FALSE(A.IsScaleOrTranslation());
1248 A.MakeIdentity();
1249 A.matrix().setDouble(3, 1, 2);
1250 EXPECT_FALSE(A.IsScaleOrTranslation());
1252 A.MakeIdentity();
1253 A.matrix().setDouble(0, 2, 2);
1254 EXPECT_FALSE(A.IsScaleOrTranslation());
1256 A.MakeIdentity();
1257 A.matrix().setDouble(1, 2, 2);
1258 EXPECT_FALSE(A.IsScaleOrTranslation());
1260 // Note carefully - expecting true here.
1261 A.MakeIdentity();
1262 A.matrix().setDouble(2, 2, 2);
1263 EXPECT_TRUE(A.IsScaleOrTranslation());
1265 A.MakeIdentity();
1266 A.matrix().setDouble(3, 2, 2);
1267 EXPECT_FALSE(A.IsScaleOrTranslation());
1269 // Note carefully - expecting true here.
1270 A.MakeIdentity();
1271 A.matrix().setDouble(0, 3, 2);
1272 EXPECT_TRUE(A.IsScaleOrTranslation());
1274 // Note carefully - expecting true here.
1275 A.MakeIdentity();
1276 A.matrix().setDouble(1, 3, 2);
1277 EXPECT_TRUE(A.IsScaleOrTranslation());
1279 // Note carefully - expecting true here.
1280 A.MakeIdentity();
1281 A.matrix().setDouble(2, 3, 2);
1282 EXPECT_TRUE(A.IsScaleOrTranslation());
1284 A.MakeIdentity();
1285 A.matrix().setDouble(3, 3, 2);
1286 EXPECT_FALSE(A.IsScaleOrTranslation());
1289 } // namespace
1290 } // namespace cc