OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // MSVC++ requires this to be set before any other includes to get M_PI. | 5 // MSVC++ requires this to be set before any other includes to get M_PI. |
6 #define _USE_MATH_DEFINES | 6 #define _USE_MATH_DEFINES |
7 | 7 |
8 #include "ui/gfx/transform.h" | 8 #include "ui/gfx/transform.h" |
9 | 9 |
10 #include <cmath> | 10 #include <cmath> |
11 #include <ostream> | 11 #include <ostream> |
12 #include <limits> | 12 #include <limits> |
13 | 13 |
14 #include "base/basictypes.h" | 14 #include "base/basictypes.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
16 #include "ui/gfx/point.h" | 16 #include "ui/gfx/point.h" |
17 #include "ui/gfx/point3_f.h" | 17 #include "ui/gfx/point3_f.h" |
18 #include "ui/gfx/transform_util.h" | 18 #include "ui/gfx/transform_util.h" |
| 19 #include "ui/gfx/vector3d_f.h" |
19 | 20 |
20 namespace gfx { | 21 namespace gfx { |
21 | 22 |
22 namespace { | 23 namespace { |
23 | 24 |
24 bool PointsAreNearlyEqual(const Point3F& lhs, | 25 bool PointsAreNearlyEqual(const Point3F& lhs, |
25 const Point3F& rhs) { | 26 const Point3F& rhs) { |
26 float epsilon = 0.0001f; | 27 float epsilon = 0.0001f; |
27 return lhs.SquaredDistanceTo(rhs) < epsilon; | 28 return lhs.SquaredDistanceTo(rhs) < epsilon; |
28 } | 29 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 } | 110 } |
110 if (i == 100) { | 111 if (i == 100) { |
111 EXPECT_TRUE(rhs == interpolated); | 112 EXPECT_TRUE(rhs == interpolated); |
112 } else { | 113 } else { |
113 EXPECT_TRUE(rhs != interpolated); | 114 EXPECT_TRUE(rhs != interpolated); |
114 } | 115 } |
115 } | 116 } |
116 lhs = Transform(); | 117 lhs = Transform(); |
117 rhs = Transform(); | 118 rhs = Transform(); |
118 for (int i = 1; i < 100; ++i) { | 119 for (int i = 1; i < 100; ++i) { |
119 lhs.SetTranslate(i, i); | 120 lhs.MakeIdentity(); |
120 rhs.SetTranslate(-i, -i); | 121 rhs.MakeIdentity(); |
| 122 lhs.Translate(i, i); |
| 123 rhs.Translate(-i, -i); |
121 EXPECT_TRUE(lhs != rhs); | 124 EXPECT_TRUE(lhs != rhs); |
122 rhs.ConcatTranslate(2*i, 2*i); | 125 rhs.Translate(2*i, 2*i); |
123 EXPECT_TRUE(lhs == rhs); | 126 EXPECT_TRUE(lhs == rhs); |
124 } | 127 } |
125 } | 128 } |
126 | 129 |
127 TEST(XFormTest, ConcatTranslate) { | 130 TEST(XFormTest, ConcatTranslate) { |
128 static const struct TestCase { | 131 static const struct TestCase { |
129 int x1; | 132 int x1; |
130 int y1; | 133 int y1; |
131 float tx; | 134 float tx; |
132 float ty; | 135 float ty; |
133 int x2; | 136 int x2; |
134 int y2; | 137 int y2; |
135 } test_cases[] = { | 138 } test_cases[] = { |
136 { 0, 0, 10.0f, 20.0f, 10, 20 }, | 139 { 0, 0, 10.0f, 20.0f, 10, 20 }, |
137 { 0, 0, -10.0f, -20.0f, 0, 0 }, | 140 { 0, 0, -10.0f, -20.0f, 0, 0 }, |
138 { 0, 0, -10.0f, -20.0f, -10, -20 }, | 141 { 0, 0, -10.0f, -20.0f, -10, -20 }, |
139 { 0, 0, | 142 { 0, 0, |
140 std::numeric_limits<float>::quiet_NaN(), | 143 std::numeric_limits<float>::quiet_NaN(), |
141 std::numeric_limits<float>::quiet_NaN(), | 144 std::numeric_limits<float>::quiet_NaN(), |
142 10, 20 }, | 145 10, 20 }, |
143 }; | 146 }; |
144 | 147 |
145 Transform xform; | 148 Transform xform; |
146 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | 149 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { |
147 const TestCase& value = test_cases[i]; | 150 const TestCase& value = test_cases[i]; |
148 xform.ConcatTranslate(value.tx, value.ty); | 151 Transform translation; |
| 152 translation.Translate(value.tx, value.ty); |
| 153 xform = translation * xform; |
149 Point3F p1(value.x1, value.y1, 0); | 154 Point3F p1(value.x1, value.y1, 0); |
150 Point3F p2(value.x2, value.y2, 0); | 155 Point3F p2(value.x2, value.y2, 0); |
151 xform.TransformPoint(p1); | 156 xform.TransformPoint(p1); |
152 if (value.tx == value.tx && | 157 if (value.tx == value.tx && |
153 value.ty == value.ty) { | 158 value.ty == value.ty) { |
154 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); | 159 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); |
155 } | 160 } |
156 } | 161 } |
157 } | 162 } |
158 | 163 |
159 TEST(XFormTest, ConcatScale) { | 164 TEST(XFormTest, ConcatScale) { |
160 static const struct TestCase { | 165 static const struct TestCase { |
161 int before; | 166 int before; |
162 float scale; | 167 float scale; |
163 int after; | 168 int after; |
164 } test_cases[] = { | 169 } test_cases[] = { |
165 { 1, 10.0f, 10 }, | 170 { 1, 10.0f, 10 }, |
166 { 1, .1f, 1 }, | 171 { 1, .1f, 1 }, |
167 { 1, 100.0f, 100 }, | 172 { 1, 100.0f, 100 }, |
168 { 1, -1.0f, -100 }, | 173 { 1, -1.0f, -100 }, |
169 { 1, std::numeric_limits<float>::quiet_NaN(), 1 } | 174 { 1, std::numeric_limits<float>::quiet_NaN(), 1 } |
170 }; | 175 }; |
171 | 176 |
172 Transform xform; | 177 Transform xform; |
173 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | 178 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { |
174 const TestCase& value = test_cases[i]; | 179 const TestCase& value = test_cases[i]; |
175 xform.ConcatScale(value.scale, value.scale); | 180 Transform scale; |
| 181 scale.Scale(value.scale, value.scale); |
| 182 xform = scale * xform; |
176 Point3F p1(value.before, value.before, 0); | 183 Point3F p1(value.before, value.before, 0); |
177 Point3F p2(value.after, value.after, 0); | 184 Point3F p2(value.after, value.after, 0); |
178 xform.TransformPoint(p1); | 185 xform.TransformPoint(p1); |
179 if (value.scale == value.scale) { | 186 if (value.scale == value.scale) { |
180 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); | 187 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); |
181 } | 188 } |
182 } | 189 } |
183 } | 190 } |
184 | 191 |
185 TEST(XFormTest, ConcatRotate) { | 192 TEST(XFormTest, ConcatRotate) { |
186 static const struct TestCase { | 193 static const struct TestCase { |
187 int x1; | 194 int x1; |
188 int y1; | 195 int y1; |
189 float degrees; | 196 float degrees; |
190 int x2; | 197 int x2; |
191 int y2; | 198 int y2; |
192 } test_cases[] = { | 199 } test_cases[] = { |
193 { 1, 0, 90.0f, 0, 1 }, | 200 { 1, 0, 90.0f, 0, 1 }, |
194 { 1, 0, -90.0f, 1, 0 }, | 201 { 1, 0, -90.0f, 1, 0 }, |
195 { 1, 0, 90.0f, 0, 1 }, | 202 { 1, 0, 90.0f, 0, 1 }, |
196 { 1, 0, 360.0f, 0, 1 }, | 203 { 1, 0, 360.0f, 0, 1 }, |
197 { 1, 0, 0.0f, 0, 1 }, | 204 { 1, 0, 0.0f, 0, 1 }, |
198 { 1, 0, std::numeric_limits<float>::quiet_NaN(), 1, 0 } | 205 { 1, 0, std::numeric_limits<float>::quiet_NaN(), 1, 0 } |
199 }; | 206 }; |
200 | 207 |
201 Transform xform; | 208 Transform xform; |
202 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | 209 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { |
203 const TestCase& value = test_cases[i]; | 210 const TestCase& value = test_cases[i]; |
204 xform.ConcatRotate(value.degrees); | 211 Transform rotation; |
| 212 rotation.Rotate(value.degrees); |
| 213 xform = rotation * xform; |
205 Point3F p1(value.x1, value.y1, 0); | 214 Point3F p1(value.x1, value.y1, 0); |
206 Point3F p2(value.x2, value.y2, 0); | 215 Point3F p2(value.x2, value.y2, 0); |
207 xform.TransformPoint(p1); | 216 xform.TransformPoint(p1); |
208 if (value.degrees == value.degrees) { | 217 if (value.degrees == value.degrees) { |
209 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); | 218 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); |
210 } | 219 } |
211 } | 220 } |
212 } | 221 } |
213 | 222 |
214 TEST(XFormTest, SetTranslate) { | 223 TEST(XFormTest, SetTranslate) { |
(...skipping 13 matching lines...) Expand all Loading... |
228 | 237 |
229 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | 238 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { |
230 const TestCase& value = test_cases[i]; | 239 const TestCase& value = test_cases[i]; |
231 for (int k = 0; k < 3; ++k) { | 240 for (int k = 0; k < 3; ++k) { |
232 Point3F p0, p1, p2; | 241 Point3F p0, p1, p2; |
233 Transform xform; | 242 Transform xform; |
234 switch (k) { | 243 switch (k) { |
235 case 0: | 244 case 0: |
236 p1.SetPoint(value.x1, 0, 0); | 245 p1.SetPoint(value.x1, 0, 0); |
237 p2.SetPoint(value.x2, 0, 0); | 246 p2.SetPoint(value.x2, 0, 0); |
238 xform.SetTranslateX(value.tx); | 247 xform.Translate(value.tx, 0.0); |
239 break; | 248 break; |
240 case 1: | 249 case 1: |
241 p1.SetPoint(0, value.y1, 0); | 250 p1.SetPoint(0, value.y1, 0); |
242 p2.SetPoint(0, value.y2, 0); | 251 p2.SetPoint(0, value.y2, 0); |
243 xform.SetTranslateY(value.ty); | 252 xform.Translate(0.0, value.ty); |
244 break; | 253 break; |
245 case 2: | 254 case 2: |
246 p1.SetPoint(value.x1, value.y1, 0); | 255 p1.SetPoint(value.x1, value.y1, 0); |
247 p2.SetPoint(value.x2, value.y2, 0); | 256 p2.SetPoint(value.x2, value.y2, 0); |
248 xform.SetTranslate(value.tx, value.ty); | 257 xform.Translate(value.tx, value.ty); |
249 break; | 258 break; |
250 } | 259 } |
251 p0 = p1; | 260 p0 = p1; |
252 xform.TransformPoint(p1); | 261 xform.TransformPoint(p1); |
253 if (value.tx == value.tx && | 262 if (value.tx == value.tx && |
254 value.ty == value.ty) { | 263 value.ty == value.ty) { |
255 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); | 264 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); |
256 xform.TransformPointReverse(p1); | 265 xform.TransformPointReverse(p1); |
257 EXPECT_TRUE(PointsAreNearlyEqual(p1, p0)); | 266 EXPECT_TRUE(PointsAreNearlyEqual(p1, p0)); |
258 } | 267 } |
(...skipping 16 matching lines...) Expand all Loading... |
275 | 284 |
276 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | 285 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { |
277 const TestCase& value = test_cases[i]; | 286 const TestCase& value = test_cases[i]; |
278 for (int k = 0; k < 3; ++k) { | 287 for (int k = 0; k < 3; ++k) { |
279 Point3F p0, p1, p2; | 288 Point3F p0, p1, p2; |
280 Transform xform; | 289 Transform xform; |
281 switch (k) { | 290 switch (k) { |
282 case 0: | 291 case 0: |
283 p1.SetPoint(value.before, 0, 0); | 292 p1.SetPoint(value.before, 0, 0); |
284 p2.SetPoint(value.after, 0, 0); | 293 p2.SetPoint(value.after, 0, 0); |
285 xform.SetScaleX(value.s); | 294 xform.Scale(value.s, 1.0); |
286 break; | 295 break; |
287 case 1: | 296 case 1: |
288 p1.SetPoint(0, value.before, 0); | 297 p1.SetPoint(0, value.before, 0); |
289 p2.SetPoint(0, value.after, 0); | 298 p2.SetPoint(0, value.after, 0); |
290 xform.SetScaleY(value.s); | 299 xform.Scale(1.0, value.s); |
291 break; | 300 break; |
292 case 2: | 301 case 2: |
293 p1.SetPoint(value.before, value.before, 0); | 302 p1.SetPoint(value.before, value.before, 0); |
294 p2.SetPoint(value.after, value.after, 0); | 303 p2.SetPoint(value.after, value.after, 0); |
295 xform.SetScale(value.s, value.s); | 304 xform.Scale(value.s, value.s); |
296 break; | 305 break; |
297 } | 306 } |
298 p0 = p1; | 307 p0 = p1; |
299 xform.TransformPoint(p1); | 308 xform.TransformPoint(p1); |
300 if (value.s == value.s) { | 309 if (value.s == value.s) { |
301 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); | 310 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); |
302 if (value.s != 0.0f) { | 311 if (value.s != 0.0f) { |
303 xform.TransformPointReverse(p1); | 312 xform.TransformPointReverse(p1); |
304 EXPECT_TRUE(PointsAreNearlyEqual(p1, p0)); | 313 EXPECT_TRUE(PointsAreNearlyEqual(p1, p0)); |
305 } | 314 } |
(...skipping 20 matching lines...) Expand all Loading... |
326 { 100, 0, 360.0f, 100, 0 } | 335 { 100, 0, 360.0f, 100, 0 } |
327 }; | 336 }; |
328 | 337 |
329 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(set_rotate_cases); ++i) { | 338 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(set_rotate_cases); ++i) { |
330 const SetRotateCase& value = set_rotate_cases[i]; | 339 const SetRotateCase& value = set_rotate_cases[i]; |
331 Point3F p0; | 340 Point3F p0; |
332 Point3F p1(value.x, value.y, 0); | 341 Point3F p1(value.x, value.y, 0); |
333 Point3F p2(value.xprime, value.yprime, 0); | 342 Point3F p2(value.xprime, value.yprime, 0); |
334 p0 = p1; | 343 p0 = p1; |
335 Transform xform; | 344 Transform xform; |
336 xform.SetRotate(value.degree); | 345 xform.Rotate(value.degree); |
337 // just want to make sure that we don't crash in the case of NaN. | 346 // just want to make sure that we don't crash in the case of NaN. |
338 if (value.degree == value.degree) { | 347 if (value.degree == value.degree) { |
339 xform.TransformPoint(p1); | 348 xform.TransformPoint(p1); |
340 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); | 349 EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); |
341 xform.TransformPointReverse(p1); | 350 xform.TransformPointReverse(p1); |
342 EXPECT_TRUE(PointsAreNearlyEqual(p1, p0)); | 351 EXPECT_TRUE(PointsAreNearlyEqual(p1, p0)); |
343 } | 352 } |
344 } | 353 } |
345 } | 354 } |
346 | 355 |
(...skipping 12 matching lines...) Expand all Loading... |
359 { 0, 0, -10.0f, -20.0f, -10, -20}, | 368 { 0, 0, -10.0f, -20.0f, -10, -20}, |
360 { 0, 0, | 369 { 0, 0, |
361 std::numeric_limits<float>::quiet_NaN(), | 370 std::numeric_limits<float>::quiet_NaN(), |
362 std::numeric_limits<float>::quiet_NaN(), | 371 std::numeric_limits<float>::quiet_NaN(), |
363 10, 20}, | 372 10, 20}, |
364 }; | 373 }; |
365 | 374 |
366 Transform xform; | 375 Transform xform; |
367 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | 376 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { |
368 const TestCase& value = test_cases[i]; | 377 const TestCase& value = test_cases[i]; |
369 xform.ConcatTranslate(value.tx, value.ty); | 378 Transform translation; |
| 379 translation.Translate(value.tx, value.ty); |
| 380 xform = translation * xform; |
370 Point p1(value.x1, value.y1); | 381 Point p1(value.x1, value.y1); |
371 Point p2(value.x2, value.y2); | 382 Point p2(value.x2, value.y2); |
372 xform.TransformPoint(p1); | 383 xform.TransformPoint(p1); |
373 if (value.tx == value.tx && | 384 if (value.tx == value.tx && |
374 value.ty == value.ty) { | 385 value.ty == value.ty) { |
375 EXPECT_EQ(p1.x(), p2.x()); | 386 EXPECT_EQ(p1.x(), p2.x()); |
376 EXPECT_EQ(p1.y(), p2.y()); | 387 EXPECT_EQ(p1.y(), p2.y()); |
377 } | 388 } |
378 } | 389 } |
379 } | 390 } |
380 | 391 |
381 TEST(XFormTest, ConcatScale2D) { | 392 TEST(XFormTest, ConcatScale2D) { |
382 static const struct TestCase { | 393 static const struct TestCase { |
383 int before; | 394 int before; |
384 float scale; | 395 float scale; |
385 int after; | 396 int after; |
386 } test_cases[] = { | 397 } test_cases[] = { |
387 { 1, 10.0f, 10}, | 398 { 1, 10.0f, 10}, |
388 { 1, .1f, 1}, | 399 { 1, .1f, 1}, |
389 { 1, 100.0f, 100}, | 400 { 1, 100.0f, 100}, |
390 { 1, -1.0f, -100}, | 401 { 1, -1.0f, -100}, |
391 { 1, std::numeric_limits<float>::quiet_NaN(), 1} | 402 { 1, std::numeric_limits<float>::quiet_NaN(), 1} |
392 }; | 403 }; |
393 | 404 |
394 Transform xform; | 405 Transform xform; |
395 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | 406 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { |
396 const TestCase& value = test_cases[i]; | 407 const TestCase& value = test_cases[i]; |
397 xform.ConcatScale(value.scale, value.scale); | 408 Transform scale; |
| 409 scale.Scale(value.scale, value.scale); |
| 410 xform = scale * xform; |
398 Point p1(value.before, value.before); | 411 Point p1(value.before, value.before); |
399 Point p2(value.after, value.after); | 412 Point p2(value.after, value.after); |
400 xform.TransformPoint(p1); | 413 xform.TransformPoint(p1); |
401 if (value.scale == value.scale) { | 414 if (value.scale == value.scale) { |
402 EXPECT_EQ(p1.x(), p2.x()); | 415 EXPECT_EQ(p1.x(), p2.x()); |
403 EXPECT_EQ(p1.y(), p2.y()); | 416 EXPECT_EQ(p1.y(), p2.y()); |
404 } | 417 } |
405 } | 418 } |
406 } | 419 } |
407 | 420 |
408 TEST(XFormTest, ConcatRotate2D) { | 421 TEST(XFormTest, ConcatRotate2D) { |
409 static const struct TestCase { | 422 static const struct TestCase { |
410 int x1; | 423 int x1; |
411 int y1; | 424 int y1; |
412 float degrees; | 425 float degrees; |
413 int x2; | 426 int x2; |
414 int y2; | 427 int y2; |
415 } test_cases[] = { | 428 } test_cases[] = { |
416 { 1, 0, 90.0f, 0, 1}, | 429 { 1, 0, 90.0f, 0, 1}, |
417 { 1, 0, -90.0f, 1, 0}, | 430 { 1, 0, -90.0f, 1, 0}, |
418 { 1, 0, 90.0f, 0, 1}, | 431 { 1, 0, 90.0f, 0, 1}, |
419 { 1, 0, 360.0f, 0, 1}, | 432 { 1, 0, 360.0f, 0, 1}, |
420 { 1, 0, 0.0f, 0, 1}, | 433 { 1, 0, 0.0f, 0, 1}, |
421 { 1, 0, std::numeric_limits<float>::quiet_NaN(), 1, 0} | 434 { 1, 0, std::numeric_limits<float>::quiet_NaN(), 1, 0} |
422 }; | 435 }; |
423 | 436 |
424 Transform xform; | 437 Transform xform; |
425 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | 438 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { |
426 const TestCase& value = test_cases[i]; | 439 const TestCase& value = test_cases[i]; |
427 xform.ConcatRotate(value.degrees); | 440 Transform rotation; |
| 441 rotation.Rotate(value.degrees); |
| 442 xform = rotation * xform; |
428 Point p1(value.x1, value.y1); | 443 Point p1(value.x1, value.y1); |
429 Point p2(value.x2, value.y2); | 444 Point p2(value.x2, value.y2); |
430 xform.TransformPoint(p1); | 445 xform.TransformPoint(p1); |
431 if (value.degrees == value.degrees) { | 446 if (value.degrees == value.degrees) { |
432 EXPECT_EQ(p1.x(), p2.x()); | 447 EXPECT_EQ(p1.x(), p2.x()); |
433 EXPECT_EQ(p1.y(), p2.y()); | 448 EXPECT_EQ(p1.y(), p2.y()); |
434 } | 449 } |
435 } | 450 } |
436 } | 451 } |
437 | 452 |
(...skipping 16 matching lines...) Expand all Loading... |
454 const TestCase& value = test_cases[i]; | 469 const TestCase& value = test_cases[i]; |
455 for (int j = -1; j < 2; ++j) { | 470 for (int j = -1; j < 2; ++j) { |
456 for (int k = 0; k < 3; ++k) { | 471 for (int k = 0; k < 3; ++k) { |
457 float epsilon = 0.0001f; | 472 float epsilon = 0.0001f; |
458 Point p0, p1, p2; | 473 Point p0, p1, p2; |
459 Transform xform; | 474 Transform xform; |
460 switch (k) { | 475 switch (k) { |
461 case 0: | 476 case 0: |
462 p1.SetPoint(value.x1, 0); | 477 p1.SetPoint(value.x1, 0); |
463 p2.SetPoint(value.x2, 0); | 478 p2.SetPoint(value.x2, 0); |
464 xform.SetTranslateX(value.tx + j * epsilon); | 479 xform.Translate(value.tx + j * epsilon, 0.0); |
465 break; | 480 break; |
466 case 1: | 481 case 1: |
467 p1.SetPoint(0, value.y1); | 482 p1.SetPoint(0, value.y1); |
468 p2.SetPoint(0, value.y2); | 483 p2.SetPoint(0, value.y2); |
469 xform.SetTranslateY(value.ty + j * epsilon); | 484 xform.Translate(0.0, value.ty + j * epsilon); |
470 break; | 485 break; |
471 case 2: | 486 case 2: |
472 p1.SetPoint(value.x1, value.y1); | 487 p1.SetPoint(value.x1, value.y1); |
473 p2.SetPoint(value.x2, value.y2); | 488 p2.SetPoint(value.x2, value.y2); |
474 xform.SetTranslate(value.tx + j * epsilon, | 489 xform.Translate(value.tx + j * epsilon, |
475 value.ty + j * epsilon); | 490 value.ty + j * epsilon); |
476 break; | 491 break; |
477 } | 492 } |
478 p0 = p1; | 493 p0 = p1; |
479 xform.TransformPoint(p1); | 494 xform.TransformPoint(p1); |
480 if (value.tx == value.tx && | 495 if (value.tx == value.tx && |
481 value.ty == value.ty) { | 496 value.ty == value.ty) { |
482 EXPECT_EQ(p1.x(), p2.x()); | 497 EXPECT_EQ(p1.x(), p2.x()); |
483 EXPECT_EQ(p1.y(), p2.y()); | 498 EXPECT_EQ(p1.y(), p2.y()); |
484 xform.TransformPointReverse(p1); | 499 xform.TransformPointReverse(p1); |
485 EXPECT_EQ(p1.x(), p0.x()); | 500 EXPECT_EQ(p1.x(), p0.x()); |
(...skipping 21 matching lines...) Expand all Loading... |
507 const TestCase& value = test_cases[i]; | 522 const TestCase& value = test_cases[i]; |
508 for (int j = -1; j < 2; ++j) { | 523 for (int j = -1; j < 2; ++j) { |
509 for (int k = 0; k < 3; ++k) { | 524 for (int k = 0; k < 3; ++k) { |
510 float epsilon = 0.0001f; | 525 float epsilon = 0.0001f; |
511 Point p0, p1, p2; | 526 Point p0, p1, p2; |
512 Transform xform; | 527 Transform xform; |
513 switch (k) { | 528 switch (k) { |
514 case 0: | 529 case 0: |
515 p1.SetPoint(value.before, 0); | 530 p1.SetPoint(value.before, 0); |
516 p2.SetPoint(value.after, 0); | 531 p2.SetPoint(value.after, 0); |
517 xform.SetScaleX(value.s + j * epsilon); | 532 xform.Scale(value.s + j * epsilon, 1.0); |
518 break; | 533 break; |
519 case 1: | 534 case 1: |
520 p1.SetPoint(0, value.before); | 535 p1.SetPoint(0, value.before); |
521 p2.SetPoint(0, value.after); | 536 p2.SetPoint(0, value.after); |
522 xform.SetScaleY(value.s + j * epsilon); | 537 xform.Scale(1.0, value.s + j * epsilon); |
523 break; | 538 break; |
524 case 2: | 539 case 2: |
525 p1.SetPoint(value.before, | 540 p1.SetPoint(value.before, |
526 value.before); | 541 value.before); |
527 p2.SetPoint(value.after, | 542 p2.SetPoint(value.after, |
528 value.after); | 543 value.after); |
529 xform.SetScale(value.s + j * epsilon, | 544 xform.Scale(value.s + j * epsilon, |
530 value.s + j * epsilon); | 545 value.s + j * epsilon); |
531 break; | 546 break; |
532 } | 547 } |
533 p0 = p1; | 548 p0 = p1; |
534 xform.TransformPoint(p1); | 549 xform.TransformPoint(p1); |
535 if (value.s == value.s) { | 550 if (value.s == value.s) { |
536 EXPECT_EQ(p1.x(), p2.x()); | 551 EXPECT_EQ(p1.x(), p2.x()); |
537 EXPECT_EQ(p1.y(), p2.y()); | 552 EXPECT_EQ(p1.y(), p2.y()); |
538 if (value.s != 0.0f) { | 553 if (value.s != 0.0f) { |
539 xform.TransformPointReverse(p1); | 554 xform.TransformPointReverse(p1); |
540 EXPECT_EQ(p1.x(), p0.x()); | 555 EXPECT_EQ(p1.x(), p0.x()); |
(...skipping 23 matching lines...) Expand all Loading... |
564 { 100, 0, 360.0f, 100, 0} | 579 { 100, 0, 360.0f, 100, 0} |
565 }; | 580 }; |
566 | 581 |
567 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(set_rotate_cases); ++i) { | 582 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(set_rotate_cases); ++i) { |
568 const SetRotateCase& value = set_rotate_cases[i]; | 583 const SetRotateCase& value = set_rotate_cases[i]; |
569 for (int j = 1; j >= -1; --j) { | 584 for (int j = 1; j >= -1; --j) { |
570 float epsilon = 0.1f; | 585 float epsilon = 0.1f; |
571 Point pt(value.x, value.y); | 586 Point pt(value.x, value.y); |
572 Transform xform; | 587 Transform xform; |
573 // should be invariant to small floating point errors. | 588 // should be invariant to small floating point errors. |
574 xform.SetRotate(value.degree + j * epsilon); | 589 xform.Rotate(value.degree + j * epsilon); |
575 // just want to make sure that we don't crash in the case of NaN. | 590 // just want to make sure that we don't crash in the case of NaN. |
576 if (value.degree == value.degree) { | 591 if (value.degree == value.degree) { |
577 xform.TransformPoint(pt); | 592 xform.TransformPoint(pt); |
578 EXPECT_EQ(value.xprime, pt.x()); | 593 EXPECT_EQ(value.xprime, pt.x()); |
579 EXPECT_EQ(value.yprime, pt.y()); | 594 EXPECT_EQ(value.yprime, pt.y()); |
580 xform.TransformPointReverse(pt); | 595 xform.TransformPointReverse(pt); |
581 EXPECT_EQ(pt.x(), value.x); | 596 EXPECT_EQ(pt.x(), value.x); |
582 EXPECT_EQ(pt.y(), value.y); | 597 EXPECT_EQ(pt.y(), value.y); |
583 } | 598 } |
584 } | 599 } |
585 } | 600 } |
586 } | 601 } |
587 | 602 |
588 TEST(XFormTest, BlendTranslate) { | 603 TEST(XFormTest, BlendTranslate) { |
589 Transform from; | 604 Transform from; |
590 for (int i = 0; i < 10; ++i) { | 605 for (int i = 0; i < 10; ++i) { |
591 Transform to; | 606 Transform to; |
592 to.SetTranslate3d(1, 1, 1); | 607 to.Translate3d(1, 1, 1); |
593 double t = i / 9.0; | 608 double t = i / 9.0; |
594 EXPECT_TRUE(to.Blend(from, t)); | 609 EXPECT_TRUE(to.Blend(from, t)); |
595 EXPECT_FLOAT_EQ(t, to.matrix().get(0, 3)); | 610 EXPECT_FLOAT_EQ(t, to.matrix().get(0, 3)); |
596 EXPECT_FLOAT_EQ(t, to.matrix().get(1, 3)); | 611 EXPECT_FLOAT_EQ(t, to.matrix().get(1, 3)); |
597 EXPECT_FLOAT_EQ(t, to.matrix().get(2, 3)); | 612 EXPECT_FLOAT_EQ(t, to.matrix().get(2, 3)); |
598 } | 613 } |
599 } | 614 } |
600 | 615 |
601 TEST(XFormTest, BlendRotate) { | 616 TEST(XFormTest, BlendRotate) { |
602 Point3F axes[] = { | 617 Vector3dF axes[] = { |
603 Point3F(1, 0, 0), | 618 Vector3dF(1, 0, 0), |
604 Point3F(0, 1, 0), | 619 Vector3dF(0, 1, 0), |
605 Point3F(0, 0, 1), | 620 Vector3dF(0, 0, 1), |
606 Point3F(1, 1, 1) | 621 Vector3dF(1, 1, 1) |
607 }; | 622 }; |
608 Transform from; | 623 Transform from; |
609 for (size_t index = 0; index < ARRAYSIZE_UNSAFE(axes); ++index) { | 624 for (size_t index = 0; index < ARRAYSIZE_UNSAFE(axes); ++index) { |
610 for (int i = 0; i < 10; ++i) { | 625 for (int i = 0; i < 10; ++i) { |
611 Transform to; | 626 Transform to; |
612 to.SetRotateAbout(axes[index], 90); | 627 to.RotateAbout(axes[index], 90); |
613 double t = i / 9.0; | 628 double t = i / 9.0; |
614 EXPECT_TRUE(to.Blend(from, t)); | 629 EXPECT_TRUE(to.Blend(from, t)); |
615 | 630 |
616 Transform expected; | 631 Transform expected; |
617 expected.SetRotateAbout(axes[index], 90 * t); | 632 expected.RotateAbout(axes[index], 90 * t); |
618 | 633 |
619 EXPECT_TRUE(MatricesAreNearlyEqual(expected, to)); | 634 EXPECT_TRUE(MatricesAreNearlyEqual(expected, to)); |
620 } | 635 } |
621 } | 636 } |
622 } | 637 } |
623 | 638 |
624 TEST(XFormTest, CannotBlend180DegreeRotation) { | 639 TEST(XFormTest, CannotBlend180DegreeRotation) { |
625 Point3F axes[] = { | 640 Vector3dF axes[] = { |
626 Point3F(1, 0, 0), | 641 Vector3dF(1, 0, 0), |
627 Point3F(0, 1, 0), | 642 Vector3dF(0, 1, 0), |
628 Point3F(0, 0, 1), | 643 Vector3dF(0, 0, 1), |
629 Point3F(1, 1, 1) | 644 Vector3dF(1, 1, 1) |
630 }; | 645 }; |
631 Transform from; | 646 Transform from; |
632 for (size_t index = 0; index < ARRAYSIZE_UNSAFE(axes); ++index) { | 647 for (size_t index = 0; index < ARRAYSIZE_UNSAFE(axes); ++index) { |
633 Transform to; | 648 Transform to; |
634 to.SetRotateAbout(axes[index], 180); | 649 to.RotateAbout(axes[index], 180); |
635 EXPECT_FALSE(to.Blend(from, 0.5)); | 650 EXPECT_FALSE(to.Blend(from, 0.5)); |
636 } | 651 } |
637 } | 652 } |
638 | 653 |
639 TEST(XFormTest, BlendScale) { | 654 TEST(XFormTest, BlendScale) { |
640 Transform from; | 655 Transform from; |
641 for (int i = 0; i < 10; ++i) { | 656 for (int i = 0; i < 10; ++i) { |
642 Transform to; | 657 Transform to; |
643 to.SetScale3d(5, 4, 3); | 658 to.Scale3d(5, 4, 3); |
644 double t = i / 9.0; | 659 double t = i / 9.0; |
645 EXPECT_TRUE(to.Blend(from, t)); | 660 EXPECT_TRUE(to.Blend(from, t)); |
646 EXPECT_FLOAT_EQ(t * 4 + 1, to.matrix().get(0, 0)); | 661 EXPECT_FLOAT_EQ(t * 4 + 1, to.matrix().get(0, 0)); |
647 EXPECT_FLOAT_EQ(t * 3 + 1, to.matrix().get(1, 1)); | 662 EXPECT_FLOAT_EQ(t * 3 + 1, to.matrix().get(1, 1)); |
648 EXPECT_FLOAT_EQ(t * 2 + 1, to.matrix().get(2, 2)); | 663 EXPECT_FLOAT_EQ(t * 2 + 1, to.matrix().get(2, 2)); |
649 } | 664 } |
650 } | 665 } |
651 | 666 |
652 TEST(XFormTest, BlendSkew) { | 667 TEST(XFormTest, BlendSkew) { |
653 Transform from; | 668 Transform from; |
654 for (int i = 0; i < 2; ++i) { | 669 for (int i = 0; i < 2; ++i) { |
655 Transform to; | 670 Transform to; |
656 to.SetSkewX(20); | 671 to.SkewX(20); |
657 to.PreconcatSkewY(10); | 672 to.SkewY(10); |
658 double t = i; | 673 double t = i; |
659 Transform expected; | 674 Transform expected; |
660 expected.SetSkewX(t * 20); | 675 expected.SkewX(t * 20); |
661 expected.PreconcatSkewY(t * 10); | 676 expected.SkewY(t * 10); |
662 EXPECT_TRUE(to.Blend(from, t)); | 677 EXPECT_TRUE(to.Blend(from, t)); |
663 EXPECT_TRUE(MatricesAreNearlyEqual(expected, to)); | 678 EXPECT_TRUE(MatricesAreNearlyEqual(expected, to)); |
664 } | 679 } |
665 } | 680 } |
666 | 681 |
667 TEST(XFormTest, BlendPerspective) { | 682 TEST(XFormTest, BlendPerspective) { |
668 Transform from; | 683 Transform from; |
669 from.SetPerspectiveDepth(200); | 684 from.ApplyPerspectiveDepth(200); |
670 for (int i = 0; i < 2; ++i) { | 685 for (int i = 0; i < 2; ++i) { |
671 Transform to; | 686 Transform to; |
672 to.SetPerspectiveDepth(800); | 687 to.ApplyPerspectiveDepth(800); |
673 double t = i; | 688 double t = i; |
674 Transform expected; | 689 Transform expected; |
675 expected.SetPerspectiveDepth(t * 600 + 200); | 690 expected.ApplyPerspectiveDepth(t * 600 + 200); |
676 EXPECT_TRUE(to.Blend(from, t)); | 691 EXPECT_TRUE(to.Blend(from, t)); |
677 EXPECT_TRUE(MatricesAreNearlyEqual(expected, to)); | 692 EXPECT_TRUE(MatricesAreNearlyEqual(expected, to)); |
678 } | 693 } |
679 } | 694 } |
680 | 695 |
681 TEST(XFormTest, BlendIdentity) { | 696 TEST(XFormTest, BlendIdentity) { |
682 Transform from; | 697 Transform from; |
683 Transform to; | 698 Transform to; |
684 EXPECT_TRUE(to.Blend(from, 0.5)); | 699 EXPECT_TRUE(to.Blend(from, 0.5)); |
685 EXPECT_EQ(to, from); | 700 EXPECT_EQ(to, from); |
686 } | 701 } |
687 | 702 |
688 TEST(XFormTest, CannotBlendSingularMatrix) { | 703 TEST(XFormTest, CannotBlendSingularMatrix) { |
689 Transform from; | 704 Transform from; |
690 Transform to; | 705 Transform to; |
691 to.matrix().set(1, 1, SkDoubleToMScalar(0)); | 706 to.matrix().set(1, 1, SkDoubleToMScalar(0)); |
692 EXPECT_FALSE(to.Blend(from, 0.5)); | 707 EXPECT_FALSE(to.Blend(from, 0.5)); |
693 } | 708 } |
694 | 709 |
695 TEST(XFormTest, VerifyBlendForTranslation) | 710 TEST(XFormTest, VerifyBlendForTranslation) |
696 { | 711 { |
697 Transform from; | 712 Transform from; |
698 from.PreconcatTranslate3d(100, 200, 100); | 713 from.Translate3d(100, 200, 100); |
699 | 714 |
700 Transform to; | 715 Transform to; |
701 | 716 |
702 to.PreconcatTranslate3d(200, 100, 300); | 717 to.Translate3d(200, 100, 300); |
703 to.Blend(from, 0); | 718 to.Blend(from, 0); |
704 EXPECT_EQ(from, to); | 719 EXPECT_EQ(from, to); |
705 | 720 |
706 to = Transform(); | 721 to = Transform(); |
707 to.PreconcatTranslate3d(200, 100, 300); | 722 to.Translate3d(200, 100, 300); |
708 to.Blend(from, 0.25); | 723 to.Blend(from, 0.25); |
709 EXPECT_ROW1_EQ(1, 0, 0, 125, to); | 724 EXPECT_ROW1_EQ(1, 0, 0, 125, to); |
710 EXPECT_ROW2_EQ(0, 1, 0, 175, to); | 725 EXPECT_ROW2_EQ(0, 1, 0, 175, to); |
711 EXPECT_ROW3_EQ(0, 0, 1, 150, to); | 726 EXPECT_ROW3_EQ(0, 0, 1, 150, to); |
712 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 727 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
713 | 728 |
714 to = Transform(); | 729 to = Transform(); |
715 to.PreconcatTranslate3d(200, 100, 300); | 730 to.Translate3d(200, 100, 300); |
716 to.Blend(from, 0.5); | 731 to.Blend(from, 0.5); |
717 EXPECT_ROW1_EQ(1, 0, 0, 150, to); | 732 EXPECT_ROW1_EQ(1, 0, 0, 150, to); |
718 EXPECT_ROW2_EQ(0, 1, 0, 150, to); | 733 EXPECT_ROW2_EQ(0, 1, 0, 150, to); |
719 EXPECT_ROW3_EQ(0, 0, 1, 200, to); | 734 EXPECT_ROW3_EQ(0, 0, 1, 200, to); |
720 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 735 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
721 | 736 |
722 to = Transform(); | 737 to = Transform(); |
723 to.PreconcatTranslate3d(200, 100, 300); | 738 to.Translate3d(200, 100, 300); |
724 to.Blend(from, 1); | 739 to.Blend(from, 1); |
725 EXPECT_ROW1_EQ(1, 0, 0, 200, to); | 740 EXPECT_ROW1_EQ(1, 0, 0, 200, to); |
726 EXPECT_ROW2_EQ(0, 1, 0, 100, to); | 741 EXPECT_ROW2_EQ(0, 1, 0, 100, to); |
727 EXPECT_ROW3_EQ(0, 0, 1, 300, to); | 742 EXPECT_ROW3_EQ(0, 0, 1, 300, to); |
728 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 743 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
729 } | 744 } |
730 | 745 |
731 TEST(XFormTest, VerifyBlendForScale) | 746 TEST(XFormTest, VerifyBlendForScale) |
732 { | 747 { |
733 Transform from; | 748 Transform from; |
734 from.PreconcatScale3d(100, 200, 100); | 749 from.Scale3d(100, 200, 100); |
735 | 750 |
736 Transform to; | 751 Transform to; |
737 | 752 |
738 to.PreconcatScale3d(200, 100, 300); | 753 to.Scale3d(200, 100, 300); |
739 to.Blend(from, 0); | 754 to.Blend(from, 0); |
740 EXPECT_EQ(from, to); | 755 EXPECT_EQ(from, to); |
741 | 756 |
742 to = Transform(); | 757 to = Transform(); |
743 to.PreconcatScale3d(200, 100, 300); | 758 to.Scale3d(200, 100, 300); |
744 to.Blend(from, 0.25); | 759 to.Blend(from, 0.25); |
745 EXPECT_ROW1_EQ(125, 0, 0, 0, to); | 760 EXPECT_ROW1_EQ(125, 0, 0, 0, to); |
746 EXPECT_ROW2_EQ(0, 175, 0, 0, to); | 761 EXPECT_ROW2_EQ(0, 175, 0, 0, to); |
747 EXPECT_ROW3_EQ(0, 0, 150, 0, to); | 762 EXPECT_ROW3_EQ(0, 0, 150, 0, to); |
748 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 763 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
749 | 764 |
750 to = Transform(); | 765 to = Transform(); |
751 to.PreconcatScale3d(200, 100, 300); | 766 to.Scale3d(200, 100, 300); |
752 to.Blend(from, 0.5); | 767 to.Blend(from, 0.5); |
753 EXPECT_ROW1_EQ(150, 0, 0, 0, to); | 768 EXPECT_ROW1_EQ(150, 0, 0, 0, to); |
754 EXPECT_ROW2_EQ(0, 150, 0, 0, to); | 769 EXPECT_ROW2_EQ(0, 150, 0, 0, to); |
755 EXPECT_ROW3_EQ(0, 0, 200, 0, to); | 770 EXPECT_ROW3_EQ(0, 0, 200, 0, to); |
756 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 771 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
757 | 772 |
758 to = Transform(); | 773 to = Transform(); |
759 to.PreconcatScale3d(200, 100, 300); | 774 to.Scale3d(200, 100, 300); |
760 to.Blend(from, 1); | 775 to.Blend(from, 1); |
761 EXPECT_ROW1_EQ(200, 0, 0, 0, to); | 776 EXPECT_ROW1_EQ(200, 0, 0, 0, to); |
762 EXPECT_ROW2_EQ(0, 100, 0, 0, to); | 777 EXPECT_ROW2_EQ(0, 100, 0, 0, to); |
763 EXPECT_ROW3_EQ(0, 0, 300, 0, to); | 778 EXPECT_ROW3_EQ(0, 0, 300, 0, to); |
764 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 779 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
765 } | 780 } |
766 | 781 |
767 TEST(XFormTest, VerifyBlendForSkewX) | 782 TEST(XFormTest, VerifyBlendForSkewX) |
768 { | 783 { |
769 Transform from; | 784 Transform from; |
770 from.PreconcatSkewX(0); | 785 from.SkewX(0); |
771 | 786 |
772 Transform to; | 787 Transform to; |
773 | 788 |
774 to.PreconcatSkewX(45); | 789 to.SkewX(45); |
775 to.Blend(from, 0); | 790 to.Blend(from, 0); |
776 EXPECT_EQ(from, to); | 791 EXPECT_EQ(from, to); |
777 | 792 |
778 to = Transform(); | 793 to = Transform(); |
779 to.PreconcatSkewX(45); | 794 to.SkewX(45); |
780 to.Blend(from, 0.5); | 795 to.Blend(from, 0.5); |
781 EXPECT_ROW1_EQ(1, 0.5, 0, 0, to); | 796 EXPECT_ROW1_EQ(1, 0.5, 0, 0, to); |
782 EXPECT_ROW2_EQ(0, 1, 0, 0, to); | 797 EXPECT_ROW2_EQ(0, 1, 0, 0, to); |
783 EXPECT_ROW3_EQ(0, 0, 1, 0, to); | 798 EXPECT_ROW3_EQ(0, 0, 1, 0, to); |
784 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 799 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
785 | 800 |
786 to = Transform(); | 801 to = Transform(); |
787 to.PreconcatSkewX(45); | 802 to.SkewX(45); |
788 to.Blend(from, 0.25); | 803 to.Blend(from, 0.25); |
789 EXPECT_ROW1_EQ(1, 0.25, 0, 0, to); | 804 EXPECT_ROW1_EQ(1, 0.25, 0, 0, to); |
790 EXPECT_ROW2_EQ(0, 1, 0, 0, to); | 805 EXPECT_ROW2_EQ(0, 1, 0, 0, to); |
791 EXPECT_ROW3_EQ(0, 0, 1, 0, to); | 806 EXPECT_ROW3_EQ(0, 0, 1, 0, to); |
792 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 807 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
793 | 808 |
794 to = Transform(); | 809 to = Transform(); |
795 to.PreconcatSkewX(45); | 810 to.SkewX(45); |
796 to.Blend(from, 1); | 811 to.Blend(from, 1); |
797 EXPECT_ROW1_EQ(1, 1, 0, 0, to); | 812 EXPECT_ROW1_EQ(1, 1, 0, 0, to); |
798 EXPECT_ROW2_EQ(0, 1, 0, 0, to); | 813 EXPECT_ROW2_EQ(0, 1, 0, 0, to); |
799 EXPECT_ROW3_EQ(0, 0, 1, 0, to); | 814 EXPECT_ROW3_EQ(0, 0, 1, 0, to); |
800 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 815 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
801 } | 816 } |
802 | 817 |
803 TEST(XFormTest, VerifyBlendForSkewY) | 818 TEST(XFormTest, VerifyBlendForSkewY) |
804 { | 819 { |
805 // NOTE CAREFULLY: Decomposition of skew and rotation terms of the matrix | 820 // NOTE CAREFULLY: Decomposition of skew and rotation terms of the matrix |
806 // is inherently underconstrained, and so it does not always compute the | 821 // is inherently underconstrained, and so it does not always compute the |
807 // originally intended skew parameters. The current implementation uses QR | 822 // originally intended skew parameters. The current implementation uses QR |
808 // decomposition, which decomposes the shear into a rotation + non-uniform | 823 // decomposition, which decomposes the shear into a rotation + non-uniform |
809 // scale. | 824 // scale. |
810 // | 825 // |
811 // It is unlikely that the decomposition implementation will need to change | 826 // It is unlikely that the decomposition implementation will need to change |
812 // very often, so to get any test coverage, the compromise is to verify the | 827 // very often, so to get any test coverage, the compromise is to verify the |
813 // exact matrix that the.Blend() operation produces. | 828 // exact matrix that the.Blend() operation produces. |
814 // | 829 // |
815 // This problem also potentially exists for skewX, but the current QR | 830 // This problem also potentially exists for skewX, but the current QR |
816 // decomposition implementation just happens to decompose those test | 831 // decomposition implementation just happens to decompose those test |
817 // matrices intuitively. | 832 // matrices intuitively. |
818 // | 833 // |
819 // Unfortunately, this case suffers from uncomfortably large precision | 834 // Unfortunately, this case suffers from uncomfortably large precision |
820 // error. | 835 // error. |
821 | 836 |
822 Transform from; | 837 Transform from; |
823 from.PreconcatSkewY(0); | 838 from.SkewY(0); |
824 | 839 |
825 Transform to; | 840 Transform to; |
826 | 841 |
827 to.PreconcatSkewY(45); | 842 to.SkewY(45); |
828 to.Blend(from, 0); | 843 to.Blend(from, 0); |
829 EXPECT_EQ(from, to); | 844 EXPECT_EQ(from, to); |
830 | 845 |
831 to = Transform(); | 846 to = Transform(); |
832 to.PreconcatSkewY(45); | 847 to.SkewY(45); |
833 to.Blend(from, 0.25); | 848 to.Blend(from, 0.25); |
834 EXPECT_ROW1_NEAR(1.0823489449280947471976333, | 849 EXPECT_ROW1_NEAR(1.0823489449280947471976333, |
835 0.0464370719145053845178239, | 850 0.0464370719145053845178239, |
836 0, | 851 0, |
837 0, | 852 0, |
838 to, | 853 to, |
839 LOOSE_ERROR_THRESHOLD); | 854 LOOSE_ERROR_THRESHOLD); |
840 EXPECT_ROW2_NEAR(0.2152925909665224513123150, | 855 EXPECT_ROW2_NEAR(0.2152925909665224513123150, |
841 0.9541702441750861130032035, | 856 0.9541702441750861130032035, |
842 0, | 857 0, |
843 0, | 858 0, |
844 to, | 859 to, |
845 LOOSE_ERROR_THRESHOLD); | 860 LOOSE_ERROR_THRESHOLD); |
846 EXPECT_ROW3_EQ(0, 0, 1, 0, to); | 861 EXPECT_ROW3_EQ(0, 0, 1, 0, to); |
847 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 862 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
848 | 863 |
849 to = Transform(); | 864 to = Transform(); |
850 to.PreconcatSkewY(45); | 865 to.SkewY(45); |
851 to.Blend(from, 0.5); | 866 to.Blend(from, 0.5); |
852 EXPECT_ROW1_NEAR(1.1152212925809066312865525, | 867 EXPECT_ROW1_NEAR(1.1152212925809066312865525, |
853 0.0676495144007326631996335, | 868 0.0676495144007326631996335, |
854 0, | 869 0, |
855 0, | 870 0, |
856 to, | 871 to, |
857 LOOSE_ERROR_THRESHOLD); | 872 LOOSE_ERROR_THRESHOLD); |
858 EXPECT_ROW2_NEAR(0.4619397844342648662419037, | 873 EXPECT_ROW2_NEAR(0.4619397844342648662419037, |
859 0.9519009045724774464858342, | 874 0.9519009045724774464858342, |
860 0, | 875 0, |
861 0, | 876 0, |
862 to, | 877 to, |
863 LOOSE_ERROR_THRESHOLD); | 878 LOOSE_ERROR_THRESHOLD); |
864 EXPECT_ROW3_EQ(0, 0, 1, 0, to); | 879 EXPECT_ROW3_EQ(0, 0, 1, 0, to); |
865 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 880 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
866 | 881 |
867 to = Transform(); | 882 to = Transform(); |
868 to.PreconcatSkewY(45); | 883 to.SkewY(45); |
869 to.Blend(from, 1); | 884 to.Blend(from, 1); |
870 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, LOOSE_ERROR_THRESHOLD); | 885 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, LOOSE_ERROR_THRESHOLD); |
871 EXPECT_ROW2_NEAR(1, 1, 0, 0, to, LOOSE_ERROR_THRESHOLD); | 886 EXPECT_ROW2_NEAR(1, 1, 0, 0, to, LOOSE_ERROR_THRESHOLD); |
872 EXPECT_ROW3_EQ(0, 0, 1, 0, to); | 887 EXPECT_ROW3_EQ(0, 0, 1, 0, to); |
873 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 888 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
874 } | 889 } |
875 | 890 |
876 TEST(XFormTest, VerifyBlendForRotationAboutX) | 891 TEST(XFormTest, VerifyBlendForRotationAboutX) |
877 { | 892 { |
878 // Even though.Blending uses quaternions, axis-aligned rotations should. | 893 // Even though.Blending uses quaternions, axis-aligned rotations should. |
879 // Blend the same with quaternions or Euler angles. So we can test | 894 // Blend the same with quaternions or Euler angles. So we can test |
880 // rotation.Blending by comparing against manually specified matrices from | 895 // rotation.Blending by comparing against manually specified matrices from |
881 // Euler angles. | 896 // Euler angles. |
882 | 897 |
883 Transform from; | 898 Transform from; |
884 from.PreconcatRotateAbout(Point3F(1, 0, 0), 0); | 899 from.RotateAbout(Vector3dF(1, 0, 0), 0); |
885 | 900 |
886 Transform to; | 901 Transform to; |
887 | 902 |
888 to.PreconcatRotateAbout(Point3F(1, 0, 0), 90); | 903 to.RotateAbout(Vector3dF(1, 0, 0), 90); |
889 to.Blend(from, 0); | 904 to.Blend(from, 0); |
890 EXPECT_EQ(from, to); | 905 EXPECT_EQ(from, to); |
891 | 906 |
892 double expectedRotationAngle = 22.5 * M_PI / 180.0; | 907 double expectedRotationAngle = 22.5 * M_PI / 180.0; |
893 to = Transform(); | 908 to = Transform(); |
894 to.PreconcatRotateAbout(Point3F(1, 0, 0), 90); | 909 to.RotateAbout(Vector3dF(1, 0, 0), 90); |
895 to.Blend(from, 0.25); | 910 to.Blend(from, 0.25); |
896 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); | 911 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); |
897 EXPECT_ROW2_NEAR(0, | 912 EXPECT_ROW2_NEAR(0, |
898 std::cos(expectedRotationAngle), | 913 std::cos(expectedRotationAngle), |
899 -std::sin(expectedRotationAngle), | 914 -std::sin(expectedRotationAngle), |
900 0, | 915 0, |
901 to, | 916 to, |
902 ERROR_THRESHOLD); | 917 ERROR_THRESHOLD); |
903 EXPECT_ROW3_NEAR(0, | 918 EXPECT_ROW3_NEAR(0, |
904 std::sin(expectedRotationAngle), | 919 std::sin(expectedRotationAngle), |
905 std::cos(expectedRotationAngle), | 920 std::cos(expectedRotationAngle), |
906 0, | 921 0, |
907 to, | 922 to, |
908 ERROR_THRESHOLD); | 923 ERROR_THRESHOLD); |
909 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 924 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
910 | 925 |
911 expectedRotationAngle = 45 * M_PI / 180.0; | 926 expectedRotationAngle = 45 * M_PI / 180.0; |
912 to = Transform(); | 927 to = Transform(); |
913 to.PreconcatRotateAbout(Point3F(1, 0, 0), 90); | 928 to.RotateAbout(Vector3dF(1, 0, 0), 90); |
914 to.Blend(from, 0.5); | 929 to.Blend(from, 0.5); |
915 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); | 930 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); |
916 EXPECT_ROW2_NEAR(0, | 931 EXPECT_ROW2_NEAR(0, |
917 std::cos(expectedRotationAngle), | 932 std::cos(expectedRotationAngle), |
918 -std::sin(expectedRotationAngle), | 933 -std::sin(expectedRotationAngle), |
919 0, | 934 0, |
920 to, | 935 to, |
921 ERROR_THRESHOLD); | 936 ERROR_THRESHOLD); |
922 EXPECT_ROW3_NEAR(0, | 937 EXPECT_ROW3_NEAR(0, |
923 std::sin(expectedRotationAngle), | 938 std::sin(expectedRotationAngle), |
924 std::cos(expectedRotationAngle), | 939 std::cos(expectedRotationAngle), |
925 0, | 940 0, |
926 to, | 941 to, |
927 ERROR_THRESHOLD); | 942 ERROR_THRESHOLD); |
928 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 943 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
929 | 944 |
930 to = Transform(); | 945 to = Transform(); |
931 to.PreconcatRotateAbout(Point3F(1, 0, 0), 90); | 946 to.RotateAbout(Vector3dF(1, 0, 0), 90); |
932 to.Blend(from, 1); | 947 to.Blend(from, 1); |
933 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); | 948 EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); |
934 EXPECT_ROW2_NEAR(0, 0, -1, 0, to, ERROR_THRESHOLD); | 949 EXPECT_ROW2_NEAR(0, 0, -1, 0, to, ERROR_THRESHOLD); |
935 EXPECT_ROW3_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); | 950 EXPECT_ROW3_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); |
936 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 951 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
937 } | 952 } |
938 | 953 |
939 TEST(XFormTest, VerifyBlendForRotationAboutY) | 954 TEST(XFormTest, VerifyBlendForRotationAboutY) |
940 { | 955 { |
941 Transform from; | 956 Transform from; |
942 from.PreconcatRotateAbout(Point3F(0, 1, 0), 0); | 957 from.RotateAbout(Vector3dF(0, 1, 0), 0); |
943 | 958 |
944 Transform to; | 959 Transform to; |
945 | 960 |
946 to.PreconcatRotateAbout(Point3F(0, 1, 0), 90); | 961 to.RotateAbout(Vector3dF(0, 1, 0), 90); |
947 to.Blend(from, 0); | 962 to.Blend(from, 0); |
948 EXPECT_EQ(from, to); | 963 EXPECT_EQ(from, to); |
949 | 964 |
950 double expectedRotationAngle = 22.5 * M_PI / 180.0; | 965 double expectedRotationAngle = 22.5 * M_PI / 180.0; |
951 to = Transform(); | 966 to = Transform(); |
952 to.PreconcatRotateAbout(Point3F(0, 1, 0), 90); | 967 to.RotateAbout(Vector3dF(0, 1, 0), 90); |
953 to.Blend(from, 0.25); | 968 to.Blend(from, 0.25); |
954 EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle), | 969 EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle), |
955 0, | 970 0, |
956 std::sin(expectedRotationAngle), | 971 std::sin(expectedRotationAngle), |
957 0, | 972 0, |
958 to, | 973 to, |
959 ERROR_THRESHOLD); | 974 ERROR_THRESHOLD); |
960 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); | 975 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); |
961 EXPECT_ROW3_NEAR(-std::sin(expectedRotationAngle), | 976 EXPECT_ROW3_NEAR(-std::sin(expectedRotationAngle), |
962 0, | 977 0, |
963 std::cos(expectedRotationAngle), | 978 std::cos(expectedRotationAngle), |
964 0, | 979 0, |
965 to, | 980 to, |
966 ERROR_THRESHOLD); | 981 ERROR_THRESHOLD); |
967 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 982 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
968 | 983 |
969 expectedRotationAngle = 45 * M_PI / 180.0; | 984 expectedRotationAngle = 45 * M_PI / 180.0; |
970 to = Transform(); | 985 to = Transform(); |
971 to.PreconcatRotateAbout(Point3F(0, 1, 0), 90); | 986 to.RotateAbout(Vector3dF(0, 1, 0), 90); |
972 to.Blend(from, 0.5); | 987 to.Blend(from, 0.5); |
973 EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle), | 988 EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle), |
974 0, | 989 0, |
975 std::sin(expectedRotationAngle), | 990 std::sin(expectedRotationAngle), |
976 0, | 991 0, |
977 to, | 992 to, |
978 ERROR_THRESHOLD); | 993 ERROR_THRESHOLD); |
979 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); | 994 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); |
980 EXPECT_ROW3_NEAR(-std::sin(expectedRotationAngle), | 995 EXPECT_ROW3_NEAR(-std::sin(expectedRotationAngle), |
981 0, | 996 0, |
982 std::cos(expectedRotationAngle), | 997 std::cos(expectedRotationAngle), |
983 0, | 998 0, |
984 to, | 999 to, |
985 ERROR_THRESHOLD); | 1000 ERROR_THRESHOLD); |
986 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 1001 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
987 | 1002 |
988 to = Transform(); | 1003 to = Transform(); |
989 to.PreconcatRotateAbout(Point3F(0, 1, 0), 90); | 1004 to.RotateAbout(Vector3dF(0, 1, 0), 90); |
990 to.Blend(from, 1); | 1005 to.Blend(from, 1); |
991 EXPECT_ROW1_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); | 1006 EXPECT_ROW1_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); |
992 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); | 1007 EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD); |
993 EXPECT_ROW3_NEAR(-1, 0, 0, 0, to, ERROR_THRESHOLD); | 1008 EXPECT_ROW3_NEAR(-1, 0, 0, 0, to, ERROR_THRESHOLD); |
994 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 1009 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
995 } | 1010 } |
996 | 1011 |
997 TEST(XFormTest, VerifyBlendForRotationAboutZ) | 1012 TEST(XFormTest, VerifyBlendForRotationAboutZ) |
998 { | 1013 { |
999 Transform from; | 1014 Transform from; |
1000 from.PreconcatRotateAbout(Point3F(0, 0, 1), 0); | 1015 from.RotateAbout(Vector3dF(0, 0, 1), 0); |
1001 | 1016 |
1002 Transform to; | 1017 Transform to; |
1003 | 1018 |
1004 to.PreconcatRotateAbout(Point3F(0, 0, 1), 90); | 1019 to.RotateAbout(Vector3dF(0, 0, 1), 90); |
1005 to.Blend(from, 0); | 1020 to.Blend(from, 0); |
1006 EXPECT_EQ(from, to); | 1021 EXPECT_EQ(from, to); |
1007 | 1022 |
1008 double expectedRotationAngle = 22.5 * M_PI / 180.0; | 1023 double expectedRotationAngle = 22.5 * M_PI / 180.0; |
1009 to = Transform(); | 1024 to = Transform(); |
1010 to.PreconcatRotateAbout(Point3F(0, 0, 1), 90); | 1025 to.RotateAbout(Vector3dF(0, 0, 1), 90); |
1011 to.Blend(from, 0.25); | 1026 to.Blend(from, 0.25); |
1012 EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle), | 1027 EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle), |
1013 -std::sin(expectedRotationAngle), | 1028 -std::sin(expectedRotationAngle), |
1014 0, | 1029 0, |
1015 0, | 1030 0, |
1016 to, | 1031 to, |
1017 ERROR_THRESHOLD); | 1032 ERROR_THRESHOLD); |
1018 EXPECT_ROW2_NEAR(std::sin(expectedRotationAngle), | 1033 EXPECT_ROW2_NEAR(std::sin(expectedRotationAngle), |
1019 std::cos(expectedRotationAngle), | 1034 std::cos(expectedRotationAngle), |
1020 0, | 1035 0, |
1021 0, | 1036 0, |
1022 to, | 1037 to, |
1023 ERROR_THRESHOLD); | 1038 ERROR_THRESHOLD); |
1024 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); | 1039 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); |
1025 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 1040 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
1026 | 1041 |
1027 expectedRotationAngle = 45 * M_PI / 180.0; | 1042 expectedRotationAngle = 45 * M_PI / 180.0; |
1028 to = Transform(); | 1043 to = Transform(); |
1029 to.PreconcatRotateAbout(Point3F(0, 0, 1), 90); | 1044 to.RotateAbout(Vector3dF(0, 0, 1), 90); |
1030 to.Blend(from, 0.5); | 1045 to.Blend(from, 0.5); |
1031 EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle), | 1046 EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle), |
1032 -std::sin(expectedRotationAngle), | 1047 -std::sin(expectedRotationAngle), |
1033 0, | 1048 0, |
1034 0, | 1049 0, |
1035 to, | 1050 to, |
1036 ERROR_THRESHOLD); | 1051 ERROR_THRESHOLD); |
1037 EXPECT_ROW2_NEAR(std::sin(expectedRotationAngle), | 1052 EXPECT_ROW2_NEAR(std::sin(expectedRotationAngle), |
1038 std::cos(expectedRotationAngle), | 1053 std::cos(expectedRotationAngle), |
1039 0, | 1054 0, |
1040 0, | 1055 0, |
1041 to, | 1056 to, |
1042 ERROR_THRESHOLD); | 1057 ERROR_THRESHOLD); |
1043 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); | 1058 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); |
1044 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 1059 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
1045 | 1060 |
1046 to = Transform(); | 1061 to = Transform(); |
1047 to.PreconcatRotateAbout(Point3F(0, 0, 1), 90); | 1062 to.RotateAbout(Vector3dF(0, 0, 1), 90); |
1048 to.Blend(from, 1); | 1063 to.Blend(from, 1); |
1049 EXPECT_ROW1_NEAR(0, -1, 0, 0, to, ERROR_THRESHOLD); | 1064 EXPECT_ROW1_NEAR(0, -1, 0, 0, to, ERROR_THRESHOLD); |
1050 EXPECT_ROW2_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); | 1065 EXPECT_ROW2_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD); |
1051 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); | 1066 EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD); |
1052 EXPECT_ROW4_EQ(0, 0, 0, 1, to); | 1067 EXPECT_ROW4_EQ(0, 0, 0, 1, to); |
1053 } | 1068 } |
1054 | 1069 |
1055 TEST(XFormTest, VerifyBlendForCompositeTransform) | 1070 TEST(XFormTest, VerifyBlendForCompositeTransform) |
1056 { | 1071 { |
1057 // Verify that the.Blending was done with a decomposition in correct order | 1072 // Verify that the.Blending was done with a decomposition in correct order |
1058 // by blending a composite transform. Using matrix x vector notation | 1073 // by blending a composite transform. Using matrix x vector notation |
1059 // (Ax = b, where x is column vector), the ordering should be: | 1074 // (Ax = b, where x is column vector), the ordering should be: |
1060 // perspective * translation * rotation * skew * scale | 1075 // perspective * translation * rotation * skew * scale |
1061 // | 1076 // |
1062 // It is not as important (or meaningful) to check intermediate | 1077 // It is not as important (or meaningful) to check intermediate |
1063 // interpolations; order of operations will be tested well enough by the | 1078 // interpolations; order of operations will be tested well enough by the |
1064 // end cases that are easier to specify. | 1079 // end cases that are easier to specify. |
1065 | 1080 |
1066 Transform from; | 1081 Transform from; |
1067 Transform to; | 1082 Transform to; |
1068 | 1083 |
1069 Transform expectedEndOfAnimation; | 1084 Transform expectedEndOfAnimation; |
1070 expectedEndOfAnimation.PreconcatPerspectiveDepth(1); | 1085 expectedEndOfAnimation.ApplyPerspectiveDepth(1); |
1071 expectedEndOfAnimation.PreconcatTranslate3d(10, 20, 30); | 1086 expectedEndOfAnimation.Translate3d(10, 20, 30); |
1072 expectedEndOfAnimation.PreconcatRotateAbout(Point3F(0, 0, 1), 25); | 1087 expectedEndOfAnimation.RotateAbout(Vector3dF(0, 0, 1), 25); |
1073 expectedEndOfAnimation.PreconcatSkewY(45); | 1088 expectedEndOfAnimation.SkewY(45); |
1074 expectedEndOfAnimation.PreconcatScale3d(6, 7, 8); | 1089 expectedEndOfAnimation.Scale3d(6, 7, 8); |
1075 | 1090 |
1076 to = expectedEndOfAnimation; | 1091 to = expectedEndOfAnimation; |
1077 to.Blend(from, 0); | 1092 to.Blend(from, 0); |
1078 EXPECT_EQ(from, to); | 1093 EXPECT_EQ(from, to); |
1079 | 1094 |
1080 to = expectedEndOfAnimation; | 1095 to = expectedEndOfAnimation; |
1081 // We short circuit if blend is >= 1, so to check the numerics, we will | 1096 // We short circuit if blend is >= 1, so to check the numerics, we will |
1082 // check that we get close to what we expect when we're nearly done | 1097 // check that we get close to what we expect when we're nearly done |
1083 // interpolating. | 1098 // interpolating. |
1084 to.Blend(from, .99999); | 1099 to.Blend(from, .99999); |
1085 | 1100 |
1086 // Recomposing the matrix results in a normalized matrix, so to verify we | 1101 // Recomposing the matrix results in a normalized matrix, so to verify we |
1087 // need to normalize the expectedEndOfAnimation before comparing elements. | 1102 // need to normalize the expectedEndOfAnimation before comparing elements. |
1088 // Normalizing means dividing everything by expectedEndOfAnimation.m44(). | 1103 // Normalizing means dividing everything by expectedEndOfAnimation.m44(). |
1089 Transform normalizedExpectedEndOfAnimation = expectedEndOfAnimation; | 1104 Transform normalizedExpectedEndOfAnimation = expectedEndOfAnimation; |
1090 Transform normalizationMatrix; | 1105 Transform normalizationMatrix; |
1091 normalizationMatrix.matrix().set( | 1106 normalizationMatrix.matrix().set( |
1092 0, 0, SkDoubleToMScalar(1 / expectedEndOfAnimation.matrix().get(3, 3))); | 1107 0, 0, SkDoubleToMScalar(1 / expectedEndOfAnimation.matrix().get(3, 3))); |
1093 normalizationMatrix.matrix().set( | 1108 normalizationMatrix.matrix().set( |
1094 1, 1, SkDoubleToMScalar(1 / expectedEndOfAnimation.matrix().get(3, 3))); | 1109 1, 1, SkDoubleToMScalar(1 / expectedEndOfAnimation.matrix().get(3, 3))); |
1095 normalizationMatrix.matrix().set( | 1110 normalizationMatrix.matrix().set( |
1096 2, 2, SkDoubleToMScalar(1 / expectedEndOfAnimation.matrix().get(3, 3))); | 1111 2, 2, SkDoubleToMScalar(1 / expectedEndOfAnimation.matrix().get(3, 3))); |
1097 normalizationMatrix.matrix().set( | 1112 normalizationMatrix.matrix().set( |
1098 3, 3, SkDoubleToMScalar(1 / expectedEndOfAnimation.matrix().get(3, 3))); | 1113 3, 3, SkDoubleToMScalar(1 / expectedEndOfAnimation.matrix().get(3, 3))); |
1099 normalizedExpectedEndOfAnimation.PreconcatTransform(normalizationMatrix); | 1114 normalizedExpectedEndOfAnimation.PreconcatTransform(normalizationMatrix); |
1100 | 1115 |
1101 EXPECT_TRUE(MatricesAreNearlyEqual(normalizedExpectedEndOfAnimation, to)); | 1116 EXPECT_TRUE(MatricesAreNearlyEqual(normalizedExpectedEndOfAnimation, to)); |
1102 } | 1117 } |
1103 | 1118 |
1104 TEST(XFormTest, SetScaleZ) | |
1105 { | |
1106 Transform scaled; | |
1107 scaled.SetScaleZ(2); | |
1108 EXPECT_FLOAT_EQ(2, scaled.matrix().get(2, 2)); | |
1109 } | |
1110 | |
1111 TEST(XFormTest, SetTranslateZ) | |
1112 { | |
1113 Transform translated; | |
1114 translated.SetTranslateZ(2); | |
1115 EXPECT_FLOAT_EQ(2, translated.matrix().get(2, 3)); | |
1116 } | |
1117 | |
1118 TEST(XFormTest, DecomposedTransformCtor) | 1119 TEST(XFormTest, DecomposedTransformCtor) |
1119 { | 1120 { |
1120 DecomposedTransform decomp; | 1121 DecomposedTransform decomp; |
1121 for (int i = 0; i < 3; ++i) { | 1122 for (int i = 0; i < 3; ++i) { |
1122 EXPECT_EQ(0.0, decomp.translate[i]); | 1123 EXPECT_EQ(0.0, decomp.translate[i]); |
1123 EXPECT_EQ(1.0, decomp.scale[i]); | 1124 EXPECT_EQ(1.0, decomp.scale[i]); |
1124 EXPECT_EQ(0.0, decomp.skew[i]); | 1125 EXPECT_EQ(0.0, decomp.skew[i]); |
1125 EXPECT_EQ(0.0, decomp.quaternion[i]); | 1126 EXPECT_EQ(0.0, decomp.quaternion[i]); |
1126 EXPECT_EQ(0.0, decomp.perspective[i]); | 1127 EXPECT_EQ(0.0, decomp.perspective[i]); |
1127 } | 1128 } |
1128 EXPECT_EQ(1.0, decomp.quaternion[3]); | 1129 EXPECT_EQ(1.0, decomp.quaternion[3]); |
1129 EXPECT_EQ(1.0, decomp.perspective[3]); | 1130 EXPECT_EQ(1.0, decomp.perspective[3]); |
1130 Transform identity; | 1131 Transform identity; |
1131 Transform composed = ComposeTransform(decomp); | 1132 Transform composed = ComposeTransform(decomp); |
1132 EXPECT_TRUE(MatricesAreNearlyEqual(identity, composed)); | 1133 EXPECT_TRUE(MatricesAreNearlyEqual(identity, composed)); |
1133 } | 1134 } |
1134 | 1135 |
| 1136 TEST(XFormTest, FactorTRS) { |
| 1137 for (int degrees = 0; degrees < 180; ++degrees) { |
| 1138 // build a transformation matrix. |
| 1139 gfx::Transform transform; |
| 1140 transform.Translate(degrees * 2, -degrees * 3); |
| 1141 transform.Rotate(degrees); |
| 1142 transform.Scale(degrees + 1, 2 * degrees + 1); |
| 1143 |
| 1144 // factor the matrix |
| 1145 DecomposedTransform decomp; |
| 1146 bool success = DecomposeTransform(&decomp, transform); |
| 1147 EXPECT_TRUE(success); |
| 1148 EXPECT_FLOAT_EQ(decomp.translate[0], degrees * 2); |
| 1149 EXPECT_FLOAT_EQ(decomp.translate[1], -degrees * 3); |
| 1150 double rotation = std::acos(decomp.quaternion[3]) * 360.0 / M_PI; |
| 1151 while (rotation < 0.0) |
| 1152 rotation += 360.0; |
| 1153 while (rotation > 360.0) |
| 1154 rotation -= 360.0; |
| 1155 EXPECT_FLOAT_EQ(rotation, degrees); |
| 1156 EXPECT_FLOAT_EQ(decomp.scale[0], degrees + 1); |
| 1157 EXPECT_FLOAT_EQ(decomp.scale[1], 2 * degrees + 1); |
| 1158 } |
| 1159 } |
| 1160 |
1135 } // namespace | 1161 } // namespace |
1136 | 1162 |
1137 } // namespace gfx | 1163 } // namespace gfx |
OLD | NEW |