Chromium Code Reviews| 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 |