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 5eb59a6a21..d556bb4fea 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 1d996487e2..c7a6a09d9c 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 24f24ff371..9c27fa1ad4 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 aff20cd54b..ce89150c19 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; };