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