Skip to content

Commit 80fae1e

Browse files
author
thildebr@chromium.org
committed
WIP BSP Tree for 3D Layer Sorting
Still adding test scenarios as I come up with them. Review URL: https://codereview.chromium.org/384083002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@286499 0039d316-1c4b-4281-b951-d872f2087c98
1 parent e3a62a3 commit 80fae1e

7 files changed

+646
-1
lines changed

cc/cc.gyp

+4-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,10 @@
244244
'layers/video_layer_impl.h',
245245
'output/begin_frame_args.cc',
246246
'output/begin_frame_args.h',
247-
'output/bsp_compare_result.h',
247+
'output/bsp_tree.cc',
248+
'output/bsp_tree.h',
249+
'output/bsp_walk_action.cc',
250+
'output/bsp_walk_action.h',
248251
'output/compositor_frame.cc',
249252
'output/compositor_frame.h',
250253
'output/compositor_frame_ack.cc',

cc/cc_tests.gyp

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
'layers/ui_resource_layer_unittest.cc',
5959
'layers/video_layer_impl_unittest.cc',
6060
'output/begin_frame_args_unittest.cc',
61+
'output/bsp_tree_unittest.cc',
6162
'output/delegating_renderer_unittest.cc',
6263
'output/filter_operations_unittest.cc',
6364
'output/gl_renderer_unittest.cc',

cc/output/bsp_tree.cc

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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 "cc/output/bsp_tree.h"
6+
7+
#include <list>
8+
#include <vector>
9+
10+
#include "base/memory/scoped_ptr.h"
11+
#include "cc/base/scoped_ptr_deque.h"
12+
#include "cc/base/scoped_ptr_vector.h"
13+
#include "cc/output/bsp_compare_result.h"
14+
#include "cc/quads/draw_polygon.h"
15+
16+
namespace cc {
17+
18+
BspNode::BspNode(scoped_ptr<DrawPolygon> data) : node_data(data.Pass()) {
19+
}
20+
21+
BspNode::~BspNode() {
22+
}
23+
24+
BspTree::BspTree(ScopedPtrDeque<DrawPolygon>* list) {
25+
if (list->size() == 0)
26+
return;
27+
28+
root_ = scoped_ptr<BspNode>(new BspNode(list->take_front()));
29+
BuildTree(root_.get(), list);
30+
}
31+
32+
// The idea behind using a deque for BuildTree's input is that we want to be
33+
// able to place polygons that we've decided aren't splitting plane candidates
34+
// at the back of the queue while moving the candidate splitting planes to the
35+
// front when the heuristic decides that they're a better choice. This way we
36+
// can always simply just take from the front of the deque for our node's
37+
// data.
38+
void BspTree::BuildTree(BspNode* node,
39+
ScopedPtrDeque<DrawPolygon>* polygon_list) {
40+
ScopedPtrDeque<DrawPolygon> front_list;
41+
ScopedPtrDeque<DrawPolygon> back_list;
42+
43+
// We take in a list of polygons at this level of the tree, and have to
44+
// find a splitting plane, then classify polygons as either in front of
45+
// or behind that splitting plane.
46+
while (polygon_list->size() > 0) {
47+
// Is this particular polygon in front of or behind our splitting polygon.
48+
BspCompareResult comparer_result =
49+
GetNodePositionRelative(*polygon_list->front(), *(node->node_data));
50+
51+
// If it's clearly behind or in front of the splitting plane, we use the
52+
// heuristic to decide whether or not we should put it at the back
53+
// or front of the list.
54+
switch (comparer_result) {
55+
case BSP_FRONT:
56+
front_list.push_back(polygon_list->take_front().Pass());
57+
break;
58+
case BSP_BACK:
59+
back_list.push_back(polygon_list->take_front().Pass());
60+
break;
61+
case BSP_SPLIT:
62+
{
63+
scoped_ptr<DrawPolygon> polygon;
64+
scoped_ptr<DrawPolygon> new_front;
65+
scoped_ptr<DrawPolygon> new_back;
66+
bool split_result = false;
67+
// Time to split this geometry, *it needs to be split by node_data.
68+
polygon = polygon_list->take_front();
69+
split_result =
70+
polygon->Split(*(node->node_data), &new_front, &new_back);
71+
DCHECK(split_result);
72+
if (!split_result) {
73+
break;
74+
}
75+
front_list.push_back(new_front.Pass());
76+
back_list.push_back(new_back.Pass());
77+
break;
78+
}
79+
case BSP_COPLANAR_FRONT:
80+
node->coplanars_front.push_back(polygon_list->take_front());
81+
break;
82+
case BSP_COPLANAR_BACK:
83+
node->coplanars_back.push_back(polygon_list->take_front());
84+
break;
85+
default:
86+
NOTREACHED();
87+
break;
88+
}
89+
}
90+
91+
// Build the back subtree using the front of the back_list as our splitter.
92+
if (back_list.size() > 0) {
93+
node->back_child = scoped_ptr<BspNode>(new BspNode(back_list.take_front()));
94+
BuildTree(node->back_child.get(), &back_list);
95+
}
96+
97+
// Build the front subtree using the front of the front_list as our splitter.
98+
if (front_list.size() > 0) {
99+
node->front_child =
100+
scoped_ptr<BspNode>(new BspNode(front_list.take_front()));
101+
BuildTree(node->front_child.get(), &front_list);
102+
}
103+
}
104+
105+
BspCompareResult BspTree::GetNodePositionRelative(const DrawPolygon& node_a,
106+
const DrawPolygon& node_b) {
107+
return DrawPolygon::SideCompare(node_a, node_b);
108+
}
109+
110+
// The base comparer with 0,0,0 as camera position facing forward
111+
BspCompareResult BspTree::GetCameraPositionRelative(const DrawPolygon& node) {
112+
if (node.normal().z() > 0.0f) {
113+
return BSP_FRONT;
114+
}
115+
return BSP_BACK;
116+
}
117+
118+
BspTree::~BspTree() {
119+
}
120+
121+
} // namespace cc

