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.
7 #include "CCMathUtil.h"
9 #include "CCGeometryTestUtils.h"
10 #include "FloatRect.h"
11 #include <gmock/gmock.h>
12 #include <gtest/gtest.h>
13 #include <public/WebTransformationMatrix.h>
15 using namespace WebCore
;
16 using WebKit::WebTransformationMatrix
;
20 TEST(CCMathUtilTest
, verifyBackfaceVisibilityBasicCases
)
22 WebTransformationMatrix transform
;
24 transform
.makeIdentity();
25 EXPECT_FALSE(transform
.isBackFaceVisible());
27 transform
.makeIdentity();
28 transform
.rotate3d(0, 80, 0);
29 EXPECT_FALSE(transform
.isBackFaceVisible());
31 transform
.makeIdentity();
32 transform
.rotate3d(0, 100, 0);
33 EXPECT_TRUE(transform
.isBackFaceVisible());
35 // Edge case, 90 degree rotation should return false.
36 transform
.makeIdentity();
37 transform
.rotate3d(0, 90, 0);
38 EXPECT_FALSE(transform
.isBackFaceVisible());
41 TEST(CCMathUtilTest
, verifyBackfaceVisibilityForPerspective
)
43 WebTransformationMatrix layerSpaceToProjectionPlane
;
45 // This tests if isBackFaceVisible works properly under perspective transforms.
46 // Specifically, layers that may have their back face visible in orthographic
47 // projection, may not actually have back face visible under perspective projection.
49 // Case 1: Layer is rotated by slightly more than 90 degrees, at the center of the
50 // prespective projection. In this case, the layer's back-side is visible to
52 layerSpaceToProjectionPlane
.makeIdentity();
53 layerSpaceToProjectionPlane
.applyPerspective(1);
54 layerSpaceToProjectionPlane
.translate3d(0, 0, 0);
55 layerSpaceToProjectionPlane
.rotate3d(0, 100, 0);
56 EXPECT_TRUE(layerSpaceToProjectionPlane
.isBackFaceVisible());
58 // Case 2: Layer is rotated by slightly more than 90 degrees, but shifted off to the
59 // side of the camera. Because of the wide field-of-view, the layer's front
60 // side is still visible.
62 // |<-- front side of layer is visible to perspective camera
67 // |\ /<-- camera field of view
69 // back side of layer -->| \ /
70 // \./ <-- camera origin
72 layerSpaceToProjectionPlane
.makeIdentity();
73 layerSpaceToProjectionPlane
.applyPerspective(1);
74 layerSpaceToProjectionPlane
.translate3d(-10, 0, 0);
75 layerSpaceToProjectionPlane
.rotate3d(0, 100, 0);
76 EXPECT_FALSE(layerSpaceToProjectionPlane
.isBackFaceVisible());
78 // Case 3: Additionally rotating the layer by 180 degrees should of course show the
79 // opposite result of case 2.
80 layerSpaceToProjectionPlane
.rotate3d(0, 180, 0);
81 EXPECT_TRUE(layerSpaceToProjectionPlane
.isBackFaceVisible());
84 TEST(CCMathUtilTest
, verifyProjectionOfPerpendicularPlane
)
86 // In this case, the m33() element of the transform becomes zero, which could cause a
87 // divide-by-zero when projecting points/quads.
89 WebTransformationMatrix transform
;
90 transform
.makeIdentity();
93 FloatRect rect
= FloatRect(0, 0, 1, 1);
94 FloatRect projectedRect
= CCMathUtil::projectClippedRect(transform
, rect
);
96 EXPECT_EQ(0, projectedRect
.x());
97 EXPECT_EQ(0, projectedRect
.y());
98 EXPECT_TRUE(projectedRect
.isEmpty());
101 TEST(CCMathUtilTest
, verifyEnclosingClippedRectUsesCorrectInitialBounds
)
103 HomogeneousCoordinate
h1(-100, -100, 0, 1);
104 HomogeneousCoordinate
h2(-10, -10, 0, 1);
105 HomogeneousCoordinate
h3(10, 10, 0, -1);
106 HomogeneousCoordinate
h4(100, 100, 0, -1);
108 // The bounds of the enclosing clipped rect should be -100 to -10 for both x and y.
109 // However, if there is a bug where the initial xmin/xmax/ymin/ymax are initialized to
110 // numeric_limits<float>::min() (which is zero, not -flt_max) then the enclosing
111 // clipped rect will be computed incorrectly.
112 FloatRect result
= CCMathUtil::computeEnclosingClippedRect(h1
, h2
, h3
, h4
);
114 EXPECT_FLOAT_RECT_EQ(FloatRect(FloatPoint(-100, -100), FloatSize(90, 90)), result
);
117 TEST(CCMathUtilTest
, verifyEnclosingRectOfVerticesUsesCorrectInitialBounds
)
119 FloatPoint vertices
[3];
122 vertices
[0] = FloatPoint(-10, -100);
123 vertices
[1] = FloatPoint(-100, -10);
124 vertices
[2] = FloatPoint(-30, -30);
126 // The bounds of the enclosing rect should be -100 to -10 for both x and y. However,
127 // if there is a bug where the initial xmin/xmax/ymin/ymax are initialized to
128 // numeric_limits<float>::min() (which is zero, not -flt_max) then the enclosing
129 // clipped rect will be computed incorrectly.
130 FloatRect result
= CCMathUtil::computeEnclosingRectOfVertices(vertices
, numVertices
);
132 EXPECT_FLOAT_RECT_EQ(FloatRect(FloatPoint(-100, -100), FloatSize(90, 90)), result
);
135 TEST(CCMathUtilTest
, smallestAngleBetweenVectors
)
139 FloatSize
testVector(0.5, 0.5);
141 // Orthogonal vectors are at an angle of 90 degress.
142 EXPECT_EQ(90, CCMathUtil::smallestAngleBetweenVectors(x
, y
));
144 // A vector makes a zero angle with itself.
145 EXPECT_EQ(0, CCMathUtil::smallestAngleBetweenVectors(x
, x
));
146 EXPECT_EQ(0, CCMathUtil::smallestAngleBetweenVectors(y
, y
));
147 EXPECT_EQ(0, CCMathUtil::smallestAngleBetweenVectors(testVector
, testVector
));
149 // Parallel but reversed vectors are at 180 degrees.
150 EXPECT_FLOAT_EQ(180, CCMathUtil::smallestAngleBetweenVectors(x
, -x
));
151 EXPECT_FLOAT_EQ(180, CCMathUtil::smallestAngleBetweenVectors(y
, -y
));
152 EXPECT_FLOAT_EQ(180, CCMathUtil::smallestAngleBetweenVectors(testVector
, -testVector
));
154 // The test vector is at a known angle.
155 EXPECT_FLOAT_EQ(45, floor(CCMathUtil::smallestAngleBetweenVectors(testVector
, x
)));
156 EXPECT_FLOAT_EQ(45, floor(CCMathUtil::smallestAngleBetweenVectors(testVector
, y
)));
159 TEST(CCMathUtilTest
, vectorProjection
)
163 FloatSize
testVector(0.3f
, 0.7f
);
165 // Orthogonal vectors project to a zero vector.
166 EXPECT_EQ(FloatSize(0, 0), CCMathUtil::projectVector(x
, y
));
167 EXPECT_EQ(FloatSize(0, 0), CCMathUtil::projectVector(y
, x
));
169 // Projecting a vector onto the orthonormal basis gives the corresponding component of the
171 EXPECT_EQ(FloatSize(testVector
.width(), 0), CCMathUtil::projectVector(testVector
, x
));
172 EXPECT_EQ(FloatSize(0, testVector
.height()), CCMathUtil::projectVector(testVector
, y
));
174 // Finally check than an arbitrary vector projected to another one gives a vector parallel to
175 // the second vector.
176 FloatSize
targetVector(0.5, 0.2f
);
177 FloatSize projectedVector
= CCMathUtil::projectVector(testVector
, targetVector
);
178 EXPECT_EQ(projectedVector
.width() / targetVector
.width(),
179 projectedVector
.height() / targetVector
.height());