Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2211)

Unified Diff: cc/output/bsp_tree_unittest.cc

Issue 384083002: WIP BSP Tree for 3D Layer Sorting (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: cc/output/bsp_tree_unittest.cc
diff --git a/cc/output/bsp_tree_unittest.cc b/cc/output/bsp_tree_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2007a082b7936e3c0ae8c40f4d27f0c5682ffd0c
--- /dev/null
+++ b/cc/output/bsp_tree_unittest.cc
@@ -0,0 +1,356 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/base/scoped_ptr_vector.h"
+#include "cc/output/bsp_controller.h"
+#include "cc/output/bsp_tree.h"
+#include "cc/output/bsp_walk_action.h"
+#include "cc/quads/draw_polygon.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+enum TestSide { IN_FRONT, BEHIND, COPLANAR };
Ian Vollick 2014/07/19 00:45:01 Is this used anymore?
troyhildebrandt 2014/07/21 19:16:50 Nope, removed.
+
+class TestBspController : public BspController {
+ public:
+ TestBspController() : BspController() {}
+ virtual float SplitWeight(const DrawPolygon& poly) OVERRIDE { return 0.0f; }
+};
+
+#define EXPECT_SORTED_LISTS_EQ(polygon_list, compare_list) \
+ do { \
+ EXPECT_EQ(polygon_list.size(), compare_list.size()); \
+ for (unsigned int i = 0; i < polygon_list.size(); i++) { \
+ EXPECT_EQ(polygon_list[i]->order_index, compare_list[i]); \
+ } \
+ } while (false);
+
+#define INT_VECTOR_FROM_ARRAY(array) \
+ std::vector<int>(array, array + arraysize(array))
+
+class BspTreeTest {
+ public:
+ static void RunTest(ScopedPtrVector<DrawPolygon>* test_polygons,
+ const std::vector<int>& compare_list) {
+ TestBspController bsp_controller;
+ BspTree bsp_tree(&bsp_controller, test_polygons);
+
+ std::vector<DrawPolygon*> sorted_list;
+ BspWalkActionToVector action_handler(&sorted_list);
+ bsp_tree.TraverseWithActionHandler(&action_handler);
+
+ // This loop is helpful for debugging purposes, will be removed once the
+ // tests are complete.
Ian Vollick 2014/07/19 00:45:01 Ok to remove this now?
troyhildebrandt 2014/07/21 19:16:50 Removed.
+ for (unsigned int i = 0; i < sorted_list.size(); i++) {
+ LOG(ERROR) << sorted_list[i]->order_index;
+ }
+ EXPECT_SORTED_LISTS_EQ(sorted_list, compare_list);
+ EXPECT_TRUE(VerifySidedness(bsp_tree.root()));
+ }
+
+ static bool VerifySidedness(const scoped_ptr<BspNode>& node) {
+ // We check if both the front and back child nodes have geometry that is
+ // completely on the expected side of the current node.
+ bool front_ok = true;
+ bool back_ok = true;
+ if (node->back_child) {
+ // Make sure the back child lies entirely behind this node.
+ if (!GeometrySide(node, node->back_child->node_data.get(), BSP_BACK)) {
+ return false;
+ }
+ back_ok = VerifySidedness(node->back_child);
+ }
+ // Make sure the front child lies entirely in front of this node.
+ if (node->front_child) {
+ if (!GeometrySide(node, node->front_child->node_data.get(), BSP_FRONT)) {
+ return false;
+ }
+ front_ok = VerifySidedness(node->front_child);
+ }
+ if (!back_ok || !front_ok) {
+ return false;
+ }
+
+ // Now we need to make sure our coplanar geometry is all actually coplanar.
+ for (unsigned int i = 0; i < node->coplanars_front.size(); i++) {
+ if (!GeometrySide(node, node->coplanars_front[i], BSP_COPLANAR)) {
+ return false;
+ }
+ }
+ for (unsigned int i = 0; i < node->coplanars_back.size(); i++) {
+ if (!GeometrySide(node, node->coplanars_back[i], BSP_COPLANAR)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static bool GeometrySide(const scoped_ptr<BspNode>& parent,
+ DrawPolygon* child_data,
+ BspCompareResult side) {
+ for (unsigned int i = 0; i < child_data->points.size(); i++) {
+ float p_distance =
+ parent->node_data->SignedPointDistance(child_data->points[i]);
+ switch (side) {
+ case BSP_BACK:
+ if (p_distance > BspController::compare_threshold) {
+ return false;
+ }
+ break;
+ case BSP_FRONT:
+ if (p_distance < -BspController::compare_threshold) {
+ return false;
+ }
+ break;
+ case BSP_COPLANAR:
+ if (std::abs(p_distance) > BspController::compare_threshold) {
+ return false;
+ }
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+ return true;
+ }
+};
+
+// Simple standing quads all parallel with each other, causing no splits.
+TEST(BspTreeTest, NoSplit) {
+ gfx::Point3F vertices_a[4];
+ vertices_a[0] = gfx::Point3F(0.0f, 10.0f, 0.0f);
+ vertices_a[1] = gfx::Point3F(0.0f, 0.0f, 0.0f);
+ vertices_a[2] = gfx::Point3F(10.0f, 0.0f, 0.0f);
+ vertices_a[3] = gfx::Point3F(10.0f, 10.0f, 0.0f);
+ gfx::Point3F vertices_b[4];
+ vertices_b[0] = gfx::Point3F(0.0f, 10.0f, -5.0f);
+ vertices_b[1] = gfx::Point3F(0.0f, 0.0f, -5.0f);
+ vertices_b[2] = gfx::Point3F(10.0f, 0.0f, -5.0f);
+ vertices_b[3] = gfx::Point3F(10.0f, 10.0f, -5.0f);
+ gfx::Point3F vertices_c[4];
+ vertices_c[0] = gfx::Point3F(0.0f, 10.0f, 5.0f);
+ vertices_c[1] = gfx::Point3F(0.0f, 0.0f, 5.0f);
+ vertices_c[2] = gfx::Point3F(10.0f, 0.0f, 5.0f);
+ vertices_c[3] = gfx::Point3F(10.0f, 10.0f, 5.0f);
+
+ scoped_ptr<DrawPolygon> polygon_a(
+ new DrawPolygon(NULL, vertices_a, 4, 0, true));
+ scoped_ptr<DrawPolygon> polygon_b(
+ new DrawPolygon(NULL, vertices_b, 4, 1, true));
+ scoped_ptr<DrawPolygon> polygon_c(
+ new DrawPolygon(NULL, vertices_c, 4, 2, true));
+ ScopedPtrVector<DrawPolygon> polygon_list;
+ polygon_list.push_back(polygon_a.Pass());
+ polygon_list.push_back(polygon_b.Pass());
+ polygon_list.push_back(polygon_c.Pass());
+
+ int compare_ids[] = {1, 0, 2};
+ std::vector<int> compare_list = INT_VECTOR_FROM_ARRAY(compare_ids);
+ BspTreeTest::RunTest(&polygon_list, compare_list);
+}
+
+// Basic two polygon split, can be viewed as a + from above.
+TEST(BspTreeTest, BasicSplit) {
+ gfx::Point3F vertices_a[4];
+ vertices_a[0] = gfx::Point3F(-5.0f, 5.0f, 0.0f);
+ vertices_a[1] = gfx::Point3F(-5.0f, -5.0f, 0.0f);
+ vertices_a[2] = gfx::Point3F(5.0f, -5.0f, 0.0f);
+ vertices_a[3] = gfx::Point3F(5.0f, 5.0f, 0.0f);
+ gfx::Point3F vertices_b[4];
+ vertices_b[0] = gfx::Point3F(0.0f, 5.0f, -5.0f);
+ vertices_b[1] = gfx::Point3F(0.0f, -5.0f, -5.0f);
+ vertices_b[2] = gfx::Point3F(0.0f, -5.0f, 5.0f);
+ vertices_b[3] = gfx::Point3F(0.0f, 5.0f, 5.0f);
+
+ scoped_ptr<DrawPolygon> polygon_a(
+ new DrawPolygon(NULL, vertices_a, 4, 0, true));
+ scoped_ptr<DrawPolygon> polygon_b(
+ new DrawPolygon(NULL, vertices_b, 4, 1, true));
+ ScopedPtrVector<DrawPolygon> polygon_list;
+ polygon_list.push_back(polygon_a.Pass());
+ polygon_list.push_back(polygon_b.Pass());
+
+ int compare_ids[] = {1, 0, 1};
+ std::vector<int> compare_list = INT_VECTOR_FROM_ARRAY(compare_ids);
+ BspTreeTest::RunTest(&polygon_list, compare_list);
+}
+
+// Same as above with the second quad offset so it doesn't intersect. One quad
+// should be very clearly on one side of the other, and no splitting should
+// occur.
+TEST(BspTreeTest, QuadOffset) {
+ gfx::Point3F vertices_a[4];
+ vertices_a[0] = gfx::Point3F(-5.0f, 5.0f, 0.0f);
+ vertices_a[1] = gfx::Point3F(-5.0f, -5.0f, 0.0f);
+ vertices_a[2] = gfx::Point3F(5.0f, -5.0f, 0.0f);
+ vertices_a[3] = gfx::Point3F(5.0f, 5.0f, 0.0f);
+ gfx::Point3F vertices_b[4];
+ vertices_b[0] = gfx::Point3F(0.0f, 5.0f, -15.0f);
+ vertices_b[1] = gfx::Point3F(0.0f, -5.0f, -15.0f);
+ vertices_b[2] = gfx::Point3F(0.0f, -5.0f, -10.0f);
+ vertices_b[3] = gfx::Point3F(0.0f, 5.0f, -10.0f);
+
+ scoped_ptr<DrawPolygon> polygon_a(
+ new DrawPolygon(NULL, vertices_a, 4, 0, true));
+ scoped_ptr<DrawPolygon> polygon_b(
+ new DrawPolygon(NULL, vertices_b, 4, 1, true));
+ ScopedPtrVector<DrawPolygon> polygon_list;
+ polygon_list.push_back(polygon_a.Pass());
+ polygon_list.push_back(polygon_b.Pass());
+
+ int compare_ids[] = {1, 0};
+ std::vector<int> compare_list = INT_VECTOR_FROM_ARRAY(compare_ids);
+ BspTreeTest::RunTest(&polygon_list, compare_list);
+}
+
+// Same as above, but this time we change the order in which the quads are
+// inserted into the tree, causing one to actually cross the plane of the other
+// and cause a split.
+TEST(BspTreeTest, QuadOffsetSplit) {
+ gfx::Point3F vertices_a[4];
+ vertices_a[0] = gfx::Point3F(-5.0f, 5.0f, 0.0f);
+ vertices_a[1] = gfx::Point3F(-5.0f, -5.0f, 0.0f);
+ vertices_a[2] = gfx::Point3F(5.0f, -5.0f, 0.0f);
+ vertices_a[3] = gfx::Point3F(5.0f, 5.0f, 0.0f);
+ gfx::Point3F vertices_b[4];
+ vertices_b[0] = gfx::Point3F(0.0f, 5.0f, -15.0f);
+ vertices_b[1] = gfx::Point3F(0.0f, -5.0f, -15.0f);
+ vertices_b[2] = gfx::Point3F(0.0f, -5.0f, -10.0f);
+ vertices_b[3] = gfx::Point3F(0.0f, 5.0f, -10.0f);
+
+ scoped_ptr<DrawPolygon> polygon_a(
+ new DrawPolygon(NULL, vertices_a, 4, 0, true));
+ scoped_ptr<DrawPolygon> polygon_b(
+ new DrawPolygon(NULL, vertices_b, 4, 1, true));
+ ScopedPtrVector<DrawPolygon> polygon_list;
+ polygon_list.push_back(polygon_b.Pass());
+ polygon_list.push_back(polygon_a.Pass());
+
+ int compare_ids[] = {0, 1, 0};
+ std::vector<int> compare_list = INT_VECTOR_FROM_ARRAY(compare_ids);
+ BspTreeTest::RunTest(&polygon_list, compare_list);
+}
+
+// In addition to what can be viewed as a + from above, another piece of
+// geometry is inserted to cut these pieces right in the middle, viewed as
+// a quad from overhead.
+TEST(BspTreeTest, ThreeWaySplit) {
+ gfx::Point3F vertices_a[4];
+ vertices_a[0] = gfx::Point3F(-5.0f, 5.0f, 0.0f);
+ vertices_a[1] = gfx::Point3F(-5.0f, -5.0f, 0.0f);
+ vertices_a[2] = gfx::Point3F(5.0f, -5.0f, 0.0f);
+ vertices_a[3] = gfx::Point3F(5.0f, 5.0f, 0.0f);
+ gfx::Point3F vertices_b[4];
+ vertices_b[0] = gfx::Point3F(0.0f, 5.0f, -5.0f);
+ vertices_b[1] = gfx::Point3F(0.0f, -5.0f, -5.0f);
+ vertices_b[2] = gfx::Point3F(0.0f, -5.0f, 5.0f);
+ vertices_b[3] = gfx::Point3F(0.0f, 5.0f, 5.0f);
+ gfx::Point3F vertices_c[4];
+ vertices_c[0] = gfx::Point3F(-5.0f, 0.0f, 5.0f);
+ vertices_c[1] = gfx::Point3F(-5.0f, 0.0f, -5.0f);
+ vertices_c[2] = gfx::Point3F(5.0f, 0.0f, -5.0f);
+ vertices_c[3] = gfx::Point3F(5.0f, 0.0f, 5.0f);
+
+ scoped_ptr<DrawPolygon> polygon_a(
+ new DrawPolygon(NULL, vertices_a, 4, 0, true));
+ scoped_ptr<DrawPolygon> polygon_b(
+ new DrawPolygon(NULL, vertices_b, 4, 1, true));
+ scoped_ptr<DrawPolygon> polygon_c(
+ new DrawPolygon(NULL, vertices_c, 4, 2, true));
+ ScopedPtrVector<DrawPolygon> polygon_list;
+ polygon_list.push_back(polygon_a.Pass());
+ polygon_list.push_back(polygon_b.Pass());
+ polygon_list.push_back(polygon_c.Pass());
+
+ int compare_ids[] = {2, 1, 2, 0, 2, 1, 2};
+ std::vector<int> compare_list = INT_VECTOR_FROM_ARRAY(compare_ids);
+ BspTreeTest::RunTest(&polygon_list, compare_list);
+}
+
+// This test checks whether coplanar geometry, when inserted into the tree in
+// order, comes back in the same order as it should.
+TEST(BspTreeTest, Coplanar) {
+ gfx::Point3F vertices_a[4];
+ vertices_a[0] = gfx::Point3F(-5.0f, 5.0f, 0.0f);
+ vertices_a[1] = gfx::Point3F(-5.0f, -5.0f, 0.0f);
+ vertices_a[2] = gfx::Point3F(5.0f, -5.0f, 0.0f);
+ vertices_a[3] = gfx::Point3F(5.0f, 5.0f, 0.0f);
+ gfx::Point3F vertices_b[4];
+ vertices_b[0] = gfx::Point3F(-4.0f, 4.0f, 0.0f);
+ vertices_b[1] = gfx::Point3F(-4.0f, -4.0f, 0.0f);
+ vertices_b[2] = gfx::Point3F(4.0f, -4.0f, 0.0f);
+ vertices_b[3] = gfx::Point3F(4.0f, 4.0f, 0.0f);
+ gfx::Point3F vertices_c[4];
+ vertices_c[0] = gfx::Point3F(-3.0f, 3.0f, 0.0f);
+ vertices_c[1] = gfx::Point3F(-3.0f, -3.0f, 0.0f);
+ vertices_c[2] = gfx::Point3F(3.0f, -3.0f, 0.0f);
+ vertices_c[3] = gfx::Point3F(3.0f, 3.0f, 0.0f);
+
+ scoped_ptr<DrawPolygon> polygon_a(
+ new DrawPolygon(NULL, vertices_a, 4, 0, true));
+ scoped_ptr<DrawPolygon> polygon_b(
+ new DrawPolygon(NULL, vertices_b, 4, 1, true));
+ scoped_ptr<DrawPolygon> polygon_c(
+ new DrawPolygon(NULL, vertices_c, 4, 2, true));
+ ScopedPtrVector<DrawPolygon> polygon_list;
+ polygon_list.push_back(polygon_a.Pass());
+ polygon_list.push_back(polygon_b.Pass());
+ polygon_list.push_back(polygon_c.Pass());
+
+ int compare_ids[] = {0, 1, 2};
+ std::vector<int> compare_list = INT_VECTOR_FROM_ARRAY(compare_ids);
+ BspTreeTest::RunTest(&polygon_list, compare_list);
+}
+
+// A bunch of coplanar geometry should end up sharing a single node, and
+// result in the final piece of geometry splitting into just two pieces on
+// either side of the shared plane.
+TEST(BspTreeTest, CoplanarSplit) {
+ gfx::Point3F vertices_a[4];
+ vertices_a[0] = gfx::Point3F(-5.0f, 5.0f, 0.0f);
+ vertices_a[1] = gfx::Point3F(-5.0f, -5.0f, 0.0f);
+ vertices_a[2] = gfx::Point3F(5.0f, -5.0f, 0.0f);
+ vertices_a[3] = gfx::Point3F(5.0f, 5.0f, 0.0f);
+ gfx::Point3F vertices_b[4];
+ vertices_b[0] = gfx::Point3F(-4.0f, 4.0f, 0.0f);
+ vertices_b[1] = gfx::Point3F(-4.0f, -4.0f, 0.0f);
+ vertices_b[2] = gfx::Point3F(4.0f, -4.0f, 0.0f);
+ vertices_b[3] = gfx::Point3F(4.0f, 4.0f, 0.0f);
+ gfx::Point3F vertices_c[4];
+ vertices_c[0] = gfx::Point3F(-3.0f, 3.0f, 0.0f);
+ vertices_c[1] = gfx::Point3F(-3.0f, -3.0f, 0.0f);
+ vertices_c[2] = gfx::Point3F(3.0f, -3.0f, 0.0f);
+ vertices_c[3] = gfx::Point3F(3.0f, 3.0f, 0.0f);
+ gfx::Point3F vertices_d[4];
+ vertices_d[0] = gfx::Point3F(0.0f, 15.0f, -15.0f);
+ vertices_d[1] = gfx::Point3F(0.0f, -15.0f, -15.0f);
+ vertices_d[2] = gfx::Point3F(0.0f, -15.0f, 15.0f);
+ vertices_d[3] = gfx::Point3F(0.0f, 15.0f, 15.0f);
+
+ scoped_ptr<DrawPolygon> polygon_a(
+ new DrawPolygon(NULL, vertices_a, 4, 0, true));
+ scoped_ptr<DrawPolygon> polygon_b(
+ new DrawPolygon(NULL, vertices_b, 4, 1, true));
+ scoped_ptr<DrawPolygon> polygon_c(
+ new DrawPolygon(NULL, vertices_c, 4, 2, true));
+ scoped_ptr<DrawPolygon> polygon_d(
+ new DrawPolygon(NULL, vertices_d, 4, 3, true));
+ ScopedPtrVector<DrawPolygon> polygon_list;
+ polygon_list.push_back(polygon_a.Pass());
+ polygon_list.push_back(polygon_b.Pass());
+ polygon_list.push_back(polygon_c.Pass());
+ polygon_list.push_back(polygon_d.Pass());
+
+ int compare_ids[] = {3, 0, 1, 2, 3};
+ std::vector<int> compare_list = INT_VECTOR_FROM_ARRAY(compare_ids);
+ BspTreeTest::RunTest(&polygon_list, compare_list);
+}
+
+} // namespace
+} // namespace cc

Powered by Google App Engine
This is Rietveld 408576698