forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
thildebr@chromium.org
committed
Jul 30, 2014
1 parent
e3a62a3
commit 80fae1e
Showing
7 changed files
with
646 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// 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 "cc/output/bsp_tree.h" | ||
|
||
#include <list> | ||
#include <vector> | ||
|
||
#include "base/memory/scoped_ptr.h" | ||
#include "cc/base/scoped_ptr_deque.h" | ||
#include "cc/base/scoped_ptr_vector.h" | ||
#include "cc/output/bsp_compare_result.h" | ||
#include "cc/quads/draw_polygon.h" | ||
|
||
namespace cc { | ||
|
||
BspNode::BspNode(scoped_ptr<DrawPolygon> data) : node_data(data.Pass()) { | ||
} | ||
|
||
BspNode::~BspNode() { | ||
} | ||
|
||
BspTree::BspTree(ScopedPtrDeque<DrawPolygon>* list) { | ||
if (list->size() == 0) | ||
return; | ||
|
||
root_ = scoped_ptr<BspNode>(new BspNode(list->take_front())); | ||
BuildTree(root_.get(), list); | ||
} | ||
|
||
// The idea behind using a deque for BuildTree's input is that we want to be | ||
// able to place polygons that we've decided aren't splitting plane candidates | ||
// at the back of the queue while moving the candidate splitting planes to the | ||
// front when the heuristic decides that they're a better choice. This way we | ||
// can always simply just take from the front of the deque for our node's | ||
// data. | ||
void BspTree::BuildTree(BspNode* node, | ||
ScopedPtrDeque<DrawPolygon>* polygon_list) { | ||
ScopedPtrDeque<DrawPolygon> front_list; | ||
ScopedPtrDeque<DrawPolygon> back_list; | ||
|
||
// We take in a list of polygons at this level of the tree, and have to | ||
// find a splitting plane, then classify polygons as either in front of | ||
// or behind that splitting plane. | ||
while (polygon_list->size() > 0) { | ||
// Is this particular polygon in front of or behind our splitting polygon. | ||
BspCompareResult comparer_result = | ||
GetNodePositionRelative(*polygon_list->front(), *(node->node_data)); | ||
|
||
// If it's clearly behind or in front of the splitting plane, we use the | ||
// heuristic to decide whether or not we should put it at the back | ||
// or front of the list. | ||
switch (comparer_result) { | ||
case BSP_FRONT: | ||
front_list.push_back(polygon_list->take_front().Pass()); | ||
break; | ||
case BSP_BACK: | ||
back_list.push_back(polygon_list->take_front().Pass()); | ||
break; | ||
case BSP_SPLIT: | ||
{ | ||
scoped_ptr<DrawPolygon> polygon; | ||
scoped_ptr<DrawPolygon> new_front; | ||
scoped_ptr<DrawPolygon> new_back; | ||
bool split_result = false; | ||
// Time to split this geometry, *it needs to be split by node_data. | ||
polygon = polygon_list->take_front(); | ||
split_result = | ||
polygon->Split(*(node->node_data), &new_front, &new_back); | ||
DCHECK(split_result); | ||
if (!split_result) { | ||
break; | ||
} | ||
front_list.push_back(new_front.Pass()); | ||
back_list.push_back(new_back.Pass()); | ||
break; | ||
} | ||
case BSP_COPLANAR_FRONT: | ||
node->coplanars_front.push_back(polygon_list->take_front()); | ||
break; | ||
case BSP_COPLANAR_BACK: | ||
node->coplanars_back.push_back(polygon_list->take_front()); | ||
break; | ||
default: | ||
NOTREACHED(); | ||
break; | ||
} | ||
} | ||
|
||
// Build the back subtree using the front of the back_list as our splitter. | ||
if (back_list.size() > 0) { | ||
node->back_child = scoped_ptr<BspNode>(new BspNode(back_list.take_front())); | ||
BuildTree(node->back_child.get(), &back_list); | ||
} | ||
|
||
// Build the front subtree using the front of the front_list as our splitter. | ||
if (front_list.size() > 0) { | ||
node->front_child = | ||
scoped_ptr<BspNode>(new BspNode(front_list.take_front())); | ||
BuildTree(node->front_child.get(), &front_list); | ||
} | ||
} | ||
|
||
BspCompareResult BspTree::GetNodePositionRelative(const DrawPolygon& node_a, | ||
const DrawPolygon& node_b) { | ||
return DrawPolygon::SideCompare(node_a, node_b); | ||
} | ||
|
||
// The base comparer with 0,0,0 as camera position facing forward | ||
BspCompareResult BspTree::GetCameraPositionRelative(const DrawPolygon& node) { | ||
if (node.normal().z() > 0.0f) { | ||
return BSP_FRONT; | ||
} | ||
return BSP_BACK; | ||
} | ||
|
||
BspTree::~BspTree() { | ||
} | ||
|
||
} // namespace cc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// 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. | ||
|
||
#ifndef CC_OUTPUT_BSP_TREE_H_ | ||
#define CC_OUTPUT_BSP_TREE_H_ | ||
|
||
#include <list> | ||
#include <vector> | ||
|
||
#include "base/memory/scoped_ptr.h" | ||
#include "cc/base/scoped_ptr_deque.h" | ||
#include "cc/base/scoped_ptr_vector.h" | ||
#include "cc/output/bsp_compare_result.h" | ||
#include "cc/quads/draw_polygon.h" | ||
|
||
namespace cc { | ||
|
||
struct BspNode { | ||
// This represents the splitting plane. | ||
scoped_ptr<DrawPolygon> node_data; | ||
// This represents any coplanar geometry we found while building the BSP. | ||
ScopedPtrVector<DrawPolygon> coplanars_front; | ||
ScopedPtrVector<DrawPolygon> coplanars_back; | ||
|
||
scoped_ptr<BspNode> back_child; | ||
scoped_ptr<BspNode> front_child; | ||
|
||
explicit BspNode(scoped_ptr<DrawPolygon> data); | ||
~BspNode(); | ||
}; | ||
|
||
class CC_EXPORT BspTree { | ||
public: | ||
explicit BspTree(ScopedPtrDeque<DrawPolygon>* list); | ||
scoped_ptr<BspNode>& root() { return root_; } | ||
|
||
template <typename ActionHandlerType> | ||
void TraverseWithActionHandler(ActionHandlerType* action_handler) const { | ||
if (root_) { | ||
WalkInOrderRecursion<ActionHandlerType>(action_handler, root_.get()); | ||
} | ||
} | ||
|
||
~BspTree(); | ||
|
||
private: | ||
scoped_ptr<BspNode> root_; | ||
|
||
void FromList(ScopedPtrVector<DrawPolygon>* list); | ||
void BuildTree(BspNode* node, ScopedPtrDeque<DrawPolygon>* data); | ||
|
||
template <typename ActionHandlerType> | ||
void WalkInOrderAction(ActionHandlerType* action_handler, | ||
DrawPolygon* item) const { | ||
(*action_handler)(item); | ||
} | ||
|
||
template <typename ActionHandlerType> | ||
void WalkInOrderVisitNodes( | ||
ActionHandlerType* action_handler, | ||
const BspNode* node, | ||
const BspNode* first_child, | ||
const BspNode* second_child, | ||
const ScopedPtrVector<DrawPolygon>& first_coplanars, | ||
const ScopedPtrVector<DrawPolygon>& second_coplanars) const { | ||
if (first_child) { | ||
WalkInOrderRecursion(action_handler, first_child); | ||
} | ||
for (size_t i = 0; i < first_coplanars.size(); i++) { | ||
WalkInOrderAction(action_handler, first_coplanars[i]); | ||
} | ||
WalkInOrderAction(action_handler, node->node_data.get()); | ||
for (size_t i = 0; i < second_coplanars.size(); i++) { | ||
WalkInOrderAction(action_handler, second_coplanars[i]); | ||
} | ||
if (second_child) { | ||
WalkInOrderRecursion(action_handler, second_child); | ||
} | ||
} | ||
|
||
template <typename ActionHandlerType> | ||
void WalkInOrderRecursion(ActionHandlerType* action_handler, | ||
const BspNode* node) const { | ||
// If our view is in front of the the polygon | ||
// in this node then walk back then front. | ||
if (GetCameraPositionRelative(*(node->node_data)) == BSP_FRONT) { | ||
WalkInOrderVisitNodes<ActionHandlerType>(action_handler, | ||
node, | ||
node->back_child.get(), | ||
node->front_child.get(), | ||
node->coplanars_front, | ||
node->coplanars_back); | ||
} else { | ||
WalkInOrderVisitNodes<ActionHandlerType>(action_handler, | ||
node, | ||
node->front_child.get(), | ||
node->back_child.get(), | ||
node->coplanars_back, | ||
node->coplanars_front); | ||
} | ||
} | ||
|
||
// Returns whether or not nodeA is on one or the other side of nodeB, | ||
// coplanar, or whether it crosses nodeB's plane and needs to be split | ||
static BspCompareResult GetNodePositionRelative(const DrawPolygon& node_a, | ||
const DrawPolygon& node_b); | ||
// Returns whether or not our viewer is in front of or behind the plane | ||
// defined by this polygon/node | ||
static BspCompareResult GetCameraPositionRelative(const DrawPolygon& node); | ||
}; | ||
|
||
} // namespace cc | ||
|
||
#endif // CC_OUTPUT_BSP_TREE_H_ |
Oops, something went wrong.