Home | History | Annotate | Download | only in quads
      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
      3 // found in the LICENSE file.
      4 
      5 #include <limits>
      6 #include <vector>
      7 
      8 #include "cc/output/bsp_compare_result.h"
      9 #include "cc/quads/draw_polygon.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 #include "ui/gfx/transform.h"
     12 
     13 namespace cc {
     14 namespace {
     15 
     16 #define CREATE_NEW_DRAW_POLYGON(name, points_vector, normal, polygon_id) \
     17   DrawPolygon name(NULL, points_vector, normal, polygon_id)
     18 
     19 #define EXPECT_FLOAT_WITHIN_EPSILON_OF(a, b) \
     20   EXPECT_TRUE(std::abs(a - b) < std::numeric_limits<float>::epsilon());
     21 
     22 #define EXPECT_POINT_EQ(point_a, point_b)    \
     23   EXPECT_FLOAT_EQ(point_a.x(), point_b.x()); \
     24   EXPECT_FLOAT_EQ(point_a.y(), point_b.y()); \
     25   EXPECT_FLOAT_EQ(point_a.z(), point_b.z());
     26 
     27 static void ValidatePoints(const DrawPolygon& polygon,
     28                            const std::vector<gfx::Point3F>& points) {
     29   EXPECT_EQ(polygon.points().size(), points.size());
     30   for (size_t i = 0; i < points.size(); i++) {
     31     EXPECT_POINT_EQ(polygon.points()[i], points[i]);
     32   }
     33 }
     34 
     35 // Two quads are definitely not touching and so no split should occur.
     36 TEST(DrawPolygonSplitTest, NotTouchingNoSplit) {
     37   std::vector<gfx::Point3F> vertices_a;
     38   vertices_a.push_back(gfx::Point3F(0.0f, 10.0f, 0.0f));
     39   vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f));
     40   vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f));
     41   vertices_a.push_back(gfx::Point3F(10.0f, 10.0f, 0.0f));
     42   std::vector<gfx::Point3F> vertices_b;
     43   vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, 5.0f));
     44   vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, 15.0f));
     45   vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, 15.0f));
     46   vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, 5.0f));
     47 
     48   CREATE_NEW_DRAW_POLYGON(
     49       polygon_a, vertices_a, gfx::Vector3dF(0.0f, 0.0f, 1.0f), 0);
     50   CREATE_NEW_DRAW_POLYGON(
     51       polygon_b, vertices_b, gfx::Vector3dF(-1.0f, 0.0f, 0.0f), 1);
     52 
     53   EXPECT_EQ(DrawPolygon::SideCompare(polygon_b, polygon_a), BSP_FRONT);
     54 }
     55 
     56 // One quad is resting against another, but doesn't cross its plane so no split
     57 // should occur.
     58 TEST(DrawPolygonSplitTest, BarelyTouchingNoSplit) {
     59   std::vector<gfx::Point3F> vertices_a;
     60   vertices_a.push_back(gfx::Point3F(0.0f, 10.0f, 0.0f));
     61   vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f));
     62   vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f));
     63   vertices_a.push_back(gfx::Point3F(10.0f, 10.0f, 0.0f));
     64   std::vector<gfx::Point3F> vertices_b;
     65   vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, 0.0f));
     66   vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, -10.0f));
     67   vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, -10.0f));
     68   vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, 0.0f));
     69 
     70   CREATE_NEW_DRAW_POLYGON(
     71       polygon_a, vertices_a, gfx::Vector3dF(0.0f, 0.0f, 1.0f), 0);
     72   CREATE_NEW_DRAW_POLYGON(
     73       polygon_b, vertices_b, gfx::Vector3dF(-1.0f, 0.0f, 0.0f), 1);
     74 
     75   EXPECT_EQ(DrawPolygon::SideCompare(polygon_b, polygon_a), BSP_BACK);
     76 }
     77 
     78 // One quad intersects another and becomes two pieces.
     79 TEST(DrawPolygonSplitTest, BasicSplit) {
     80   std::vector<gfx::Point3F> vertices_a;
     81   vertices_a.push_back(gfx::Point3F(0.0f, 10.0f, 0.0f));
     82   vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f));
     83   vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f));
     84   vertices_a.push_back(gfx::Point3F(10.0f, 10.0f, 0.0f));
     85   std::vector<gfx::Point3F> vertices_b;
     86   vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, -5.0f));
     87   vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, -5.0f));
     88   vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, 5.0f));
     89   vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, 5.0f));
     90 
     91   CREATE_NEW_DRAW_POLYGON(
     92       polygon_a, vertices_a, gfx::Vector3dF(0.0f, 0.0f, 1.0f), 0);
     93   CREATE_NEW_DRAW_POLYGON(
     94       polygon_b, vertices_b, gfx::Vector3dF(-1.0f, 0.0f, 0.0f), 1);
     95 
     96   EXPECT_EQ(DrawPolygon::SideCompare(polygon_b, polygon_a), BSP_SPLIT);
     97 
     98   scoped_ptr<DrawPolygon> front_polygon;
     99   scoped_ptr<DrawPolygon> back_polygon;
    100   polygon_b.Split(polygon_a, &front_polygon, &back_polygon);
    101   EXPECT_EQ(DrawPolygon::SideCompare(*front_polygon, polygon_a), BSP_FRONT);
    102   EXPECT_EQ(DrawPolygon::SideCompare(*back_polygon, polygon_a), BSP_BACK);
    103 
    104   std::vector<gfx::Point3F> test_points_a;
    105   test_points_a.push_back(gfx::Point3F(5.0f, 0.0f, 0.0f));
    106   test_points_a.push_back(gfx::Point3F(5.0f, 0.0f, 5.0f));
    107   test_points_a.push_back(gfx::Point3F(5.0f, 10.0f, 5.0f));
    108   test_points_a.push_back(gfx::Point3F(5.0f, 10.0f, 0.0f));
    109   std::vector<gfx::Point3F> test_points_b;
    110   test_points_b.push_back(gfx::Point3F(5.0f, 10.0f, 0.0f));
    111   test_points_b.push_back(gfx::Point3F(5.0f, 10.0f, -5.0f));
    112   test_points_b.push_back(gfx::Point3F(5.0f, 0.0f, -5.0f));
    113   test_points_b.push_back(gfx::Point3F(5.0f, 0.0f, 0.0f));
    114   ValidatePoints(*(front_polygon.get()), test_points_a);
    115   ValidatePoints(*(back_polygon.get()), test_points_b);
    116 
    117   EXPECT_EQ(front_polygon->points().size(), 4u);
    118   EXPECT_EQ(back_polygon->points().size(), 4u);
    119 }
    120 
    121 // In this test we cut the corner of a quad so that it creates a triangle and
    122 // a pentagon as a result.
    123 TEST(DrawPolygonSplitTest, AngledSplit) {
    124   std::vector<gfx::Point3F> vertices_a;
    125   vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f));
    126   vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 10.0f));
    127   vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 10.0f));
    128   vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f));
    129   std::vector<gfx::Point3F> vertices_b;
    130   vertices_b.push_back(gfx::Point3F(2.0f, 5.0f, 1.0f));
    131   vertices_b.push_back(gfx::Point3F(2.0f, -5.0f, 1.0f));
    132   vertices_b.push_back(gfx::Point3F(-1.0f, -5.0f, -2.0f));
    133   vertices_b.push_back(gfx::Point3F(-1.0f, 5.0f, -2.0f));
    134 
    135   CREATE_NEW_DRAW_POLYGON(
    136       polygon_a, vertices_a, gfx::Vector3dF(0.0f, 1.0f, 0.0f), 0);
    137   CREATE_NEW_DRAW_POLYGON(
    138       polygon_b, vertices_b, gfx::Vector3dF(0.707107f, 0.0f, -0.707107f), 1);
    139 
    140   EXPECT_EQ(DrawPolygon::SideCompare(polygon_a, polygon_b), BSP_SPLIT);
    141 
    142   scoped_ptr<DrawPolygon> front_polygon;
    143   scoped_ptr<DrawPolygon> back_polygon;
    144   polygon_a.Split(polygon_b, &front_polygon, &back_polygon);
    145   EXPECT_EQ(DrawPolygon::SideCompare(*front_polygon, polygon_b), BSP_FRONT);
    146   EXPECT_EQ(DrawPolygon::SideCompare(*back_polygon, polygon_b), BSP_BACK);
    147 
    148   EXPECT_EQ(front_polygon->points().size(), 3u);
    149   EXPECT_EQ(back_polygon->points().size(), 5u);
    150 
    151   std::vector<gfx::Point3F> test_points_a;
    152   test_points_a.push_back(gfx::Point3F(10.0f, 0.0f, 9.0f));
    153   test_points_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f));
    154   test_points_a.push_back(gfx::Point3F(1.0f, 0.0f, 0.0f));
    155   std::vector<gfx::Point3F> test_points_b;
    156   test_points_b.push_back(gfx::Point3F(1.0f, 0.0f, 0.0f));
    157   test_points_b.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f));
    158   test_points_b.push_back(gfx::Point3F(0.0f, 0.0f, 10.0f));
    159   test_points_b.push_back(gfx::Point3F(10.0f, 0.0f, 10.0f));
    160   test_points_b.push_back(gfx::Point3F(10.0f, 0.0f, 9.0f));
    161 
    162   ValidatePoints(*(front_polygon.get()), test_points_a);
    163   ValidatePoints(*(back_polygon.get()), test_points_b);
    164 }
    165 
    166 TEST(DrawPolygonTransformTest, TransformNormal) {
    167   // We give this polygon no actual vertices because we're not interested
    168   // in actually transforming any points, just the normal.
    169   std::vector<gfx::Point3F> vertices_a;
    170   CREATE_NEW_DRAW_POLYGON(
    171       polygon_a, vertices_a, gfx::Vector3dF(0.707107f, 0.0f, -0.707107f), 0);
    172 
    173   gfx::Transform transform;
    174   transform.RotateAboutYAxis(45.0);
    175   // This would transform the vertices as well, but we are transforming a
    176   // DrawPolygon with 0 vertices just to make sure our normal transformation
    177   // using the inverse tranpose matrix gives us the right result.
    178   polygon_a.TransformToScreenSpace(transform);
    179 
    180   // Note: We use EXPECT_FLOAT_WITHIN_EPSILON instead of EXPECT_FLOAT_EQUAL here
    181   // because some architectures (e.g., Arm64) employ a fused multiply-add
    182   // instruction which causes rounding asymmetry and reduces precision.
    183   // http://crbug.com/401117.
    184   EXPECT_FLOAT_WITHIN_EPSILON_OF(polygon_a.normal().x(), 0);
    185   EXPECT_FLOAT_WITHIN_EPSILON_OF(polygon_a.normal().y(), 0);
    186   EXPECT_FLOAT_WITHIN_EPSILON_OF(polygon_a.normal().z(), -1);
    187 }
    188 
    189 }  // namespace
    190 }  // namespace cc
    191