cc/output/bsp_tree.h

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
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+
#ifndef CC_OUTPUT_BSP_TREE_H_
6+
#define CC_OUTPUT_BSP_TREE_H_
7+
8+
#include <list>
9+
#include <vector>
10+
11+
#include "base/memory/scoped_ptr.h"
12+
#include "cc/base/scoped_ptr_deque.h"
13+
#include "cc/base/scoped_ptr_vector.h"
14+
#include "cc/output/bsp_compare_result.h"
15+
#include "cc/quads/draw_polygon.h"
16+
17+
namespace cc {
18+
19+
struct BspNode {
20+
// This represents the splitting plane.
21+
scoped_ptr<DrawPolygon> node_data;
22+
// This represents any coplanar geometry we found while building the BSP.
23+
ScopedPtrVector<DrawPolygon> coplanars_front;
24+
ScopedPtrVector<DrawPolygon> coplanars_back;
25+
26+
scoped_ptr<BspNode> back_child;
27+
scoped_ptr<BspNode> front_child;
28+
29+
explicit BspNode(scoped_ptr<DrawPolygon> data);
30+
~BspNode();
31+
};
32+
33+
class CC_EXPORT BspTree {
34+
public:
35+
explicit BspTree(ScopedPtrDeque<DrawPolygon>* list);
36+
scoped_ptr<BspNode>& root() { return root_; }
37+
38+
template <typename ActionHandlerType>
39+
void TraverseWithActionHandler(ActionHandlerType* action_handler) const {
40+
if (root_) {
41+
WalkInOrderRecursion<ActionHandlerType>(action_handler, root_.get());
42+
}
43+
}
44+
45+
~BspTree();
46+
47+
private:
48+
scoped_ptr<BspNode> root_;
49+
50+
void FromList(ScopedPtrVector<DrawPolygon>* list);
51+
void BuildTree(BspNode* node, ScopedPtrDeque<DrawPolygon>* data);
52+
53+
template <typename ActionHandlerType>
54+
void WalkInOrderAction(ActionHandlerType* action_handler,
55+
DrawPolygon* item) const {
56+
(*action_handler)(item);
57+
}
58+
59+
template <typename ActionHandlerType>
60+
void WalkInOrderVisitNodes(
61+
ActionHandlerType* action_handler,
62+
const BspNode* node,
63+
const BspNode* first_child,
64+
const BspNode* second_child,
65+
const ScopedPtrVector<DrawPolygon>& first_coplanars,
66+
const ScopedPtrVector<DrawPolygon>& second_coplanars) const {
67+
if (first_child) {
68+
WalkInOrderRecursion(action_handler, first_child);
69+
}
70+
for (size_t i = 0; i < first_coplanars.size(); i++) {
71+
WalkInOrderAction(action_handler, first_coplanars[i]);
72+
}
73+
WalkInOrderAction(action_handler, node->node_data.get());
74+
for (size_t i = 0; i < second_coplanars.size(); i++) {
75+
WalkInOrderAction(action_handler, second_coplanars[i]);
76+
}
77+
if (second_child) {
78+
WalkInOrderRecursion(action_handler, second_child);
79+
}
80+
}
81+
82+
template <typename ActionHandlerType>
83+
void WalkInOrderRecursion(ActionHandlerType* action_handler,
84+
const BspNode* node) const {
85+
// If our view is in front of the the polygon
86+
// in this node then walk back then front.
87+
if (GetCameraPositionRelative(*(node->node_data)) == BSP_FRONT) {
88+
WalkInOrderVisitNodes<ActionHandlerType>(action_handler,
89+
node,
90+
node->back_child.get(),
91+
node->front_child.get(),
92+
node->coplanars_front,
93+
node->coplanars_back);
94+
} else {
95+
WalkInOrderVisitNodes<ActionHandlerType>(action_handler,
96+
node,
97+
node->front_child.get(),
98+
node->back_child.get(),
99+
node->coplanars_back,
100+
node->coplanars_front);
101+
}
102+
}
103+
104+
// Returns whether or not nodeA is on one or the other side of nodeB,
105+
// coplanar, or whether it crosses nodeB's plane and needs to be split
106+
static BspCompareResult GetNodePositionRelative(const DrawPolygon& node_a,
107+
const DrawPolygon& node_b);
108+
// Returns whether or not our viewer is in front of or behind the plane
109+
// defined by this polygon/node
110+
static BspCompareResult GetCameraPositionRelative(const DrawPolygon& node);
111+
};
112+
113+
} // namespace cc
114+
115+
#endif // CC_OUTPUT_BSP_TREE_H_

0 commit comments

Comments
 (0)