| 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 #endif | 27 #endif |
| 28 | 28 |
| 29 static int sign(float v) { |
| 30 static const float epsilon = 0.00001f; |
| 31 |
| 32 if (v > epsilon) |
| 33 return 1; |
| 34 if (v < -epsilon) |
| 35 return -1; |
| 36 return 0; |
| 37 } |
| 38 |
| 39 bool IsPlanarForTesting(const DrawPolygon& p) { |
| 40 static const float epsilon = 0.00001f; |
| 41 for (size_t i = 1; i < p.points_.size(); i++) { |
| 42 if (gfx::DotProduct(p.points_[i] - p.points_[0], p.normal_) > epsilon) |
| 43 return false; |
| 44 } |
| 45 return true; |
| 46 } |
| 47 |
| 48 bool IsConvexForTesting(const DrawPolygon& p) { |
| 49 if (p.points_.size() < 3) |
| 50 return true; |
| 51 |
| 52 gfx::Vector3dF prev = |
| 53 p.points_[p.points_.size() - 1] - p.points_[p.points_.size() - 2]; |
| 54 gfx::Vector3dF next = p.points_[0] - p.points_[p.points_.size() - 1]; |
| 55 int ccw = sign(gfx::DotProduct(CrossProduct(prev, next), p.normal_)); |
| 56 for (size_t i = 1; i < p.points_.size(); i++) { |
| 57 prev = next; |
| 58 next = p.points_[i] - p.points_[i - 1]; |
| 59 int next_sign = sign(gfx::DotProduct(CrossProduct(prev, next), p.normal_)); |
| 60 if (ccw == 0) |
| 61 ccw = next_sign; |
| 62 if (next_sign != 0 && next_sign != ccw) |
| 63 return false; |
| 64 } |
| 65 return true; |
| 66 } |
| 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)) |
| 37 | 76 |
| 38 #define CREATE_TEST_DRAW_FORWARD_POLYGON(name, points_vector, id) \ | 77 #define CREATE_TEST_DRAW_FORWARD_POLYGON(name, points_vector, id) \ |
| (...skipping 271 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 EXPECT_TRUE(IsPlanarForTesting(*(polygon_a.get()))); |
| 381 EXPECT_TRUE(IsConvexForTesting(*(polygon_a.get()))); |
| 382 EXPECT_TRUE(IsPlanarForTesting(*(polygon_b.get()))); |
| 383 EXPECT_TRUE(IsConvexForTesting(*(polygon_b.get()))); |
| 384 |
| 385 std::unique_ptr<DrawPolygon> front_polygon; |
| 386 std::unique_ptr<DrawPolygon> back_polygon; |
| 387 bool is_coplanar; |
| 388 |
| 389 polygon_a->SplitPolygon(std::move(polygon_b), &front_polygon, &back_polygon, |
| 390 &is_coplanar); |
| 391 |
| 392 EXPECT_FALSE(is_coplanar); |
| 393 EXPECT_TRUE(front_polygon != nullptr); |
| 394 EXPECT_TRUE(back_polygon != nullptr); |
| 395 } |
| 396 |
| 320 // One quad intersects another and becomes two pieces. | 397 // One quad intersects another and becomes two pieces. |
| 321 TEST(DrawPolygonSplitTest, BasicSplit) { | 398 TEST(DrawPolygonSplitTest, BasicSplit) { |
| 322 std::vector<gfx::Point3F> vertices_a; | 399 std::vector<gfx::Point3F> vertices_a; |
| 323 vertices_a.push_back(gfx::Point3F(0.0f, 10.0f, 0.0f)); | 400 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)); | 401 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)); | 402 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)); | 403 vertices_a.push_back(gfx::Point3F(10.0f, 10.0f, 0.0f)); |
| 327 std::vector<gfx::Point3F> vertices_b; | 404 std::vector<gfx::Point3F> vertices_b; |
| 328 vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, -5.0f)); | 405 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)); | 406 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)); | 476 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)); | 477 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)); | 478 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)); | 479 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)); | 480 test_points_b.push_back(gfx::Point3F(10.0f, 0.0f, 9.0f)); |
| 404 | 481 |
| 405 ValidatePointsWithinDeltaOf(*(front_polygon.get()), test_points_a, 1e-6f); | 482 ValidatePointsWithinDeltaOf(*(front_polygon.get()), test_points_a, 1e-6f); |
| 406 ValidatePointsWithinDeltaOf(*(back_polygon.get()), test_points_b, 1e-6f); | 483 ValidatePointsWithinDeltaOf(*(back_polygon.get()), test_points_b, 1e-6f); |
| 407 } | 484 } |
| 408 | 485 |
| 486 // In this test we cut the corner of a quad so that it creates a triangle and |
| 487 // a pentagon as a result, and then cut the pentagon. |
| 488 TEST(DrawPolygonSplitTest, DoubleSplit) { |
| 489 std::vector<gfx::Point3F> vertices_a; |
| 490 vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f)); |
| 491 vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 10.0f)); |
| 492 vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 10.0f)); |
| 493 vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f)); |
| 494 std::vector<gfx::Point3F> vertices_b; |
| 495 vertices_b.push_back(gfx::Point3F(2.0f, 5.0f, 1.0f)); |
| 496 vertices_b.push_back(gfx::Point3F(2.0f, -5.0f, 1.0f)); |
| 497 vertices_b.push_back(gfx::Point3F(-1.0f, -5.0f, -2.0f)); |
| 498 vertices_b.push_back(gfx::Point3F(-1.0f, 5.0f, -2.0f)); |
| 499 |
| 500 CREATE_NEW_DRAW_POLYGON_PTR(polygon_a, vertices_a, |
| 501 gfx::Vector3dF(0.0f, 1.0f, 0.0f), 0); |
| 502 CREATE_NEW_DRAW_POLYGON_PTR(polygon_b, vertices_b, |
| 503 gfx::Vector3dF(sqrt(2) / 2, 0.0f, -sqrt(2) / 2), |
| 504 1); |
| 505 |
| 506 std::unique_ptr<DrawPolygon> front_polygon; |
| 507 std::unique_ptr<DrawPolygon> back_polygon; |
| 508 bool is_coplanar; |
| 509 |
| 510 polygon_b->SplitPolygon(std::move(polygon_a), &front_polygon, &back_polygon, |
| 511 &is_coplanar); |
| 512 EXPECT_FALSE(is_coplanar); |
| 513 EXPECT_TRUE(front_polygon != nullptr); |
| 514 EXPECT_TRUE(back_polygon != nullptr); |
| 515 |
| 516 EXPECT_EQ(3u, front_polygon->points().size()); |
| 517 EXPECT_EQ(5u, back_polygon->points().size()); |
| 518 |
| 519 std::vector<gfx::Point3F> vertices_c; |
| 520 vertices_c.push_back(gfx::Point3F(0.0f, 0.0f, 10.0f)); |
| 521 vertices_c.push_back(gfx::Point3F(1.0f, -0.05f, 0.0f)); |
| 522 vertices_c.push_back(gfx::Point3F(10.0f, 0.05f, 9.0f)); |
| 523 |
| 524 CREATE_NEW_DRAW_POLYGON_PTR(polygon_c, vertices_c, |
| 525 gfx::Vector3dF(0.0055f, -0.999f, 0.0055f), 0); |
| 526 |
| 527 std::unique_ptr<DrawPolygon> second_front_polygon; |
| 528 std::unique_ptr<DrawPolygon> second_back_polygon; |
| 529 |
| 530 polygon_c->SplitPolygon(std::move(back_polygon), &second_front_polygon, |
| 531 &second_back_polygon, &is_coplanar); |
| 532 EXPECT_FALSE(is_coplanar); |
| 533 EXPECT_TRUE(second_front_polygon != nullptr); |
| 534 EXPECT_TRUE(second_back_polygon != nullptr); |
| 535 |
| 536 EXPECT_EQ(3u, second_front_polygon->points().size()); |
| 537 EXPECT_EQ(3u, second_back_polygon->points().size()); |
| 538 } |
| 539 |
| 409 TEST(DrawPolygonTransformTest, TransformNormal) { | 540 TEST(DrawPolygonTransformTest, TransformNormal) { |
| 410 std::vector<gfx::Point3F> vertices_a; | 541 std::vector<gfx::Point3F> vertices_a; |
| 411 vertices_a.push_back(gfx::Point3F(1.0f, 0.0f, 1.0f)); | 542 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)); | 543 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)); | 544 vertices_a.push_back(gfx::Point3F(0.0f, 1.0f, 0.0f)); |
| 414 CREATE_NEW_DRAW_POLYGON(polygon_a, vertices_a, | 545 CREATE_NEW_DRAW_POLYGON(polygon_a, vertices_a, |
| 415 gfx::Vector3dF(sqrt(2) / 2, 0.0f, -sqrt(2) / 2), 0); | 546 gfx::Vector3dF(sqrt(2) / 2, 0.0f, -sqrt(2) / 2), 0); |
| 416 EXPECT_NORMAL(polygon_a, sqrt(2) / 2, 0.0f, -sqrt(2) / 2); | 547 EXPECT_NORMAL(polygon_a, sqrt(2) / 2, 0.0f, -sqrt(2) / 2); |
| 417 | 548 |
| 418 gfx::Transform transform; | 549 gfx::Transform transform; |
| 419 transform.RotateAboutYAxis(45.0f); | 550 transform.RotateAboutYAxis(45.0f); |
| 420 // This would transform the vertices as well, but we are transforming a | 551 // This would transform the vertices as well, but we are transforming a |
| 421 // DrawPolygon with 0 vertices just to make sure our normal transformation | 552 // DrawPolygon with 0 vertices just to make sure our normal transformation |
| 422 // using the inverse tranpose matrix gives us the right result. | 553 // using the inverse tranpose matrix gives us the right result. |
| 423 polygon_a.TransformToScreenSpace(transform); | 554 polygon_a.TransformToScreenSpace(transform); |
| 424 | 555 |
| 425 // Note: We use EXPECT_FLOAT_WITHIN_EPSILON instead of EXPECT_FLOAT_EQUAL here | 556 // 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 | 557 // because some architectures (e.g., Arm64) employ a fused multiply-add |
| 427 // instruction which causes rounding asymmetry and reduces precision. | 558 // instruction which causes rounding asymmetry and reduces precision. |
| 428 // http://crbug.com/401117. | 559 // http://crbug.com/401117. |
| 429 EXPECT_NORMAL(polygon_a, 0.0f, 0.0f, -1.0f); | 560 EXPECT_NORMAL(polygon_a, 0.0f, 0.0f, -1.0f); |
| 430 } | 561 } |
| 431 | 562 |
| 432 } // namespace | 563 } // namespace |
| 433 } // namespace cc | 564 } // namespace cc |
| OLD | NEW |