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(polygon_b, vertices_b, | |
376 gfx::Vector3dF(0.707107, -0.707107, 0.000000), 1); | |
377 | |
378 // These are well formed, convex polygons. | |
379 #if !defined(OS_WIN) | |
flackr
2016/10/13 18:42:26
I agree this ensures that the polygons are indeed
flackr
2016/10/13 18:49:30
Nevermind, thanks for pointing out we declare Draw
| |
380 EXPECT_EQ(polygon_a->IsPlanarForTesting(), true); | |
381 EXPECT_EQ(polygon_a->IsConvexForTesting(), true); | |
382 EXPECT_EQ(polygon_b->IsPlanarForTesting(), true); | |
383 EXPECT_EQ(polygon_b->IsConvexForTesting(), true); | |
384 #endif | |
385 | |
386 std::unique_ptr<DrawPolygon> front_polygon; | |
387 std::unique_ptr<DrawPolygon> back_polygon; | |
388 bool is_coplanar; | |
389 | |
390 polygon_a->SplitPolygon(std::move(polygon_b), &front_polygon, &back_polygon, | |
391 &is_coplanar); | |
392 | |
393 EXPECT_FALSE(is_coplanar); | |
394 EXPECT_TRUE(front_polygon != nullptr); | |
395 EXPECT_TRUE(back_polygon != nullptr); | |
396 } | |
397 | |
320 // One quad intersects another and becomes two pieces. | 398 // One quad intersects another and becomes two pieces. |
321 TEST(DrawPolygonSplitTest, BasicSplit) { | 399 TEST(DrawPolygonSplitTest, BasicSplit) { |
322 std::vector<gfx::Point3F> vertices_a; | 400 std::vector<gfx::Point3F> vertices_a; |
323 vertices_a.push_back(gfx::Point3F(0.0f, 10.0f, 0.0f)); | 401 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)); | 402 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)); | 403 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)); | 404 vertices_a.push_back(gfx::Point3F(10.0f, 10.0f, 0.0f)); |
327 std::vector<gfx::Point3F> vertices_b; | 405 std::vector<gfx::Point3F> vertices_b; |
328 vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, -5.0f)); | 406 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)); | 407 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)); | 477 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)); | 478 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)); | 479 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)); | 480 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)); | 481 test_points_b.push_back(gfx::Point3F(10.0f, 0.0f, 9.0f)); |
404 | 482 |
405 ValidatePointsWithinDeltaOf(*(front_polygon.get()), test_points_a, 1e-6f); | 483 ValidatePointsWithinDeltaOf(*(front_polygon.get()), test_points_a, 1e-6f); |
406 ValidatePointsWithinDeltaOf(*(back_polygon.get()), test_points_b, 1e-6f); | 484 ValidatePointsWithinDeltaOf(*(back_polygon.get()), test_points_b, 1e-6f); |
407 } | 485 } |
408 | 486 |
487 // In this test we cut the corner of a quad so that it creates a triangle and | |
488 // a pentagon as a result, and then cut the pentagon. | |
489 TEST(DrawPolygonSplitTest, DoubleSplit) { | |
490 std::vector<gfx::Point3F> vertices_a; | |
491 vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f)); | |
492 vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 10.0f)); | |
493 vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 10.0f)); | |
494 vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f)); | |
495 std::vector<gfx::Point3F> vertices_b; | |
496 vertices_b.push_back(gfx::Point3F(2.0f, 5.0f, 1.0f)); | |
497 vertices_b.push_back(gfx::Point3F(2.0f, -5.0f, 1.0f)); | |
498 vertices_b.push_back(gfx::Point3F(-1.0f, -5.0f, -2.0f)); | |
499 vertices_b.push_back(gfx::Point3F(-1.0f, 5.0f, -2.0f)); | |
500 | |
501 CREATE_NEW_DRAW_POLYGON_PTR(polygon_a, vertices_a, | |
502 gfx::Vector3dF(0.0f, 1.0f, 0.0f), 0); | |
503 CREATE_NEW_DRAW_POLYGON_PTR(polygon_b, vertices_b, | |
504 gfx::Vector3dF(sqrt(2) / 2, 0.0f, -sqrt(2) / 2), | |
505 1); | |
506 | |
507 std::unique_ptr<DrawPolygon> front_polygon; | |
508 std::unique_ptr<DrawPolygon> back_polygon; | |
509 bool is_coplanar; | |
510 | |
511 polygon_b->SplitPolygon(std::move(polygon_a), &front_polygon, &back_polygon, | |
512 &is_coplanar); | |
513 EXPECT_FALSE(is_coplanar); | |
514 EXPECT_TRUE(front_polygon != nullptr); | |
515 EXPECT_TRUE(back_polygon != nullptr); | |
516 | |
517 EXPECT_EQ(3u, front_polygon->points().size()); | |
518 EXPECT_EQ(5u, back_polygon->points().size()); | |
519 | |
520 std::vector<gfx::Point3F> vertices_c; | |
521 vertices_c.push_back(gfx::Point3F(0.0f, 0.0f, 10.0f)); | |
522 vertices_c.push_back(gfx::Point3F(1.0f, -0.05f, 0.0f)); | |
523 vertices_c.push_back(gfx::Point3F(10.0f, 0.05f, 9.0f)); | |
524 | |
525 CREATE_NEW_DRAW_POLYGON_PTR(polygon_c, vertices_c, | |
526 gfx::Vector3dF(0.0055f, -0.999f, 0.0055f), 0); | |
527 | |
528 std::unique_ptr<DrawPolygon> second_front_polygon; | |
529 std::unique_ptr<DrawPolygon> second_back_polygon; | |
530 | |
531 polygon_c->SplitPolygon(std::move(back_polygon), &second_front_polygon, | |
532 &second_back_polygon, &is_coplanar); | |
533 EXPECT_FALSE(is_coplanar); | |
534 EXPECT_TRUE(second_front_polygon != nullptr); | |
535 EXPECT_TRUE(second_back_polygon != nullptr); | |
536 | |
537 EXPECT_EQ(3u, second_front_polygon->points().size()); | |
538 EXPECT_EQ(3u, second_back_polygon->points().size()); | |
539 } | |
540 | |
409 TEST(DrawPolygonTransformTest, TransformNormal) { | 541 TEST(DrawPolygonTransformTest, TransformNormal) { |
410 std::vector<gfx::Point3F> vertices_a; | 542 std::vector<gfx::Point3F> vertices_a; |
411 vertices_a.push_back(gfx::Point3F(1.0f, 0.0f, 1.0f)); | 543 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)); | 544 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)); | 545 vertices_a.push_back(gfx::Point3F(0.0f, 1.0f, 0.0f)); |
414 CREATE_NEW_DRAW_POLYGON(polygon_a, vertices_a, | 546 CREATE_NEW_DRAW_POLYGON(polygon_a, vertices_a, |
415 gfx::Vector3dF(sqrt(2) / 2, 0.0f, -sqrt(2) / 2), 0); | 547 gfx::Vector3dF(sqrt(2) / 2, 0.0f, -sqrt(2) / 2), 0); |
416 EXPECT_NORMAL(polygon_a, sqrt(2) / 2, 0.0f, -sqrt(2) / 2); | 548 EXPECT_NORMAL(polygon_a, sqrt(2) / 2, 0.0f, -sqrt(2) / 2); |
417 | 549 |
418 gfx::Transform transform; | 550 gfx::Transform transform; |
419 transform.RotateAboutYAxis(45.0f); | 551 transform.RotateAboutYAxis(45.0f); |
420 // This would transform the vertices as well, but we are transforming a | 552 // This would transform the vertices as well, but we are transforming a |
421 // DrawPolygon with 0 vertices just to make sure our normal transformation | 553 // DrawPolygon with 0 vertices just to make sure our normal transformation |
422 // using the inverse tranpose matrix gives us the right result. | 554 // using the inverse tranpose matrix gives us the right result. |
423 polygon_a.TransformToScreenSpace(transform); | 555 polygon_a.TransformToScreenSpace(transform); |
424 | 556 |
425 // Note: We use EXPECT_FLOAT_WITHIN_EPSILON instead of EXPECT_FLOAT_EQUAL here | 557 // 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 | 558 // because some architectures (e.g., Arm64) employ a fused multiply-add |
427 // instruction which causes rounding asymmetry and reduces precision. | 559 // instruction which causes rounding asymmetry and reduces precision. |
428 // http://crbug.com/401117. | 560 // http://crbug.com/401117. |
429 EXPECT_NORMAL(polygon_a, 0.0f, 0.0f, -1.0f); | 561 EXPECT_NORMAL(polygon_a, 0.0f, 0.0f, -1.0f); |
430 } | 562 } |
431 | 563 |
432 } // namespace | 564 } // namespace |
433 } // namespace cc | 565 } // namespace cc |
OLD | NEW |