OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #define _USE_MATH_DEFINES | |
6 #include <math.h> | |
7 | |
8 #include "testing/gtest/include/gtest/gtest.h" | |
9 #include "third_party/WebKit/Source/Platform/chromium/public/WebTransformationMa
trix.h" | |
10 | |
11 #define EXPECT_ROW1_EQ(a, b, c, d, matrix) \ | |
12 EXPECT_FLOAT_EQ((a), (matrix).m11()); \ | |
13 EXPECT_FLOAT_EQ((b), (matrix).m21()); \ | |
14 EXPECT_FLOAT_EQ((c), (matrix).m31()); \ | |
15 EXPECT_FLOAT_EQ((d), (matrix).m41()); | |
16 | |
17 #define EXPECT_ROW2_EQ(a, b, c, d, matrix) \ | |
18 EXPECT_FLOAT_EQ((a), (matrix).m12()); \ | |
19 EXPECT_FLOAT_EQ((b), (matrix).m22()); \ | |
20 EXPECT_FLOAT_EQ((c), (matrix).m32()); \ | |
21 EXPECT_FLOAT_EQ((d), (matrix).m42()); | |
22 | |
23 #define EXPECT_ROW3_EQ(a, b, c, d, matrix) \ | |
24 EXPECT_FLOAT_EQ((a), (matrix).m13()); \ | |
25 EXPECT_FLOAT_EQ((b), (matrix).m23()); \ | |
26 EXPECT_FLOAT_EQ((c), (matrix).m33()); \ | |
27 EXPECT_FLOAT_EQ((d), (matrix).m43()); | |
28 | |
29 #define EXPECT_ROW4_EQ(a, b, c, d, matrix) \ | |
30 EXPECT_FLOAT_EQ((a), (matrix).m14()); \ | |
31 EXPECT_FLOAT_EQ((b), (matrix).m24()); \ | |
32 EXPECT_FLOAT_EQ((c), (matrix).m34()); \ | |
33 EXPECT_FLOAT_EQ((d), (matrix).m44()); | |
34 | |
35 #define EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(expected, actual) \ | |
36 EXPECT_FLOAT_EQ((expected).m11(), (actual).m11()); \ | |
37 EXPECT_FLOAT_EQ((expected).m12(), (actual).m12()); \ | |
38 EXPECT_FLOAT_EQ((expected).m13(), (actual).m13()); \ | |
39 EXPECT_FLOAT_EQ((expected).m14(), (actual).m14()); \ | |
40 EXPECT_FLOAT_EQ((expected).m21(), (actual).m21()); \ | |
41 EXPECT_FLOAT_EQ((expected).m22(), (actual).m22()); \ | |
42 EXPECT_FLOAT_EQ((expected).m23(), (actual).m23()); \ | |
43 EXPECT_FLOAT_EQ((expected).m24(), (actual).m24()); \ | |
44 EXPECT_FLOAT_EQ((expected).m31(), (actual).m31()); \ | |
45 EXPECT_FLOAT_EQ((expected).m32(), (actual).m32()); \ | |
46 EXPECT_FLOAT_EQ((expected).m33(), (actual).m33()); \ | |
47 EXPECT_FLOAT_EQ((expected).m34(), (actual).m34()); \ | |
48 EXPECT_FLOAT_EQ((expected).m41(), (actual).m41()); \ | |
49 EXPECT_FLOAT_EQ((expected).m42(), (actual).m42()); \ | |
50 EXPECT_FLOAT_EQ((expected).m43(), (actual).m43()); \ | |
51 EXPECT_FLOAT_EQ((expected).m44(), (actual).m44()); | |
52 | |
53 // Checking float values for equality close to zero is not robust using EXPECT_F
LOAT_EQ | |
54 // (see gtest documentation). So, to verify rotation matrices, we must use a loo
ser | |
55 // absolute error threshold in some places. | |
56 #define EXPECT_ROW1_NEAR(a, b, c, d, matrix, error_threshold) \ | |
57 EXPECT_NEAR((a), (matrix).m11(), (error_threshold)); \ | |
58 EXPECT_NEAR((b), (matrix).m21(), (error_threshold)); \ | |
59 EXPECT_NEAR((c), (matrix).m31(), (error_threshold)); \ | |
60 EXPECT_NEAR((d), (matrix).m41(), (error_threshold)); | |
61 | |
62 #define EXPECT_ROW2_NEAR(a, b, c, d, matrix, error_threshold) \ | |
63 EXPECT_NEAR((a), (matrix).m12(), (error_threshold)); \ | |
64 EXPECT_NEAR((b), (matrix).m22(), (error_threshold)); \ | |
65 EXPECT_NEAR((c), (matrix).m32(), (error_threshold)); \ | |
66 EXPECT_NEAR((d), (matrix).m42(), (error_threshold)); | |
67 | |
68 #define EXPECT_ROW3_NEAR(a, b, c, d, matrix, error_threshold) \ | |
69 EXPECT_NEAR((a), (matrix).m13(), (error_threshold)); \ | |
70 EXPECT_NEAR((b), (matrix).m23(), (error_threshold)); \ | |
71 EXPECT_NEAR((c), (matrix).m33(), (error_threshold)); \ | |
72 EXPECT_NEAR((d), (matrix).m43(), (error_threshold)); | |
73 | |
74 #define ERROR_THRESHOLD 1e-14 | |
75 #define LOOSE_ERROR_THRESHOLD 1e-7 | |
76 | |
77 using namespace WebKit; | |
78 | |
79 namespace { | |
80 | |
81 static void initializeTestMatrix(WebTransformationMatrix& transform) { | |
82 transform.setM11(10); | |
83 transform.setM12(11); | |
84 transform.setM13(12); | |
85 transform.setM14(13); | |
86 transform.setM21(14); | |
87 transform.setM22(15); | |
88 transform.setM23(16); | |
89 transform.setM24(17); | |
90 transform.setM31(18); | |
91 transform.setM32(19); | |
92 transform.setM33(20); | |
93 transform.setM34(21); | |
94 transform.setM41(22); | |
95 transform.setM42(23); | |
96 transform.setM43(24); | |
97 transform.setM44(25); | |
98 | |
99 // Sanity check | |
100 EXPECT_ROW1_EQ(10, 14, 18, 22, transform); | |
101 EXPECT_ROW2_EQ(11, 15, 19, 23, transform); | |
102 EXPECT_ROW3_EQ(12, 16, 20, 24, transform); | |
103 EXPECT_ROW4_EQ(13, 17, 21, 25, transform); | |
104 } | |
105 | |
106 static void initializeTestMatrix2(WebTransformationMatrix& transform) { | |
107 transform.setM11(30); | |
108 transform.setM12(31); | |
109 transform.setM13(32); | |
110 transform.setM14(33); | |
111 transform.setM21(34); | |
112 transform.setM22(35); | |
113 transform.setM23(36); | |
114 transform.setM24(37); | |
115 transform.setM31(38); | |
116 transform.setM32(39); | |
117 transform.setM33(40); | |
118 transform.setM34(41); | |
119 transform.setM41(42); | |
120 transform.setM42(43); | |
121 transform.setM43(44); | |
122 transform.setM44(45); | |
123 | |
124 // Sanity check | |
125 EXPECT_ROW1_EQ(30, 34, 38, 42, transform); | |
126 EXPECT_ROW2_EQ(31, 35, 39, 43, transform); | |
127 EXPECT_ROW3_EQ(32, 36, 40, 44, transform); | |
128 EXPECT_ROW4_EQ(33, 37, 41, 45, transform); | |
129 } | |
130 | |
131 TEST(WebTransformationMatrixTest, DefaultConstructorCreatesIdentityMatrix) { | |
132 WebTransformationMatrix A; | |
133 EXPECT_ROW1_EQ(1, 0, 0, 0, A); | |
134 EXPECT_ROW2_EQ(0, 1, 0, 0, A); | |
135 EXPECT_ROW3_EQ(0, 0, 1, 0, A); | |
136 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
137 EXPECT_TRUE(A.isIdentity()); | |
138 } | |
139 | |
140 TEST(WebTransformationMatrixTest, ConstructorFor2dElements) { | |
141 WebTransformationMatrix A(1, 2, 3, 4, 5, 6); | |
142 EXPECT_ROW1_EQ(1, 3, 0, 5, A); | |
143 EXPECT_ROW2_EQ(2, 4, 0, 6, A); | |
144 EXPECT_ROW3_EQ(0, 0, 1, 0, A); | |
145 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
146 } | |
147 | |
148 TEST(WebTransformationMatrixTest, ConstructorForAllElements) { | |
149 WebTransformationMatrix A( | |
150 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); | |
151 EXPECT_ROW1_EQ(1, 5, 9, 13, A); | |
152 EXPECT_ROW2_EQ(2, 6, 10, 14, A); | |
153 EXPECT_ROW3_EQ(3, 7, 11, 15, A); | |
154 EXPECT_ROW4_EQ(4, 8, 12, 16, A); | |
155 } | |
156 | |
157 TEST(WebTransformationMatrixTest, CopyConstructor) { | |
158 WebTransformationMatrix A; | |
159 initializeTestMatrix(A); | |
160 | |
161 // Copy constructor should produce exact same elements as matrix A. | |
162 WebTransformationMatrix B(A); | |
163 EXPECT_ROW1_EQ(10, 14, 18, 22, B); | |
164 EXPECT_ROW2_EQ(11, 15, 19, 23, B); | |
165 EXPECT_ROW3_EQ(12, 16, 20, 24, B); | |
166 EXPECT_ROW4_EQ(13, 17, 21, 25, B); | |
167 } | |
168 | |
169 TEST(WebTransformationMatrixTest, MatrixInversion) { | |
170 // Invert a translation | |
171 WebTransformationMatrix translation; | |
172 translation.translate3d(2, 3, 4); | |
173 EXPECT_TRUE(translation.isInvertible()); | |
174 | |
175 WebTransformationMatrix inverse_translation = translation.inverse(); | |
176 EXPECT_ROW1_EQ(1, 0, 0, -2, inverse_translation); | |
177 EXPECT_ROW2_EQ(0, 1, 0, -3, inverse_translation); | |
178 EXPECT_ROW3_EQ(0, 0, 1, -4, inverse_translation); | |
179 EXPECT_ROW4_EQ(0, 0, 0, 1, inverse_translation); | |
180 | |
181 // Note that inversion should not have changed the original matrix. | |
182 EXPECT_ROW1_EQ(1, 0, 0, 2, translation); | |
183 EXPECT_ROW2_EQ(0, 1, 0, 3, translation); | |
184 EXPECT_ROW3_EQ(0, 0, 1, 4, translation); | |
185 EXPECT_ROW4_EQ(0, 0, 0, 1, translation); | |
186 | |
187 // Invert a non-uniform scale | |
188 WebTransformationMatrix scale; | |
189 scale.scale3d(4, 10, 100); | |
190 EXPECT_TRUE(scale.isInvertible()); | |
191 | |
192 WebTransformationMatrix inverse_scale = scale.inverse(); | |
193 EXPECT_ROW1_EQ(0.25, 0, 0, 0, inverse_scale); | |
194 EXPECT_ROW2_EQ(0, .1f, 0, 0, inverse_scale); | |
195 EXPECT_ROW3_EQ(0, 0, .01f, 0, inverse_scale); | |
196 EXPECT_ROW4_EQ(0, 0, 0, 1, inverse_scale); | |
197 | |
198 // Try to invert a matrix that is not invertible. | |
199 // The inverse() function should simply return an identity matrix. | |
200 WebTransformationMatrix not_invertible; | |
201 not_invertible.setM11(0); | |
202 not_invertible.setM22(0); | |
203 not_invertible.setM33(0); | |
204 not_invertible.setM44(0); | |
205 EXPECT_FALSE(not_invertible.isInvertible()); | |
206 | |
207 WebTransformationMatrix inverse_of_not_invertible; | |
208 initializeTestMatrix( | |
209 inverse_of_not_invertible); // initialize this to something non-identity,
to make sure that assignment below actually took place. | |
210 inverse_of_not_invertible = not_invertible.inverse(); | |
211 EXPECT_TRUE(inverse_of_not_invertible.isIdentity()); | |
212 } | |
213 | |
214 TEST(WebTransformationMatrixTest, To2DTransform) { | |
215 WebTransformationMatrix A; | |
216 initializeTestMatrix(A); | |
217 | |
218 WebTransformationMatrix B = A.to2dTransform(); | |
219 | |
220 EXPECT_ROW1_EQ(10, 14, 0, 22, B); | |
221 EXPECT_ROW2_EQ(11, 15, 0, 23, B); | |
222 EXPECT_ROW3_EQ(0, 0, 1, 0, B); | |
223 EXPECT_ROW4_EQ(13, 17, 0, 25, B); | |
224 | |
225 // Note that to2DTransform should not have changed the original matrix. | |
226 EXPECT_ROW1_EQ(10, 14, 18, 22, A); | |
227 EXPECT_ROW2_EQ(11, 15, 19, 23, A); | |
228 EXPECT_ROW3_EQ(12, 16, 20, 24, A); | |
229 EXPECT_ROW4_EQ(13, 17, 21, 25, A); | |
230 } | |
231 | |
232 TEST(WebTransformationMatrixTest, AssignmentOperator) { | |
233 WebTransformationMatrix A; | |
234 initializeTestMatrix(A); | |
235 WebTransformationMatrix B; | |
236 initializeTestMatrix2(B); | |
237 WebTransformationMatrix C; | |
238 initializeTestMatrix2(C); | |
239 C = B = A; | |
240 | |
241 // Both B and C should now have been re-assigned to the value of A. | |
242 EXPECT_ROW1_EQ(10, 14, 18, 22, B); | |
243 EXPECT_ROW2_EQ(11, 15, 19, 23, B); | |
244 EXPECT_ROW3_EQ(12, 16, 20, 24, B); | |
245 EXPECT_ROW4_EQ(13, 17, 21, 25, B); | |
246 | |
247 EXPECT_ROW1_EQ(10, 14, 18, 22, C); | |
248 EXPECT_ROW2_EQ(11, 15, 19, 23, C); | |
249 EXPECT_ROW3_EQ(12, 16, 20, 24, C); | |
250 EXPECT_ROW4_EQ(13, 17, 21, 25, C); | |
251 } | |
252 | |
253 TEST(WebTransformationMatrixTest, EqualsBooleanOperator) { | |
254 WebTransformationMatrix A; | |
255 initializeTestMatrix(A); | |
256 | |
257 WebTransformationMatrix B; | |
258 initializeTestMatrix(B); | |
259 EXPECT_TRUE(A == B); | |
260 | |
261 // Modifying multiple elements should cause equals operator to return false. | |
262 WebTransformationMatrix C; | |
263 initializeTestMatrix2(C); | |
264 EXPECT_FALSE(A == C); | |
265 | |
266 // Modifying any one individual element should cause equals operator to return
false. | |
267 WebTransformationMatrix D; | |
268 D = A; | |
269 D.setM11(0); | |
270 EXPECT_FALSE(A == D); | |
271 | |
272 D = A; | |
273 D.setM12(0); | |
274 EXPECT_FALSE(A == D); | |
275 | |
276 D = A; | |
277 D.setM13(0); | |
278 EXPECT_FALSE(A == D); | |
279 | |
280 D = A; | |
281 D.setM14(0); | |
282 EXPECT_FALSE(A == D); | |
283 | |
284 D = A; | |
285 D.setM21(0); | |
286 EXPECT_FALSE(A == D); | |
287 | |
288 D = A; | |
289 D.setM22(0); | |
290 EXPECT_FALSE(A == D); | |
291 | |
292 D = A; | |
293 D.setM23(0); | |
294 EXPECT_FALSE(A == D); | |
295 | |
296 D = A; | |
297 D.setM24(0); | |
298 EXPECT_FALSE(A == D); | |
299 | |
300 D = A; | |
301 D.setM31(0); | |
302 EXPECT_FALSE(A == D); | |
303 | |
304 D = A; | |
305 D.setM32(0); | |
306 EXPECT_FALSE(A == D); | |
307 | |
308 D = A; | |
309 D.setM33(0); | |
310 EXPECT_FALSE(A == D); | |
311 | |
312 D = A; | |
313 D.setM34(0); | |
314 EXPECT_FALSE(A == D); | |
315 | |
316 D = A; | |
317 D.setM41(0); | |
318 EXPECT_FALSE(A == D); | |
319 | |
320 D = A; | |
321 D.setM42(0); | |
322 EXPECT_FALSE(A == D); | |
323 | |
324 D = A; | |
325 D.setM43(0); | |
326 EXPECT_FALSE(A == D); | |
327 | |
328 D = A; | |
329 D.setM44(0); | |
330 EXPECT_FALSE(A == D); | |
331 } | |
332 | |
333 TEST(WebTransformationMatrixTest, MultiplyOperator) { | |
334 WebTransformationMatrix A; | |
335 initializeTestMatrix(A); | |
336 | |
337 WebTransformationMatrix B; | |
338 initializeTestMatrix2(B); | |
339 | |
340 WebTransformationMatrix C = A * B; | |
341 EXPECT_ROW1_EQ(2036, 2292, 2548, 2804, C); | |
342 EXPECT_ROW2_EQ(2162, 2434, 2706, 2978, C); | |
343 EXPECT_ROW3_EQ(2288, 2576, 2864, 3152, C); | |
344 EXPECT_ROW4_EQ(2414, 2718, 3022, 3326, C); | |
345 | |
346 // Just an additional sanity check; matrix multiplication is not commutative. | |
347 EXPECT_FALSE(A * B == B * A); | |
348 } | |
349 | |
350 TEST(WebTransformationMatrixTest, MatrixMultiplication) { | |
351 WebTransformationMatrix A; | |
352 initializeTestMatrix(A); | |
353 | |
354 WebTransformationMatrix B; | |
355 initializeTestMatrix2(B); | |
356 | |
357 A.multiply(B); | |
358 EXPECT_ROW1_EQ(2036, 2292, 2548, 2804, A); | |
359 EXPECT_ROW2_EQ(2162, 2434, 2706, 2978, A); | |
360 EXPECT_ROW3_EQ(2288, 2576, 2864, 3152, A); | |
361 EXPECT_ROW4_EQ(2414, 2718, 3022, 3326, A); | |
362 } | |
363 | |
364 TEST(WebTransformationMatrixTest, MakeIdentiy) { | |
365 WebTransformationMatrix A; | |
366 initializeTestMatrix(A); | |
367 A.makeIdentity(); | |
368 EXPECT_ROW1_EQ(1, 0, 0, 0, A); | |
369 EXPECT_ROW2_EQ(0, 1, 0, 0, A); | |
370 EXPECT_ROW3_EQ(0, 0, 1, 0, A); | |
371 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
372 EXPECT_TRUE(A.isIdentity()); | |
373 } | |
374 | |
375 TEST(WebTransformationMatrixTest, Translate) { | |
376 WebTransformationMatrix A; | |
377 A.translate(2, 3); | |
378 EXPECT_ROW1_EQ(1, 0, 0, 2, A); | |
379 EXPECT_ROW2_EQ(0, 1, 0, 3, A); | |
380 EXPECT_ROW3_EQ(0, 0, 1, 0, A); | |
381 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
382 | |
383 // Verify that translate() post-multiplies the existing matrix. | |
384 A.makeIdentity(); | |
385 A.scale(5); | |
386 A.translate(2, 3); | |
387 EXPECT_ROW1_EQ(5, 0, 0, 10, A); | |
388 EXPECT_ROW2_EQ(0, 5, 0, 15, A); | |
389 EXPECT_ROW3_EQ(0, 0, 1, 0, A); | |
390 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
391 } | |
392 | |
393 TEST(WebTransformationMatrixTest, Translate3d) { | |
394 WebTransformationMatrix A; | |
395 A.translate3d(2, 3, 4); | |
396 EXPECT_ROW1_EQ(1, 0, 0, 2, A); | |
397 EXPECT_ROW2_EQ(0, 1, 0, 3, A); | |
398 EXPECT_ROW3_EQ(0, 0, 1, 4, A); | |
399 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
400 | |
401 // Verify that translate3d() post-multiplies the existing matrix. | |
402 A.makeIdentity(); | |
403 A.scale3d(6, 7, 8); | |
404 A.translate3d(2, 3, 4); | |
405 EXPECT_ROW1_EQ(6, 0, 0, 12, A); | |
406 EXPECT_ROW2_EQ(0, 7, 0, 21, A); | |
407 EXPECT_ROW3_EQ(0, 0, 8, 32, A); | |
408 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
409 } | |
410 | |
411 TEST(WebTransformationMatrixTest, TranslateRight3d) { | |
412 WebTransformationMatrix A; | |
413 A.translateRight3d(2, 3, 4); | |
414 EXPECT_ROW1_EQ(1, 0, 0, 2, A); | |
415 EXPECT_ROW2_EQ(0, 1, 0, 3, A); | |
416 EXPECT_ROW3_EQ(0, 0, 1, 4, A); | |
417 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
418 | |
419 // Note carefully, all other operations do post-multiply, this one is unique. | |
420 // Verify that translateRight3d() PRE-multiplies the existing matrix. | |
421 A.makeIdentity(); | |
422 A.scale3d(6, 7, 8); | |
423 A.translateRight3d(2, 3, 4); | |
424 EXPECT_ROW1_EQ(6, 0, 0, 2, A); | |
425 EXPECT_ROW2_EQ(0, 7, 0, 3, A); | |
426 EXPECT_ROW3_EQ(0, 0, 8, 4, A); | |
427 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
428 } | |
429 | |
430 TEST(WebTransformationMatrixTest, Scale) { | |
431 WebTransformationMatrix A; | |
432 A.scale(5); | |
433 EXPECT_ROW1_EQ(5, 0, 0, 0, A); | |
434 EXPECT_ROW2_EQ(0, 5, 0, 0, A); | |
435 EXPECT_ROW3_EQ(0, 0, 1, 0, A); | |
436 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
437 | |
438 // Verify that scale() post-multiplies the existing matrix. | |
439 A.makeIdentity(); | |
440 A.translate3d(2, 3, 4); | |
441 A.scale(5); | |
442 EXPECT_ROW1_EQ(5, 0, 0, 2, A); | |
443 EXPECT_ROW2_EQ(0, 5, 0, 3, A); | |
444 EXPECT_ROW3_EQ(0, 0, 1, 4, A); | |
445 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
446 } | |
447 | |
448 TEST(WebTransformationMatrixTest, NonUniformScale) { | |
449 WebTransformationMatrix A; | |
450 A.scaleNonUniform(6, 7); | |
451 EXPECT_ROW1_EQ(6, 0, 0, 0, A); | |
452 EXPECT_ROW2_EQ(0, 7, 0, 0, A); | |
453 EXPECT_ROW3_EQ(0, 0, 1, 0, A); | |
454 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
455 | |
456 // Verify that scaleNonUniform() post-multiplies the existing matrix. | |
457 A.makeIdentity(); | |
458 A.translate3d(2, 3, 4); | |
459 A.scaleNonUniform(6, 7); | |
460 EXPECT_ROW1_EQ(6, 0, 0, 2, A); | |
461 EXPECT_ROW2_EQ(0, 7, 0, 3, A); | |
462 EXPECT_ROW3_EQ(0, 0, 1, 4, A); | |
463 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
464 } | |
465 | |
466 TEST(WebTransformationMatrixTest, Scale3d) { | |
467 WebTransformationMatrix A; | |
468 A.scale3d(6, 7, 8); | |
469 EXPECT_ROW1_EQ(6, 0, 0, 0, A); | |
470 EXPECT_ROW2_EQ(0, 7, 0, 0, A); | |
471 EXPECT_ROW3_EQ(0, 0, 8, 0, A); | |
472 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
473 | |
474 // Verify that scale3d() post-multiplies the existing matrix. | |
475 A.makeIdentity(); | |
476 A.translate3d(2, 3, 4); | |
477 A.scale3d(6, 7, 8); | |
478 EXPECT_ROW1_EQ(6, 0, 0, 2, A); | |
479 EXPECT_ROW2_EQ(0, 7, 0, 3, A); | |
480 EXPECT_ROW3_EQ(0, 0, 8, 4, A); | |
481 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
482 } | |
483 | |
484 TEST(WebTransformationMatrixTest, Rotate) { | |
485 WebTransformationMatrix A; | |
486 A.rotate(90); | |
487 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD); | |
488 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD); | |
489 EXPECT_ROW3_EQ(0, 0, 1, 0, A); | |
490 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
491 | |
492 // Verify that rotate() post-multiplies the existing matrix. | |
493 A.makeIdentity(); | |
494 A.scale3d(6, 7, 8); | |
495 A.rotate(90); | |
496 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD); | |
497 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD); | |
498 EXPECT_ROW3_EQ(0, 0, 8, 0, A); | |
499 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
500 } | |
501 | |
502 TEST(WebTransformationMatrixTest, Rotate3d) { | |
503 WebTransformationMatrix A; | |
504 | |
505 // Check rotation about z-axis | |
506 A.makeIdentity(); | |
507 A.rotate3d(0, 0, 90); | |
508 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD); | |
509 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD); | |
510 EXPECT_ROW3_EQ(0, 0, 1, 0, A); | |
511 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
512 | |
513 // Check rotation about x-axis | |
514 A.makeIdentity(); | |
515 A.rotate3d(90, 0, 0); | |
516 EXPECT_ROW1_EQ(1, 0, 0, 0, A); | |
517 EXPECT_ROW2_NEAR(0, 0, -1, 0, A, ERROR_THRESHOLD); | |
518 EXPECT_ROW3_NEAR(0, 1, 0, 0, A, ERROR_THRESHOLD); | |
519 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
520 | |
521 // Check rotation about y-axis. | |
522 // Note carefully, the expected pattern is inverted compared to rotating about
x axis or z axis. | |
523 A.makeIdentity(); | |
524 A.rotate3d(0, 90, 0); | |
525 EXPECT_ROW1_NEAR(0, 0, 1, 0, A, ERROR_THRESHOLD); | |
526 EXPECT_ROW2_EQ(0, 1, 0, 0, A); | |
527 EXPECT_ROW3_NEAR(-1, 0, 0, 0, A, ERROR_THRESHOLD); | |
528 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
529 | |
530 // Verify that rotate3d(rx, ry, rz) post-multiplies the existing matrix. | |
531 A.makeIdentity(); | |
532 A.scale3d(6, 7, 8); | |
533 A.rotate3d(0, 0, 90); | |
534 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD); | |
535 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD); | |
536 EXPECT_ROW3_EQ(0, 0, 8, 0, A); | |
537 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
538 } | |
539 | |
540 TEST(WebTransformationMatrixTest, Rotate3dOrderOfCompositeRotations) { | |
541 // Rotate3d(degreesX, degreesY, degreesZ) is actually composite transform cons
iting of | |
542 // three primitive rotations. This test verifies that the ordering of those th
ree | |
543 // transforms is the intended ordering. | |
544 // | |
545 // The correct ordering for this test case should be: | |
546 // 1. rotate by 30 degrees about z-axis | |
547 // 2. rotate by 20 degrees about y-axis | |
548 // 3. rotate by 10 degrees about x-axis | |
549 // | |
550 // Note: there are 6 possible orderings of 3 transforms. For the specific tran
sforms | |
551 // used in this test, all 6 combinations produce a unique matrix that is diffe
rent | |
552 // from the other orderings. That way, this test verifies the exact ordering. | |
553 | |
554 WebTransformationMatrix A; | |
555 A.makeIdentity(); | |
556 A.rotate3d(10, 20, 30); | |
557 | |
558 EXPECT_ROW1_NEAR(0.8137976813493738026394908, | |
559 -0.4409696105298823720630708, | |
560 0.3785223063697923939763257, | |
561 0, | |
562 A, | |
563 ERROR_THRESHOLD); | |
564 EXPECT_ROW2_NEAR(0.4698463103929541584413698, | |
565 0.8825641192593856043657752, | |
566 0.0180283112362972230968694, | |
567 0, | |
568 A, | |
569 ERROR_THRESHOLD); | |
570 EXPECT_ROW3_NEAR(-0.3420201433256686573969318, | |
571 0.1631759111665348205288950, | |
572 0.9254165783983233639631294, | |
573 0, | |
574 A, | |
575 ERROR_THRESHOLD); | |
576 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
577 } | |
578 | |
579 TEST(WebTransformationMatrixTest, RotateAxisAngle3d) { | |
580 WebTransformationMatrix A; | |
581 | |
582 // Check rotation about z-axis | |
583 A.makeIdentity(); | |
584 A.rotate3d(0, 0, 1, 90); | |
585 EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD); | |
586 EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD); | |
587 EXPECT_ROW3_EQ(0, 0, 1, 0, A); | |
588 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
589 | |
590 // Check rotation about x-axis | |
591 A.makeIdentity(); | |
592 A.rotate3d(1, 0, 0, 90); | |
593 EXPECT_ROW1_EQ(1, 0, 0, 0, A); | |
594 EXPECT_ROW2_NEAR(0, 0, -1, 0, A, ERROR_THRESHOLD); | |
595 EXPECT_ROW3_NEAR(0, 1, 0, 0, A, ERROR_THRESHOLD); | |
596 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
597 | |
598 // Check rotation about y-axis. | |
599 // Note carefully, the expected pattern is inverted compared to rotating about
x axis or z axis. | |
600 A.makeIdentity(); | |
601 A.rotate3d(0, 1, 0, 90); | |
602 EXPECT_ROW1_NEAR(0, 0, 1, 0, A, ERROR_THRESHOLD); | |
603 EXPECT_ROW2_EQ(0, 1, 0, 0, A); | |
604 EXPECT_ROW3_NEAR(-1, 0, 0, 0, A, ERROR_THRESHOLD); | |
605 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
606 | |
607 // Verify that rotate3d(axis, angle) post-multiplies the existing matrix. | |
608 A.makeIdentity(); | |
609 A.scale3d(6, 7, 8); | |
610 A.rotate3d(0, 0, 1, 90); | |
611 EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD); | |
612 EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD); | |
613 EXPECT_ROW3_EQ(0, 0, 8, 0, A); | |
614 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
615 } | |
616 | |
617 TEST(WebTransformationMatrixTest, RotateAxisAngle3dForArbitraryAxis) { | |
618 // Check rotation about an arbitrary non-axis-aligned vector. | |
619 WebTransformationMatrix A; | |
620 A.rotate3d(1, 1, 1, 90); | |
621 EXPECT_ROW1_NEAR(0.3333333333333334258519187, | |
622 -0.2440169358562924717404030, | |
623 0.9106836025229592124219380, | |
624 0, | |
625 A, | |
626 ERROR_THRESHOLD); | |
627 EXPECT_ROW2_NEAR(0.9106836025229592124219380, | |
628 0.3333333333333334258519187, | |
629 -0.2440169358562924717404030, | |
630 0, | |
631 A, | |
632 ERROR_THRESHOLD); | |
633 EXPECT_ROW3_NEAR(-0.2440169358562924717404030, | |
634 0.9106836025229592124219380, | |
635 0.3333333333333334258519187, | |
636 0, | |
637 A, | |
638 ERROR_THRESHOLD); | |
639 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
640 } | |
641 | |
642 TEST(WebTransformationMatrixTest, RotateAxisAngle3dForDegenerateAxis) { | |
643 // Check rotation about a degenerate zero vector. | |
644 // It is expected to skip applying the rotation. | |
645 WebTransformationMatrix A; | |
646 | |
647 A.rotate3d(0, 0, 0, 45); | |
648 // Verify that A remains unchanged. | |
649 EXPECT_TRUE(A.isIdentity()); | |
650 | |
651 initializeTestMatrix(A); | |
652 A.rotate3d(0, 0, 0, 35); | |
653 | |
654 // Verify that A remains unchanged. | |
655 EXPECT_ROW1_EQ(10, 14, 18, 22, A); | |
656 EXPECT_ROW2_EQ(11, 15, 19, 23, A); | |
657 EXPECT_ROW3_EQ(12, 16, 20, 24, A); | |
658 EXPECT_ROW4_EQ(13, 17, 21, 25, A); | |
659 } | |
660 | |
661 TEST(WebTransformationMatrixTest, SkewX) { | |
662 WebTransformationMatrix A; | |
663 A.skewX(45); | |
664 EXPECT_ROW1_EQ(1, 1, 0, 0, A); | |
665 EXPECT_ROW2_EQ(0, 1, 0, 0, A); | |
666 EXPECT_ROW3_EQ(0, 0, 1, 0, A); | |
667 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
668 | |
669 // Verify that skewX() post-multiplies the existing matrix. | |
670 // Row 1, column 2, would incorrectly have value "7" if the matrix is pre-mult
iplied instead of post-multiplied. | |
671 A.makeIdentity(); | |
672 A.scale3d(6, 7, 8); | |
673 A.skewX(45); | |
674 EXPECT_ROW1_EQ(6, 6, 0, 0, A); | |
675 EXPECT_ROW2_EQ(0, 7, 0, 0, A); | |
676 EXPECT_ROW3_EQ(0, 0, 8, 0, A); | |
677 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
678 } | |
679 | |
680 TEST(WebTransformationMatrixTest, SkewY) { | |
681 WebTransformationMatrix A; | |
682 A.skewY(45); | |
683 EXPECT_ROW1_EQ(1, 0, 0, 0, A); | |
684 EXPECT_ROW2_EQ(1, 1, 0, 0, A); | |
685 EXPECT_ROW3_EQ(0, 0, 1, 0, A); | |
686 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
687 | |
688 // Verify that skewY() post-multiplies the existing matrix. | |
689 // Row 2, column 1, would incorrectly have value "6" if the matrix is pre-mult
iplied instead of post-multiplied. | |
690 A.makeIdentity(); | |
691 A.scale3d(6, 7, 8); | |
692 A.skewY(45); | |
693 EXPECT_ROW1_EQ(6, 0, 0, 0, A); | |
694 EXPECT_ROW2_EQ(7, 7, 0, 0, A); | |
695 EXPECT_ROW3_EQ(0, 0, 8, 0, A); | |
696 EXPECT_ROW4_EQ(0, 0, 0, 1, A); | |
697 } | |
698 | |
699 TEST(WebTransformationMatrixTest, ApplyPerspective) { | |
700 WebTransformationMatrix A; | |
701 A.applyPerspective(1); | |
702 EXPECT_ROW1_EQ(1, 0, 0, 0, A); | |
703 EXPECT_ROW2_EQ(0, 1, 0, 0, A); | |
704 EXPECT_ROW3_EQ(0, 0, 1, 0, A); | |
705 EXPECT_ROW4_EQ(0, 0, -1, 1, A); | |
706 | |
707 // Verify that applyPerspective() post-multiplies the existing matrix. | |
708 A.makeIdentity(); | |
709 A.translate3d(2, 3, 4); | |
710 A.applyPerspective(1); | |
711 EXPECT_ROW1_EQ(1, 0, -2, 2, A); | |
712 EXPECT_ROW2_EQ(0, 1, -3, 3, A); | |
713 EXPECT_ROW3_EQ(0, 0, -3, 4, A); | |
714 EXPECT_ROW4_EQ(0, 0, -1, 1, A); | |
715 } | |
716 | |
717 TEST(WebTransformationMatrixTest, HasPerspective) { | |
718 WebTransformationMatrix A; | |
719 A.applyPerspective(1); | |
720 EXPECT_TRUE(A.hasPerspective()); | |
721 | |
722 A.makeIdentity(); | |
723 A.applyPerspective(0); | |
724 EXPECT_FALSE(A.hasPerspective()); | |
725 | |
726 A.makeIdentity(); | |
727 A.setM34(-0.3); | |
728 EXPECT_TRUE(A.hasPerspective()); | |
729 | |
730 // FIXME: WebCore only checkes m34() for perspective, but that is probably | |
731 // wrong. https://bugs.webkit.org/show_bug.cgi?id=83088. For now, this
test | |
732 // case expects the exact behavior as implemented by WebCore, but this
should | |
733 // probably be changed so that if the entire bottom row is not exactly | |
734 // (0, 0, 0, 1), then hasPerspective should return true. | |
735 | |
736 A.makeIdentity(); | |
737 A.setM14(-1); | |
738 EXPECT_FALSE(A.hasPerspective()); | |
739 | |
740 A.makeIdentity(); | |
741 A.setM24(-1); | |
742 EXPECT_FALSE(A.hasPerspective()); | |
743 | |
744 A.makeIdentity(); | |
745 A.setM44(0.5); | |
746 EXPECT_FALSE(A.hasPerspective()); | |
747 } | |
748 | |
749 TEST(WebTransformationMatrixTest, IsInvertible) { | |
750 WebTransformationMatrix A; | |
751 | |
752 // Translations, rotations, scales, skews and arbitrary combinations of them a
re invertible. | |
753 A.makeIdentity(); | |
754 EXPECT_TRUE(A.isInvertible()); | |
755 | |
756 A.makeIdentity(); | |
757 A.translate3d(2, 3, 4); | |
758 EXPECT_TRUE(A.isInvertible()); | |
759 | |
760 A.makeIdentity(); | |
761 A.scale3d(6, 7, 8); | |
762 EXPECT_TRUE(A.isInvertible()); | |
763 | |
764 A.makeIdentity(); | |
765 A.rotate3d(10, 20, 30); | |
766 EXPECT_TRUE(A.isInvertible()); | |
767 | |
768 A.makeIdentity(); | |
769 A.skewX(45); | |
770 EXPECT_TRUE(A.isInvertible()); | |
771 | |
772 // A perspective matrix (projection plane at z=0) is invertible. The intuitive | |
773 // explanation is that perspective is eqivalent to a skew of the w-axis; skews
are | |
774 // invertible. | |
775 A.makeIdentity(); | |
776 A.applyPerspective(1); | |
777 EXPECT_TRUE(A.isInvertible()); | |
778 | |
779 // A "pure" perspective matrix derived by similar triangles, with m44() set to
zero | |
780 // (i.e. camera positioned at the origin), is not invertible. | |
781 A.makeIdentity(); | |
782 A.applyPerspective(1); | |
783 A.setM44(0); | |
784 EXPECT_FALSE(A.isInvertible()); | |
785 | |
786 // Adding more to a non-invertible matrix will not make it invertible in the g
eneral case. | |
787 A.makeIdentity(); | |
788 A.applyPerspective(1); | |
789 A.setM44(0); | |
790 A.scale3d(6, 7, 8); | |
791 A.rotate3d(10, 20, 30); | |
792 A.translate3d(6, 7, 8); | |
793 EXPECT_FALSE(A.isInvertible()); | |
794 | |
795 // A degenerate matrix of all zeros is not invertible. | |
796 A.makeIdentity(); | |
797 A.setM11(0); | |
798 A.setM22(0); | |
799 A.setM33(0); | |
800 A.setM44(0); | |
801 EXPECT_FALSE(A.isInvertible()); | |
802 } | |
803 | |
804 TEST(WebTransformationMatrixTest, IsIdentity) { | |
805 WebTransformationMatrix A; | |
806 | |
807 initializeTestMatrix(A); | |
808 EXPECT_FALSE(A.isIdentity()); | |
809 | |
810 A.makeIdentity(); | |
811 EXPECT_TRUE(A.isIdentity()); | |
812 | |
813 // Modifying any one individual element should cause the matrix to no longer b
e identity. | |
814 A.makeIdentity(); | |
815 A.setM11(2); | |
816 EXPECT_FALSE(A.isIdentity()); | |
817 | |
818 A.makeIdentity(); | |
819 A.setM12(2); | |
820 EXPECT_FALSE(A.isIdentity()); | |
821 | |
822 A.makeIdentity(); | |
823 A.setM13(2); | |
824 EXPECT_FALSE(A.isIdentity()); | |
825 | |
826 A.makeIdentity(); | |
827 A.setM14(2); | |
828 EXPECT_FALSE(A.isIdentity()); | |
829 | |
830 A.makeIdentity(); | |
831 A.setM21(2); | |
832 EXPECT_FALSE(A.isIdentity()); | |
833 | |
834 A.makeIdentity(); | |
835 A.setM22(2); | |
836 EXPECT_FALSE(A.isIdentity()); | |
837 | |
838 A.makeIdentity(); | |
839 A.setM23(2); | |
840 EXPECT_FALSE(A.isIdentity()); | |
841 | |
842 A.makeIdentity(); | |
843 A.setM24(2); | |
844 EXPECT_FALSE(A.isIdentity()); | |
845 | |
846 A.makeIdentity(); | |
847 A.setM31(2); | |
848 EXPECT_FALSE(A.isIdentity()); | |
849 | |
850 A.makeIdentity(); | |
851 A.setM32(2); | |
852 EXPECT_FALSE(A.isIdentity()); | |
853 | |
854 A.makeIdentity(); | |
855 A.setM33(2); | |
856 EXPECT_FALSE(A.isIdentity()); | |
857 | |
858 A.makeIdentity(); | |
859 A.setM34(2); | |
860 EXPECT_FALSE(A.isIdentity()); | |
861 | |
862 A.makeIdentity(); | |
863 A.setM41(2); | |
864 EXPECT_FALSE(A.isIdentity()); | |
865 | |
866 A.makeIdentity(); | |
867 A.setM42(2); | |
868 EXPECT_FALSE(A.isIdentity()); | |
869 | |
870 A.makeIdentity(); | |
871 A.setM43(2); | |
872 EXPECT_FALSE(A.isIdentity()); | |
873 | |
874 A.makeIdentity(); | |
875 A.setM44(2); | |
876 EXPECT_FALSE(A.isIdentity()); | |
877 } | |
878 | |
879 TEST(WebTransformationMatrixTest, IsIdentityOrTranslation) { | |
880 WebTransformationMatrix A; | |
881 | |
882 initializeTestMatrix(A); | |
883 EXPECT_FALSE(A.isIdentityOrTranslation()); | |
884 | |
885 A.makeIdentity(); | |
886 EXPECT_TRUE(A.isIdentityOrTranslation()); | |
887 | |
888 // Modifying any non-translation components should cause isIdentityOrTranslati
on() to | |
889 // return false. NOTE: m41(), m42(), and m43() are the translation components,
so | |
890 // modifying them should still return true for isIdentityOrTranslation(). | |
891 A.makeIdentity(); | |
892 A.setM11(2); | |
893 EXPECT_FALSE(A.isIdentityOrTranslation()); | |
894 | |
895 A.makeIdentity(); | |
896 A.setM12(2); | |
897 EXPECT_FALSE(A.isIdentityOrTranslation()); | |
898 | |
899 A.makeIdentity(); | |
900 A.setM13(2); | |
901 EXPECT_FALSE(A.isIdentityOrTranslation()); | |
902 | |
903 A.makeIdentity(); | |
904 A.setM14(2); | |
905 EXPECT_FALSE(A.isIdentityOrTranslation()); | |
906 | |
907 A.makeIdentity(); | |
908 A.setM21(2); | |
909 EXPECT_FALSE(A.isIdentityOrTranslation()); | |
910 | |
911 A.makeIdentity(); | |
912 A.setM22(2); | |
913 EXPECT_FALSE(A.isIdentityOrTranslation()); | |
914 | |
915 A.makeIdentity(); | |
916 A.setM23(2); | |
917 EXPECT_FALSE(A.isIdentityOrTranslation()); | |
918 | |
919 A.makeIdentity(); | |
920 A.setM24(2); | |
921 EXPECT_FALSE(A.isIdentityOrTranslation()); | |
922 | |
923 A.makeIdentity(); | |
924 A.setM31(2); | |
925 EXPECT_FALSE(A.isIdentityOrTranslation()); | |
926 | |
927 A.makeIdentity(); | |
928 A.setM32(2); | |
929 EXPECT_FALSE(A.isIdentityOrTranslation()); | |
930 | |
931 A.makeIdentity(); | |
932 A.setM33(2); | |
933 EXPECT_FALSE(A.isIdentityOrTranslation()); | |
934 | |
935 A.makeIdentity(); | |
936 A.setM34(2); | |
937 EXPECT_FALSE(A.isIdentityOrTranslation()); | |
938 | |
939 // Note carefully - expecting true here. | |
940 A.makeIdentity(); | |
941 A.setM41(2); | |
942 EXPECT_TRUE(A.isIdentityOrTranslation()); | |
943 | |
944 // Note carefully - expecting true here. | |
945 A.makeIdentity(); | |
946 A.setM42(2); | |
947 EXPECT_TRUE(A.isIdentityOrTranslation()); | |
948 | |
949 // Note carefully - expecting true here. | |
950 A.makeIdentity(); | |
951 A.setM43(2); | |
952 EXPECT_TRUE(A.isIdentityOrTranslation()); | |
953 | |
954 A.makeIdentity(); | |
955 A.setM44(2); | |
956 EXPECT_FALSE(A.isIdentityOrTranslation()); | |
957 } | |
958 | |
959 TEST(WebTransformationMatrixTest, IsIntegerTranslation) { | |
960 WebTransformationMatrix A; | |
961 | |
962 A.makeIdentity(); | |
963 A.translate(2, 3); | |
964 EXPECT_TRUE(A.isIntegerTranslation()); | |
965 | |
966 A.makeIdentity(); | |
967 A.translate(2, 3); | |
968 EXPECT_TRUE(A.isIntegerTranslation()); | |
969 | |
970 A.makeIdentity(); | |
971 A.translate(2.00001, 3); | |
972 EXPECT_FALSE(A.isIntegerTranslation()); | |
973 | |
974 A.makeIdentity(); | |
975 A.translate(2, 2.99999); | |
976 EXPECT_FALSE(A.isIntegerTranslation()); | |
977 | |
978 // Stacking many integer translations should ideally not accumulate any precis
ion error. | |
979 A.makeIdentity(); | |
980 for (int i = 0; i < 100000; ++i) | |
981 A.translate(2, 3); | |
982 EXPECT_TRUE(A.isIntegerTranslation()); | |
983 } | |
984 | |
985 TEST(WebTransformationMatrixTest, BlendForTranslation) { | |
986 WebTransformationMatrix from; | |
987 from.translate3d(100, 200, 100); | |
988 | |
989 WebTransformationMatrix to; | |
990 | |
991 to.makeIdentity(); | |
992 to.translate3d(200, 100, 300); | |
993 to.blend(from, 0); | |
994 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to); | |
995 | |
996 to.makeIdentity(); | |
997 to.translate3d(200, 100, 300); | |
998 to.blend(from, 0.25); | |
999 EXPECT_ROW1_EQ(1, 0, 0, 125, to); | |
1000 EXPECT_ROW2_EQ(0, 1, 0, 175, to); | |
1001 EXPECT_ROW3_EQ(0, 0, 1, 150, to); | |
1002 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1003 | |
1004 to.makeIdentity(); | |
1005 to.translate3d(200, 100, 300); | |
1006 to.blend(from, 0.5); | |
1007 EXPECT_ROW1_EQ(1, 0, 0, 150, to); | |
1008 EXPECT_ROW2_EQ(0, 1, 0, 150, to); | |
1009 EXPECT_ROW3_EQ(0, 0, 1, 200, to); | |
1010 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1011 | |
1012 to.makeIdentity(); | |
1013 to.translate3d(200, 100, 300); | |
1014 to.blend(from, 1); | |
1015 EXPECT_ROW1_EQ(1, 0, 0, 200, to); | |
1016 EXPECT_ROW2_EQ(0, 1, 0, 100, to); | |
1017 EXPECT_ROW3_EQ(0, 0, 1, 300, to); | |
1018 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1019 } | |
1020 | |
1021 TEST(WebTransformationMatrixTest, BlendForScale) { | |
1022 WebTransformationMatrix from; | |
1023 from.scale3d(100, 200, 100); | |
1024 | |
1025 WebTransformationMatrix to; | |
1026 | |
1027 to.makeIdentity(); | |
1028 to.scale3d(200, 100, 300); | |
1029 to.blend(from, 0); | |
1030 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to); | |
1031 | |
1032 to.makeIdentity(); | |
1033 to.scale3d(200, 100, 300); | |
1034 to.blend(from, 0.25); | |
1035 EXPECT_ROW1_EQ(125, 0, 0, 0, to); | |
1036 EXPECT_ROW2_EQ(0, 175, 0, 0, to); | |
1037 EXPECT_ROW3_EQ(0, 0, 150, 0, to); | |
1038 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1039 | |
1040 to.makeIdentity(); | |
1041 to.scale3d(200, 100, 300); | |
1042 to.blend(from, 0.5); | |
1043 EXPECT_ROW1_EQ(150, 0, 0, 0, to); | |
1044 EXPECT_ROW2_EQ(0, 150, 0, 0, to); | |
1045 EXPECT_ROW3_EQ(0, 0, 200, 0, to); | |
1046 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1047 | |
1048 to.makeIdentity(); | |
1049 to.scale3d(200, 100, 300); | |
1050 to.blend(from, 1); | |
1051 EXPECT_ROW1_EQ(200, 0, 0, 0, to); | |
1052 EXPECT_ROW2_EQ(0, 100, 0, 0, to); | |
1053 EXPECT_ROW3_EQ(0, 0, 300, 0, to); | |
1054 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1055 } | |
1056 | |
1057 TEST(WebTransformationMatrixTest, BlendForSkewX) { | |
1058 WebTransformationMatrix from; | |
1059 from.skewX(0); | |
1060 | |
1061 WebTransformationMatrix to; | |
1062 | |
1063 to.makeIdentity(); | |
1064 to.skewX(45); | |
1065 to.blend(from, 0); | |
1066 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to); | |
1067 | |
1068 to.makeIdentity(); | |
1069 to.skewX(45); | |
1070 to.blend(from, 0.5); | |
1071 EXPECT_ROW1_EQ(1, 0.5, 0, 0, to); | |
1072 EXPECT_ROW2_EQ(0, 1, 0, 0, to); | |
1073 EXPECT_ROW3_EQ(0, 0, 1, 0, to); | |
1074 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1075 | |
1076 to.makeIdentity(); | |
1077 to.skewX(45); | |
1078 to.blend(from, 0.25); | |
1079 EXPECT_ROW1_EQ(1, 0.25, 0, 0, to); | |
1080 EXPECT_ROW2_EQ(0, 1, 0, 0, to); | |
1081 EXPECT_ROW3_EQ(0, 0, 1, 0, to); | |
1082 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1083 | |
1084 to.makeIdentity(); | |
1085 to.skewX(45); | |
1086 to.blend(from, 1); | |
1087 EXPECT_ROW1_EQ(1, 1, 0, 0, to); | |
1088 EXPECT_ROW2_EQ(0, 1, 0, 0, to); | |
1089 EXPECT_ROW3_EQ(0, 0, 1, 0, to); | |
1090 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1091 } | |
1092 | |
1093 TEST(WebTransformationMatrixTest, BlendForSkewY) { | |
1094 // NOTE CAREFULLY: Decomposition of skew and rotation terms of the matrix is | |
1095 // inherently underconstrained, and so it does not always compute the original
ly | |
1096 // intended skew parameters. The current implementation uses QR decomposition,
which | |
1097 // decomposes the shear into a rotation + non-uniform scale. | |
1098 // | |
1099 // It is unlikely that the decomposition implementation will need to change ve
ry | |
1100 // often, so to get any test coverage, the compromise is to verify the exact m
atrix | |
1101 // that the blend() operation produces. | |
1102 // | |
1103 // This problem also potentially exists for skewX, but the current QR decompos
ition | |
1104 // implementation just happens to decompose those test matrices intuitively. | |
1105 | |
1106 WebTransformationMatrix from; | |
1107 from.skewY(0); | |
1108 | |
1109 WebTransformationMatrix to; | |
1110 | |
1111 to.makeIdentity(); | |
1112 to.skewY(45); | |
1113 to.blend(from, 0); | |
1114 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to); | |
1115 | |
1116 to.makeIdentity(); | |
1117 to.skewY(45); | |
1118 to.blend(from, 0.25); | |
1119 EXPECT_ROW1_NEAR(1.0823489449280947471976333, | |
1120 0.0464370719145053845178239, | |
1121 0, | |
1122 0, | |
1123 to, | |
1124 LOOSE_ERROR_THRESHOLD); | |
1125 EXPECT_ROW2_NEAR(0.2152925909665224513123150, | |
1126 0.9541702441750861130032035, | |
1127 0, | |
1128 0, | |
1129 to, | |
1130 LOOSE_ERROR_THRESHOLD); | |
1131 EXPECT_ROW3_EQ(0, 0, 1, 0, to); | |
1132 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1133 | |
1134 to.makeIdentity(); | |
1135 to.skewY(45); | |
1136 to.blend(from, 0.5); | |
1137 EXPECT_ROW1_NEAR(1.1152212925809066312865525, | |
1138 0.0676495144007326631996335, | |
1139 0, | |
1140 0, | |
1141 to, | |
1142 LOOSE_ERROR_THRESHOLD); | |
1143 EXPECT_ROW2_NEAR(0.4619397844342648662419037, | |
1144 0.9519009045724774464858342, | |
1145 0, | |
1146 0, | |
1147 to, | |
1148 LOOSE_ERROR_THRESHOLD); | |
1149 EXPECT_ROW3_EQ(0, 0, 1, 0, to); | |
1150 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1151 | |
1152 // Unfortunately, this case suffers from uncomfortably large precision error. | |
1153 to.makeIdentity(); | |
1154 to.skewY(45); | |
1155 to.blend(from, 1); | |
1156 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, LOOSE_ERROR_THRESHOLD); | |
1157 EXPECT_ROW2_NEAR(1, 1, 0, 0, to, LOOSE_ERROR_THRESHOLD); | |
1158 EXPECT_ROW3_EQ(0, 0, 1, 0, to); | |
1159 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1160 } | |
1161 | |
1162 TEST(WebTransformationMatrixTest, BlendForRotationAboutX) { | |
1163 // Even though blending uses quaternions, axis-aligned rotations should blend
the same | |
1164 // with quaternions or Euler angles. So we can test rotation blending by compa
ring | |
1165 // against manually specified matrices from Euler angles. | |
1166 | |
1167 WebTransformationMatrix from; | |
1168 from.rotate3d(1, 0, 0, 0); | |
1169 | |
1170 WebTransformationMatrix to; | |
1171 | |
1172 to.makeIdentity(); | |
1173 to.rotate3d(1, 0, 0, 90); | |
1174 to.blend(from, 0); | |
1175 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to); | |
1176 | |
1177 double expected_rotation_angle = 22.5 * M_PI / 180.0; | |
1178 to.makeIdentity(); | |
1179 to.rotate3d(1, 0, 0, 90); | |
1180 to.blend(from, 0.25); | |
1181 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); | |
1182 EXPECT_ROW2_NEAR(0, | |
1183 cos(expected_rotation_angle), | |
1184 -sin(expected_rotation_angle), | |
1185 0, | |
1186 to, | |
1187 ERROR_THRESHOLD); | |
1188 EXPECT_ROW3_NEAR(0, | |
1189 sin(expected_rotation_angle), | |
1190 cos(expected_rotation_angle), | |
1191 0, | |
1192 to, | |
1193 ERROR_THRESHOLD); | |
1194 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1195 | |
1196 expected_rotation_angle = 45 * M_PI / 180.0; | |
1197 to.makeIdentity(); | |
1198 to.rotate3d(1, 0, 0, 90); | |
1199 to.blend(from, 0.5); | |
1200 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); | |
1201 EXPECT_ROW2_NEAR(0, | |
1202 cos(expected_rotation_angle), | |
1203 -sin(expected_rotation_angle), | |
1204 0, | |
1205 to, | |
1206 ERROR_THRESHOLD); | |
1207 EXPECT_ROW3_NEAR(0, | |
1208 sin(expected_rotation_angle), | |
1209 cos(expected_rotation_angle), | |
1210 0, | |
1211 to, | |
1212 ERROR_THRESHOLD); | |
1213 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1214 | |
1215 to.makeIdentity(); | |
1216 to.rotate3d(1, 0, 0, 90); | |
1217 to.blend(from, 1); | |
1218 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); | |
1219 EXPECT_ROW2_NEAR(0, 0, -1, 0, to, ERROR_THRESHOLD); | |
1220 EXPECT_ROW3_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); | |
1221 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1222 } | |
1223 | |
1224 TEST(WebTransformationMatrixTest, BlendForRotationAboutY) { | |
1225 WebTransformationMatrix from; | |
1226 from.rotate3d(0, 1, 0, 0); | |
1227 | |
1228 WebTransformationMatrix to; | |
1229 | |
1230 to.makeIdentity(); | |
1231 to.rotate3d(0, 1, 0, 90); | |
1232 to.blend(from, 0); | |
1233 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to); | |
1234 | |
1235 double expected_rotation_angle = 22.5 * M_PI / 180.0; | |
1236 to.makeIdentity(); | |
1237 to.rotate3d(0, 1, 0, 90); | |
1238 to.blend(from, 0.25); | |
1239 EXPECT_ROW1_NEAR(cos(expected_rotation_angle), | |
1240 0, | |
1241 sin(expected_rotation_angle), | |
1242 0, | |
1243 to, | |
1244 ERROR_THRESHOLD); | |
1245 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); | |
1246 EXPECT_ROW3_NEAR(-sin(expected_rotation_angle), | |
1247 0, | |
1248 cos(expected_rotation_angle), | |
1249 0, | |
1250 to, | |
1251 ERROR_THRESHOLD); | |
1252 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1253 | |
1254 expected_rotation_angle = 45 * M_PI / 180.0; | |
1255 to.makeIdentity(); | |
1256 to.rotate3d(0, 1, 0, 90); | |
1257 to.blend(from, 0.5); | |
1258 EXPECT_ROW1_NEAR(cos(expected_rotation_angle), | |
1259 0, | |
1260 sin(expected_rotation_angle), | |
1261 0, | |
1262 to, | |
1263 ERROR_THRESHOLD); | |
1264 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); | |
1265 EXPECT_ROW3_NEAR(-sin(expected_rotation_angle), | |
1266 0, | |
1267 cos(expected_rotation_angle), | |
1268 0, | |
1269 to, | |
1270 ERROR_THRESHOLD); | |
1271 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1272 | |
1273 to.makeIdentity(); | |
1274 to.rotate3d(0, 1, 0, 90); | |
1275 to.blend(from, 1); | |
1276 EXPECT_ROW1_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); | |
1277 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); | |
1278 EXPECT_ROW3_NEAR(-1, 0, 0, 0, to, ERROR_THRESHOLD); | |
1279 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1280 } | |
1281 | |
1282 TEST(WebTransformationMatrixTest, BlendForRotationAboutZ) { | |
1283 WebTransformationMatrix from; | |
1284 from.rotate3d(0, 0, 1, 0); | |
1285 | |
1286 WebTransformationMatrix to; | |
1287 | |
1288 to.makeIdentity(); | |
1289 to.rotate3d(0, 0, 1, 90); | |
1290 to.blend(from, 0); | |
1291 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to); | |
1292 | |
1293 double expected_rotation_angle = 22.5 * M_PI / 180.0; | |
1294 to.makeIdentity(); | |
1295 to.rotate3d(0, 0, 1, 90); | |
1296 to.blend(from, 0.25); | |
1297 EXPECT_ROW1_NEAR(cos(expected_rotation_angle), | |
1298 -sin(expected_rotation_angle), | |
1299 0, | |
1300 0, | |
1301 to, | |
1302 ERROR_THRESHOLD); | |
1303 EXPECT_ROW2_NEAR(sin(expected_rotation_angle), | |
1304 cos(expected_rotation_angle), | |
1305 0, | |
1306 0, | |
1307 to, | |
1308 ERROR_THRESHOLD); | |
1309 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); | |
1310 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1311 | |
1312 expected_rotation_angle = 45 * M_PI / 180.0; | |
1313 to.makeIdentity(); | |
1314 to.rotate3d(0, 0, 1, 90); | |
1315 to.blend(from, 0.5); | |
1316 EXPECT_ROW1_NEAR(cos(expected_rotation_angle), | |
1317 -sin(expected_rotation_angle), | |
1318 0, | |
1319 0, | |
1320 to, | |
1321 ERROR_THRESHOLD); | |
1322 EXPECT_ROW2_NEAR(sin(expected_rotation_angle), | |
1323 cos(expected_rotation_angle), | |
1324 0, | |
1325 0, | |
1326 to, | |
1327 ERROR_THRESHOLD); | |
1328 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); | |
1329 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1330 | |
1331 to.makeIdentity(); | |
1332 to.rotate3d(0, 0, 1, 90); | |
1333 to.blend(from, 1); | |
1334 EXPECT_ROW1_NEAR(0, -1, 0, 0, to, ERROR_THRESHOLD); | |
1335 EXPECT_ROW2_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); | |
1336 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); | |
1337 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | |
1338 } | |
1339 | |
1340 TEST(WebTransformationMatrixTest, BlendForCompositeTransform) { | |
1341 // Verify that the blending was done with a decomposition in correct order by
blending | |
1342 // a composite transform. | |
1343 // Using matrix x vector notation (Ax = b, where x is column vector), the orde
ring should be: | |
1344 // perspective * translation * rotation * skew * scale | |
1345 // | |
1346 // It is not as important (or meaningful) to check intermediate interpolations
; order | |
1347 // of operations will be tested well enough by the end cases that are easier t
o | |
1348 // specify. | |
1349 | |
1350 WebTransformationMatrix from; | |
1351 WebTransformationMatrix to; | |
1352 | |
1353 WebTransformationMatrix expected_end_of_animation; | |
1354 expected_end_of_animation.applyPerspective(1); | |
1355 expected_end_of_animation.translate3d(10, 20, 30); | |
1356 expected_end_of_animation.rotate3d(0, 0, 1, 25); | |
1357 expected_end_of_animation.skewY(45); | |
1358 expected_end_of_animation.scale3d(6, 7, 8); | |
1359 | |
1360 to = expected_end_of_animation; | |
1361 to.blend(from, 0); | |
1362 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(from, to); | |
1363 | |
1364 to = expected_end_of_animation; | |
1365 to.blend(from, 1); | |
1366 | |
1367 // Recomposing the matrix results in a normalized matrix, so to verify we need
to | |
1368 // normalize the expected_end_of_animation before comparing elements. Normaliz
ing means | |
1369 // dividing everything by expected_end_of_animation.m44(). | |
1370 WebTransformationMatrix normalized_expected_end_of_animation = | |
1371 expected_end_of_animation; | |
1372 WebTransformationMatrix normalization_matrix; | |
1373 normalization_matrix.setM11(1 / expected_end_of_animation.m44()); | |
1374 normalization_matrix.setM22(1 / expected_end_of_animation.m44()); | |
1375 normalization_matrix.setM33(1 / expected_end_of_animation.m44()); | |
1376 normalization_matrix.setM44(1 / expected_end_of_animation.m44()); | |
1377 normalized_expected_end_of_animation.multiply(normalization_matrix); | |
1378 | |
1379 EXPECT_WEB_TRANSFORMATION_MATRIX_EQ(normalized_expected_end_of_animation, to); | |
1380 } | |
1381 | |
1382 } // namespace | |
OLD | NEW |