OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 // We would like to use M_PI on windows too. | 5 // We would like to use M_PI on windows too. |
6 #ifdef _WIN32 | 6 #ifdef _WIN32 |
7 #define _USE_MATH_DEFINES | 7 #define _USE_MATH_DEFINES |
8 #endif | 8 #endif |
9 | 9 |
10 #include <stddef.h> | 10 #include <stddef.h> |
11 | 11 |
12 #include <limits> | 12 #include <limits> |
13 #include <vector> | 13 #include <vector> |
14 | 14 |
15 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
16 #include "cc/output/bsp_compare_result.h" | 16 #include "cc/output/bsp_compare_result.h" |
17 #include "cc/quads/draw_polygon.h" | 17 #include "cc/quads/draw_polygon.h" |
18 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
19 #include "ui/gfx/transform.h" | 19 #include "ui/gfx/transform.h" |
20 | 20 |
21 namespace cc { | 21 namespace cc { |
22 | 22 |
23 #if !defined(OS_WIN) | 23 #if !defined(OS_WIN) |
24 void DrawPolygon::RecomputeNormalForTesting() { | 24 void DrawPolygon::RecomputeNormalForTesting() { |
25 ConstructNormal(); | 25 ConstructNormal(); |
26 } | 26 } |
27 | |
28 static int sign(float v) { | |
29 static const float epsilon = 0.00001f; | |
30 | |
31 if (v > epsilon) | |
32 return 1; | |
33 if (v < -epsilon) | |
34 return -1; | |
35 return 0; | |
36 } | |
37 | |
38 bool DrawPolygon::IsPlanarForTesting() const { | |
39 static const float epsilon = 0.00001f; | |
40 for (size_t i = 1; i < points_.size(); i++) { | |
41 if (gfx::DotProduct(points_[i] - points_[0], normal_) > epsilon) | |
42 return false; | |
43 } | |
44 return true; | |
45 } | |
46 | |
47 bool DrawPolygon::IsConvexForTesting() const { | |
48 if (points_.size() < 3) | |
49 return true; | |
50 | |
51 gfx::Vector3dF prev = | |
52 points_[points_.size() - 1] - points_[points_.size() - 2]; | |
53 gfx::Vector3dF next = points_[0] - points_[points_.size() - 1]; | |
54 int ccw = sign(gfx::DotProduct(CrossProduct(prev, next), normal_)); | |
55 for (size_t i = 1; i < points_.size(); i++) { | |
56 prev = next; | |
57 next = points_[i] - points_[i - 1]; | |
58 int next_sign = sign(gfx::DotProduct(CrossProduct(prev, next), normal_)); | |
59 if (ccw == 0) | |
60 ccw = next_sign; | |
61 if (next_sign != 0 && next_sign != ccw) | |
62 return false; | |
63 } | |
64 return true; | |
65 } | |
27 #endif | 66 #endif |
28 | 67 |
29 namespace { | 68 namespace { |
30 | 69 |
31 #define CREATE_NEW_DRAW_POLYGON(name, points_vector, normal, polygon_id) \ | 70 #define CREATE_NEW_DRAW_POLYGON(name, points_vector, normal, polygon_id) \ |
32 DrawPolygon name(NULL, points_vector, normal, polygon_id) | 71 DrawPolygon name(NULL, points_vector, normal, polygon_id) |
33 | 72 |
34 #define CREATE_NEW_DRAW_POLYGON_PTR(name, points_vector, normal, polygon_id) \ | 73 #define CREATE_NEW_DRAW_POLYGON_PTR(name, points_vector, normal, polygon_id) \ |
35 std::unique_ptr<DrawPolygon> name(base::MakeUnique<DrawPolygon>( \ | 74 std::unique_ptr<DrawPolygon> name(base::MakeUnique<DrawPolygon>( \ |
36 nullptr, points_vector, normal, polygon_id)) | 75 nullptr, points_vector, normal, polygon_id)) |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
310 vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, 0.0f)); | 349 vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, 0.0f)); |
311 | 350 |
312 CREATE_NEW_DRAW_POLYGON(polygon_a, vertices_a, | 351 CREATE_NEW_DRAW_POLYGON(polygon_a, vertices_a, |
313 gfx::Vector3dF(0.0f, 0.0f, 1.0f), 0); | 352 gfx::Vector3dF(0.0f, 0.0f, 1.0f), 0); |
314 CREATE_NEW_DRAW_POLYGON(polygon_b, vertices_b, | 353 CREATE_NEW_DRAW_POLYGON(polygon_b, vertices_b, |
315 gfx::Vector3dF(-1.0f, 0.0f, 0.0f), 1); | 354 gfx::Vector3dF(-1.0f, 0.0f, 0.0f), 1); |
316 | 355 |
317 EXPECT_EQ(BSP_BACK, SideCompare(polygon_b, polygon_a)); | 356 EXPECT_EQ(BSP_BACK, SideCompare(polygon_b, polygon_a)); |
318 } | 357 } |
319 | 358 |
359 // One quad intersects a pent with an occluded side. | |
360 TEST(DrawPolygonSplitTest, SlimClip) { | |
361 std::vector<gfx::Point3F> vertices_a; | |
362 vertices_a.push_back(gfx::Point3F(0.0f, 10.0f, 0.0f)); | |
363 vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f)); | |
364 vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f)); | |
365 vertices_a.push_back(gfx::Point3F(10.0f, 10.0f, 0.0f)); | |
366 std::vector<gfx::Point3F> vertices_b; | |
367 vertices_b.push_back(gfx::Point3F(9.0f, 9.0f, 5.000f)); | |
368 vertices_b.push_back(gfx::Point3F(1.0f, 1.0f, 0.001f)); | |
369 vertices_b.push_back(gfx::Point3F(1.0f, 1.0f, 0.000f)); | |
370 vertices_b.push_back(gfx::Point3F(1.002f, 1.002f, -0.005f)); | |
371 vertices_b.push_back(gfx::Point3F(9.0f, 9.0f, -4.000f)); | |
372 | |
373 CREATE_NEW_DRAW_POLYGON_PTR(polygon_a, vertices_a, | |
374 gfx::Vector3dF(0.0f, 0.0f, 1.0f), 0); | |
375 CREATE_NEW_DRAW_POLYGON_PTR( | |
376 polygon_b, vertices_b, | |
377 gfx::Vector3dF(sqrt(2) / 2, -sqrt(2) / 2, 0.000000), 1); | |
378 | |
379 // These are well formed, convex polygons. | |
380 #if !defined(OS_WIN) | |
enne (OOO)
2016/10/14 18:04:59
These are well-formed polygons, except on Windows.
flackr
2016/10/14 18:12:32
They're well-formed on Windows too, but defining D
| |
381 EXPECT_TRUE(polygon_a->IsPlanarForTesting()); | |
382 EXPECT_TRUE(polygon_a->IsConvexForTesting()); | |
383 EXPECT_TRUE(polygon_b->IsPlanarForTesting()); | |
384 EXPECT_TRUE(polygon_b->IsConvexForTesting()); | |
385 #endif | |
386 | |
387 std::unique_ptr<DrawPolygon> front_polygon; | |
388 std::unique_ptr<DrawPolygon> back_polygon; | |
389 bool is_coplanar; | |
390 | |
391 polygon_a->SplitPolygon(std::move(polygon_b), &front_polygon, &back_polygon, | |
392 &is_coplanar); | |
393 | |
394 EXPECT_FALSE(is_coplanar); | |
395 EXPECT_TRUE(front_polygon != nullptr); | |
396 EXPECT_TRUE(back_polygon != nullptr); | |
397 } | |
398 | |
320 // One quad intersects another and becomes two pieces. | 399 // One quad intersects another and becomes two pieces. |
321 TEST(DrawPolygonSplitTest, BasicSplit) { | 400 TEST(DrawPolygonSplitTest, BasicSplit) { |
322 std::vector<gfx::Point3F> vertices_a; | 401 std::vector<gfx::Point3F> vertices_a; |
323 vertices_a.push_back(gfx::Point3F(0.0f, 10.0f, 0.0f)); | 402 vertices_a.push_back(gfx::Point3F(0.0f, 10.0f, 0.0f)); |
324 vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f)); | 403 vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f)); |
325 vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f)); | 404 vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f)); |
326 vertices_a.push_back(gfx::Point3F(10.0f, 10.0f, 0.0f)); | 405 vertices_a.push_back(gfx::Point3F(10.0f, 10.0f, 0.0f)); |
327 std::vector<gfx::Point3F> vertices_b; | 406 std::vector<gfx::Point3F> vertices_b; |
328 vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, -5.0f)); | 407 vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, -5.0f)); |
329 vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, -5.0f)); | 408 vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, -5.0f)); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
399 test_points_b.push_back(gfx::Point3F(1.0f, 0.0f, 0.0f)); | 478 test_points_b.push_back(gfx::Point3F(1.0f, 0.0f, 0.0f)); |
400 test_points_b.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f)); | 479 test_points_b.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f)); |
401 test_points_b.push_back(gfx::Point3F(0.0f, 0.0f, 10.0f)); | 480 test_points_b.push_back(gfx::Point3F(0.0f, 0.0f, 10.0f)); |
402 test_points_b.push_back(gfx::Point3F(10.0f, 0.0f, 10.0f)); | 481 test_points_b.push_back(gfx::Point3F(10.0f, 0.0f, 10.0f)); |
403 test_points_b.push_back(gfx::Point3F(10.0f, 0.0f, 9.0f)); | 482 test_points_b.push_back(gfx::Point3F(10.0f, 0.0f, 9.0f)); |
404 | 483 |
405 ValidatePointsWithinDeltaOf(*(front_polygon.get()), test_points_a, 1e-6f); | 484 ValidatePointsWithinDeltaOf(*(front_polygon.get()), test_points_a, 1e-6f); |
406 ValidatePointsWithinDeltaOf(*(back_polygon.get()), test_points_b, 1e-6f); | 485 ValidatePointsWithinDeltaOf(*(back_polygon.get()), test_points_b, 1e-6f); |
407 } | 486 } |
408 | 487 |
488 // In this test we cut the corner of a quad so that it creates a triangle and | |
489 // a pentagon as a result, and then cut the pentagon. | |
490 TEST(DrawPolygonSplitTest, DoubleSplit) { | |
491 std::vector<gfx::Point3F> vertices_a; | |
492 vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f)); | |
493 vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 10.0f)); | |
494 vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 10.0f)); | |
495 vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f)); | |
496 std::vector<gfx::Point3F> vertices_b; | |
497 vertices_b.push_back(gfx::Point3F(2.0f, 5.0f, 1.0f)); | |
498 vertices_b.push_back(gfx::Point3F(2.0f, -5.0f, 1.0f)); | |
499 vertices_b.push_back(gfx::Point3F(-1.0f, -5.0f, -2.0f)); | |
500 vertices_b.push_back(gfx::Point3F(-1.0f, 5.0f, -2.0f)); | |
501 | |
502 CREATE_NEW_DRAW_POLYGON_PTR(polygon_a, vertices_a, | |
503 gfx::Vector3dF(0.0f, 1.0f, 0.0f), 0); | |
504 CREATE_NEW_DRAW_POLYGON_PTR(polygon_b, vertices_b, | |
505 gfx::Vector3dF(sqrt(2) / 2, 0.0f, -sqrt(2) / 2), | |
506 1); | |
507 | |
508 std::unique_ptr<DrawPolygon> front_polygon; | |
509 std::unique_ptr<DrawPolygon> back_polygon; | |
510 bool is_coplanar; | |
511 | |
512 polygon_b->SplitPolygon(std::move(polygon_a), &front_polygon, &back_polygon, | |
513 &is_coplanar); | |
514 EXPECT_FALSE(is_coplanar); | |
515 EXPECT_TRUE(front_polygon != nullptr); | |
516 EXPECT_TRUE(back_polygon != nullptr); | |
517 | |
518 EXPECT_EQ(3u, front_polygon->points().size()); | |
519 EXPECT_EQ(5u, back_polygon->points().size()); | |
520 | |
521 std::vector<gfx::Point3F> vertices_c; | |
522 vertices_c.push_back(gfx::Point3F(0.0f, 0.0f, 10.0f)); | |
523 vertices_c.push_back(gfx::Point3F(1.0f, -0.05f, 0.0f)); | |
524 vertices_c.push_back(gfx::Point3F(10.0f, 0.05f, 9.0f)); | |
525 | |
526 CREATE_NEW_DRAW_POLYGON_PTR(polygon_c, vertices_c, | |
527 gfx::Vector3dF(0.0055f, -0.999f, 0.0055f), 0); | |
528 | |
529 std::unique_ptr<DrawPolygon> second_front_polygon; | |
530 std::unique_ptr<DrawPolygon> second_back_polygon; | |
531 | |
532 polygon_c->SplitPolygon(std::move(back_polygon), &second_front_polygon, | |
533 &second_back_polygon, &is_coplanar); | |
534 EXPECT_FALSE(is_coplanar); | |
535 EXPECT_TRUE(second_front_polygon != nullptr); | |
536 EXPECT_TRUE(second_back_polygon != nullptr); | |
537 | |
538 EXPECT_EQ(3u, second_front_polygon->points().size()); | |
539 EXPECT_EQ(3u, second_back_polygon->points().size()); | |
540 } | |
541 | |
409 TEST(DrawPolygonTransformTest, TransformNormal) { | 542 TEST(DrawPolygonTransformTest, TransformNormal) { |
410 std::vector<gfx::Point3F> vertices_a; | 543 std::vector<gfx::Point3F> vertices_a; |
411 vertices_a.push_back(gfx::Point3F(1.0f, 0.0f, 1.0f)); | 544 vertices_a.push_back(gfx::Point3F(1.0f, 0.0f, 1.0f)); |
412 vertices_a.push_back(gfx::Point3F(-1.0f, 0.0f, -1.0f)); | 545 vertices_a.push_back(gfx::Point3F(-1.0f, 0.0f, -1.0f)); |
413 vertices_a.push_back(gfx::Point3F(0.0f, 1.0f, 0.0f)); | 546 vertices_a.push_back(gfx::Point3F(0.0f, 1.0f, 0.0f)); |
414 CREATE_NEW_DRAW_POLYGON(polygon_a, vertices_a, | 547 CREATE_NEW_DRAW_POLYGON(polygon_a, vertices_a, |
415 gfx::Vector3dF(sqrt(2) / 2, 0.0f, -sqrt(2) / 2), 0); | 548 gfx::Vector3dF(sqrt(2) / 2, 0.0f, -sqrt(2) / 2), 0); |
416 EXPECT_NORMAL(polygon_a, sqrt(2) / 2, 0.0f, -sqrt(2) / 2); | 549 EXPECT_NORMAL(polygon_a, sqrt(2) / 2, 0.0f, -sqrt(2) / 2); |
417 | 550 |
418 gfx::Transform transform; | 551 gfx::Transform transform; |
419 transform.RotateAboutYAxis(45.0f); | 552 transform.RotateAboutYAxis(45.0f); |
420 // This would transform the vertices as well, but we are transforming a | 553 // This would transform the vertices as well, but we are transforming a |
421 // DrawPolygon with 0 vertices just to make sure our normal transformation | 554 // DrawPolygon with 0 vertices just to make sure our normal transformation |
422 // using the inverse tranpose matrix gives us the right result. | 555 // using the inverse tranpose matrix gives us the right result. |
423 polygon_a.TransformToScreenSpace(transform); | 556 polygon_a.TransformToScreenSpace(transform); |
424 | 557 |
425 // Note: We use EXPECT_FLOAT_WITHIN_EPSILON instead of EXPECT_FLOAT_EQUAL here | 558 // Note: We use EXPECT_FLOAT_WITHIN_EPSILON instead of EXPECT_FLOAT_EQUAL here |
426 // because some architectures (e.g., Arm64) employ a fused multiply-add | 559 // because some architectures (e.g., Arm64) employ a fused multiply-add |
427 // instruction which causes rounding asymmetry and reduces precision. | 560 // instruction which causes rounding asymmetry and reduces precision. |
428 // http://crbug.com/401117. | 561 // http://crbug.com/401117. |
429 EXPECT_NORMAL(polygon_a, 0.0f, 0.0f, -1.0f); | 562 EXPECT_NORMAL(polygon_a, 0.0f, 0.0f, -1.0f); |
430 } | 563 } |
431 | 564 |
432 } // namespace | 565 } // namespace |
433 } // namespace cc | 566 } // namespace cc |
OLD | NEW |