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.
5 #include "cc/output/bsp_tree.h"
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"
18 BspNode::BspNode(scoped_ptr
<DrawPolygon
> data
) : node_data(data
.Pass()) {
24 BspTree::BspTree(ScopedPtrDeque
<DrawPolygon
>* list
) {
25 if (list
->size() == 0)
28 root_
= make_scoped_ptr(new BspNode(list
->take_front()));
29 BuildTree(root_
.get(), list
);
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
38 void BspTree::BuildTree(BspNode
* node
,
39 ScopedPtrDeque
<DrawPolygon
>* polygon_list
) {
40 ScopedPtrDeque
<DrawPolygon
> front_list
;
41 ScopedPtrDeque
<DrawPolygon
> back_list
;
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
));
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
) {
56 front_list
.push_back(polygon_list
->take_front().Pass());
59 back_list
.push_back(polygon_list
->take_front().Pass());
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();
70 polygon
->Split(*(node
->node_data
), &new_front
, &new_back
);
75 front_list
.push_back(new_front
.Pass());
76 back_list
.push_back(new_back
.Pass());
79 case BSP_COPLANAR_FRONT
:
80 node
->coplanars_front
.push_back(polygon_list
->take_front());
82 case BSP_COPLANAR_BACK
:
83 node
->coplanars_back
.push_back(polygon_list
->take_front());
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
= make_scoped_ptr(new BspNode(back_list
.take_front()));
94 BuildTree(node
->back_child
.get(), &back_list
);
97 // Build the front subtree using the front of the front_list as our splitter.
98 if (front_list
.size() > 0) {
100 scoped_ptr
<BspNode
>(new BspNode(front_list
.take_front()));
101 BuildTree(node
->front_child
.get(), &front_list
);
105 BspCompareResult
BspTree::GetNodePositionRelative(const DrawPolygon
& node_a
,
106 const DrawPolygon
& node_b
) {
107 return DrawPolygon::SideCompare(node_a
, node_b
);
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
) {
118 BspTree::~BspTree() {