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"
9 #include "base/memory/scoped_ptr.h"
10 #include "cc/base/scoped_ptr_deque.h"
11 #include "cc/base/scoped_ptr_vector.h"
12 #include "cc/output/bsp_compare_result.h"
13 #include "cc/quads/draw_polygon.h"
17 BspNode::BspNode(scoped_ptr
<DrawPolygon
> data
) : node_data(data
.Pass()) {
23 BspTree::BspTree(ScopedPtrDeque
<DrawPolygon
>* list
) {
24 if (list
->size() == 0)
27 root_
= make_scoped_ptr(new BspNode(list
->take_front()));
28 BuildTree(root_
.get(), list
);
31 // The idea behind using a deque for BuildTree's input is that we want to be
32 // able to place polygons that we've decided aren't splitting plane candidates
33 // at the back of the queue while moving the candidate splitting planes to the
34 // front when the heuristic decides that they're a better choice. This way we
35 // can always simply just take from the front of the deque for our node's
37 void BspTree::BuildTree(BspNode
* node
,
38 ScopedPtrDeque
<DrawPolygon
>* polygon_list
) {
39 ScopedPtrDeque
<DrawPolygon
> front_list
;
40 ScopedPtrDeque
<DrawPolygon
> back_list
;
42 // We take in a list of polygons at this level of the tree, and have to
43 // find a splitting plane, then classify polygons as either in front of
44 // or behind that splitting plane.
45 while (polygon_list
->size() > 0) {
46 // Is this particular polygon in front of or behind our splitting polygon.
47 BspCompareResult comparer_result
=
48 GetNodePositionRelative(*polygon_list
->front(), *(node
->node_data
));
50 // If it's clearly behind or in front of the splitting plane, we use the
51 // heuristic to decide whether or not we should put it at the back
52 // or front of the list.
53 switch (comparer_result
) {
55 front_list
.push_back(polygon_list
->take_front().Pass());
58 back_list
.push_back(polygon_list
->take_front().Pass());
62 scoped_ptr
<DrawPolygon
> polygon
;
63 scoped_ptr
<DrawPolygon
> new_front
;
64 scoped_ptr
<DrawPolygon
> new_back
;
65 bool split_result
= false;
66 // Time to split this geometry, *it needs to be split by node_data.
67 polygon
= polygon_list
->take_front();
69 polygon
->Split(*(node
->node_data
), &new_front
, &new_back
);
74 front_list
.push_back(new_front
.Pass());
75 back_list
.push_back(new_back
.Pass());
78 case BSP_COPLANAR_FRONT
:
79 node
->coplanars_front
.push_back(polygon_list
->take_front());
81 case BSP_COPLANAR_BACK
:
82 node
->coplanars_back
.push_back(polygon_list
->take_front());
90 // Build the back subtree using the front of the back_list as our splitter.
91 if (back_list
.size() > 0) {
92 node
->back_child
= make_scoped_ptr(new BspNode(back_list
.take_front()));
93 BuildTree(node
->back_child
.get(), &back_list
);
96 // Build the front subtree using the front of the front_list as our splitter.
97 if (front_list
.size() > 0) {
99 scoped_ptr
<BspNode
>(new BspNode(front_list
.take_front()));
100 BuildTree(node
->front_child
.get(), &front_list
);
104 BspCompareResult
BspTree::GetNodePositionRelative(const DrawPolygon
& node_a
,
105 const DrawPolygon
& node_b
) {
106 return DrawPolygon::SideCompare(node_a
, node_b
);
109 // The base comparer with 0,0,0 as camera position facing forward
110 BspCompareResult
BspTree::GetCameraPositionRelative(const DrawPolygon
& node
) {
111 if (node
.normal().z() > 0.0f
) {
117 BspTree::~BspTree() {