Commit 6b4fd406 authored by Hans-Christian Ebke's avatar Hans-Christian Ebke
Browse files

Made traversal of scene graph non-recursive.

parent 45da5e0b
Pipeline #2915 failed with stage
in 57 minutes and 29 seconds
...@@ -402,6 +402,7 @@ void IRenderer::collectRenderObjects( ACG::GLState* _glState, ACG::SceneGraph::D ...@@ -402,6 +402,7 @@ void IRenderer::collectRenderObjects( ACG::GLState* _glState, ACG::SceneGraph::D
// } // }
renderObjects_.clear(); renderObjects_.clear();
if (!_sceneGraphRoot) return;
// default material needed // default material needed
ACG::SceneGraph::Material defMat; ACG::SceneGraph::Material defMat;
...@@ -413,70 +414,99 @@ void IRenderer::collectRenderObjects( ACG::GLState* _glState, ACG::SceneGraph::D ...@@ -413,70 +414,99 @@ void IRenderer::collectRenderObjects( ACG::GLState* _glState, ACG::SceneGraph::D
// defMat.alphaValue(1.0f); // defMat.alphaValue(1.0f);
// collect renderables // collect renderables
traverseRenderableNodes(_glState, _drawMode, _sceneGraphRoot, &defMat); traverseRenderableNodes(_glState, _drawMode, *_sceneGraphRoot, defMat);
} }
/// Stack element used in IRenderer::traverseRenderableNodes
namespace {
class ScenegraphTraversalStackEl {
public:
ScenegraphTraversalStackEl(ACG::SceneGraph::BaseNode &_node,
const ACG::SceneGraph::Material *_material) :
node(_node), material(_material),
subtree_index_start(0), leave(false) {}
ACG::SceneGraph::BaseNode &node;
const ACG::SceneGraph::Material* material;
size_t subtree_index_start;
bool leave;
};
}
void IRenderer::traverseRenderableNodes( ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode &_node, const ACG::SceneGraph::Material &_mat )
void IRenderer::traverseRenderableNodes( ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode* _node, const ACG::SceneGraph::Material* _mat )
{ {
if (_node) if (_node.status() == ACG::SceneGraph::BaseNode::HideSubtree)
{ return;
ACG::SceneGraph::BaseNode::StatusMode status(_node->status());
std::vector<ScenegraphTraversalStackEl> stack;
ACG::SceneGraph::DrawModes::DrawMode nodeDM = _node->drawMode(); // That's roughly the minimum size every scenegraph requries.
stack.reserve(32);
if (nodeDM == ACG::SceneGraph::DrawModes::DEFAULT) stack.push_back(ScenegraphTraversalStackEl(_node, &_mat));
nodeDM = _drawMode; while (!stack.empty()) {
ScenegraphTraversalStackEl &cur = stack.back();
ACG::SceneGraph::DrawModes::DrawMode nodeDM = cur.node.drawMode();
// If the subtree is hidden, ignore this node and its children while rendering if (nodeDM == ACG::SceneGraph::DrawModes::DEFAULT)
if (status != ACG::SceneGraph::BaseNode::HideSubtree) nodeDM = _drawMode;
{
if (!cur.leave) {
if ( _node->status() != ACG::SceneGraph::BaseNode::HideNode ) /*
_node->enter(this, *_glState, nodeDM); * Stuff that happens before processing cur.node's children.
*/
const size_t subtree_index_start = renderObjects_.size(); if ( cur.node.status() != ACG::SceneGraph::BaseNode::HideNode )
cur.node.enter(this, *_glState, nodeDM);
// fetch material (Node itself can be a material node, so we have to
// set that in front of the nodes own rendering cur.subtree_index_start = renderObjects_.size();
ACG::SceneGraph::MaterialNode* matNode = dynamic_cast<ACG::SceneGraph::MaterialNode*>(_node);
if (matNode) // fetch material (Node itself can be a material node, so we have to
_mat = &matNode->material(); // set that in front of the nodes own rendering
ACG::SceneGraph::MaterialNode* matNode =
if (_node->status() != ACG::SceneGraph::BaseNode::HideNode) dynamic_cast<ACG::SceneGraph::MaterialNode*>(&cur.node);
_node->getRenderObjects(this, *_glState, nodeDM, _mat); if (matNode)
cur.material = &matNode->material();
// Process children?
if (status != ACG::SceneGraph::BaseNode::HideChildren) if (cur.node.status() != ACG::SceneGraph::BaseNode::HideNode)
{ cur.node.getRenderObjects(this, *_glState, nodeDM, cur.material);
ACG::SceneGraph::BaseNode::ChildIter cIt, cEnd(_node->childrenEnd()); // Process children?
if (cur.node.status() != ACG::SceneGraph::BaseNode::HideChildren) {
// Process all children which are not second pass // Process all children which are second pass
for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt) for (ACG::SceneGraph::BaseNode::ChildIter
if (~(*cIt)->traverseMode() & ACG::SceneGraph::BaseNode::SecondPass) cIt = cur.node.childrenBegin(),
traverseRenderableNodes( _glState, _drawMode, *cIt, _mat); cEnd = cur.node.childrenEnd(); cIt != cEnd; ++cIt) {
if (((*cIt)->traverseMode() &
// Process all children which are second pass ACG::SceneGraph::BaseNode::SecondPass) &&
for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt) (*cIt)->status() != ACG::SceneGraph::BaseNode::HideSubtree)
if ((*cIt)->traverseMode() & ACG::SceneGraph::BaseNode::SecondPass) stack.push_back(ScenegraphTraversalStackEl(**cIt, cur.material));
traverseRenderableNodes( _glState, _drawMode, *cIt, _mat); }
// Process all children which are not second pass
for (ACG::SceneGraph::BaseNode::ChildIter
cIt = cur.node.childrenBegin(),
cEnd = cur.node.childrenEnd(); cIt != cEnd; ++cIt) {
if ((~(*cIt)->traverseMode() &
ACG::SceneGraph::BaseNode::SecondPass) &&
(*cIt)->status() != ACG::SceneGraph::BaseNode::HideSubtree)
stack.push_back(ScenegraphTraversalStackEl(**cIt, cur.material));
}
}
} // Next time process the other branch of this if statement.
cur.leave = true;
// Prepare current subtree info before calling leave(). } else {
current_subtree_objects_ = RenderObjectRange( /*
renderObjects_.begin() + subtree_index_start, * Stuff that happens after processing cur.node's children.
renderObjects_.end()); */
current_subtree_objects_ = RenderObjectRange(
renderObjects_.begin() + cur.subtree_index_start,
renderObjects_.end());
if (_node->status() != ACG::SceneGraph::BaseNode::HideNode ) if (cur.node.status() != ACG::SceneGraph::BaseNode::HideNode )
_node->leave(this, *_glState, nodeDM); cur.node.leave(this, *_glState, nodeDM);
stack.pop_back();
}
} }
}
} }
void IRenderer::prepareRenderingPipeline(ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode* _scenegraphRoot) void IRenderer::prepareRenderingPipeline(ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode* _scenegraphRoot)
......
...@@ -187,7 +187,7 @@ protected: ...@@ -187,7 +187,7 @@ protected:
* *
* Calls getRenderObjects on each node of the scenegraph recursively. Each node then triggers the callbacks. * Calls getRenderObjects on each node of the scenegraph recursively. Each node then triggers the callbacks.
*/ */
void traverseRenderableNodes(ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode* _node, const ACG::SceneGraph::Material* _mat); void traverseRenderableNodes(ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode &_node, const ACG::SceneGraph::Material &_mat);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment