From 8c151364df0b7a50b6ba1cd6a7409966a05d5c64 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 9 Mar 2017 00:01:13 +0100 Subject: [PATCH] Add special handling for CullVisitor to QuadTreeWorld. - Cull only against bounding box, not bounding sphere, as this appears to perform better. - Also traverse into non visible nodes to compute their LOD, this is to avoid nodes having to be loaded in when the player turns the view around, and will avoid unnecessary refs/unrefs of rendering data in the View. This should probably be turned off at some point for static cameras, such as the local maps. --- components/terrain/quadtreenode.cpp | 7 +++++- components/terrain/quadtreenode.hpp | 2 ++ components/terrain/quadtreeworld.cpp | 33 +++++++++++++++++++++++++--- components/terrain/viewdata.cpp | 12 +++++----- components/terrain/viewdata.hpp | 5 +++-- 5 files changed, 48 insertions(+), 11 deletions(-) diff --git a/components/terrain/quadtreenode.cpp b/components/terrain/quadtreenode.cpp index 5eb59a6a2..d556bb4fe 100644 --- a/components/terrain/quadtreenode.cpp +++ b/components/terrain/quadtreenode.cpp @@ -104,7 +104,7 @@ void QuadTreeNode::traverse(osg::NodeVisitor &nv) } if ((mLodCallback && mLodCallback->isSufficientDetail(this, nv)) || !getNumChildren()) - getView(nv)->add(this); + getView(nv)->add(this, true); else osg::Group::traverse(nv); } @@ -114,6 +114,11 @@ void QuadTreeNode::setLodCallback(LodCallback *lodCallback) mLodCallback = lodCallback; } +LodCallback *QuadTreeNode::getLodCallback() +{ + return mLodCallback; +} + void QuadTreeNode::setViewDataMap(ViewDataMap *map) { mViewDataMap = map; diff --git a/components/terrain/quadtreenode.hpp b/components/terrain/quadtreenode.hpp index 1d996487e..c7a6a09d9 100644 --- a/components/terrain/quadtreenode.hpp +++ b/components/terrain/quadtreenode.hpp @@ -66,6 +66,8 @@ namespace Terrain /// Set the Lod callback to use for determining when to stop traversing further down the quad tree. void setLodCallback(LodCallback* lodCallback); + LodCallback* getLodCallback(); + /// Set the view data map that the finally used nodes for a given camera/intersection are pushed onto. void setViewDataMap(ViewDataMap* map); diff --git a/components/terrain/quadtreeworld.cpp b/components/terrain/quadtreeworld.cpp index 24f24ff37..9c27fa1ad 100644 --- a/components/terrain/quadtreeworld.cpp +++ b/components/terrain/quadtreeworld.cpp @@ -1,5 +1,7 @@ #include "quadtreeworld.hpp" +#include + #include #include "quadtreenode.hpp" @@ -235,15 +237,39 @@ QuadTreeWorld::~QuadTreeWorld() } } + +void traverse(QuadTreeNode* node, ViewData* vd, osgUtil::CullVisitor* cv, bool visible) +{ + if (!node->hasValidBounds()) + return; + + visible = visible && !cv->isCulled(node->getBoundingBox()); + bool stopTraversal = (node->getLodCallback() && node->getLodCallback()->isSufficientDetail(node, *cv)) || !node->getNumChildren(); + + if (stopTraversal) + vd->add(node, visible); + else + { + for (unsigned int i=0; igetNumChildren(); ++i) + traverse(node->getChild(i), vd, cv, visible); + } +} + void QuadTreeWorld::accept(osg::NodeVisitor &nv) { if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR)// && nv.getVisitorType() != osg::NodeVisitor::INTERSECTION_VISITOR) return; - mRootNode->traverse(nv); - ViewData* vd = mRootNode->getView(nv); + if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR) + { + osgUtil::CullVisitor* cv = static_cast(&nv); + traverse(mRootNode.get(), vd, cv, true); + } + else + mRootNode->traverse(nv); + for (unsigned int i=0; igetNumEntries(); ++i) { ViewData::Entry& entry = vd->getEntry(i); @@ -253,7 +279,8 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv) entry.mRenderingNode = mChunkManager->getChunk(entry.mNode->getSize(), entry.mNode->getCenter(), lod); } - entry.mRenderingNode->accept(nv); + if (entry.mVisible) + entry.mRenderingNode->accept(nv); } vd->reset(nv.getTraversalNumber()); diff --git a/components/terrain/viewdata.cpp b/components/terrain/viewdata.cpp index aff20cd54..ce89150c1 100644 --- a/components/terrain/viewdata.cpp +++ b/components/terrain/viewdata.cpp @@ -12,14 +12,14 @@ ViewData::ViewData() } -void ViewData::add(QuadTreeNode *node) +void ViewData::add(QuadTreeNode *node, bool visible) { int index = mNumEntries++; mEntries.resize(index+1); Entry& entry = mEntries[index]; - if (entry.set(node)) + if (entry.set(node, visible)) mChanged = true; } @@ -37,7 +37,7 @@ void ViewData::reset(unsigned int frame) { // clear any unused entries for (unsigned int i=mNumEntries; i mRenderingNode; };