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.
0.6.1
scrawl 8 years ago
parent f19a88be9d
commit 8c151364df

@ -104,7 +104,7 @@ void QuadTreeNode::traverse(osg::NodeVisitor &nv)
} }
if ((mLodCallback && mLodCallback->isSufficientDetail(this, nv)) || !getNumChildren()) if ((mLodCallback && mLodCallback->isSufficientDetail(this, nv)) || !getNumChildren())
getView(nv)->add(this); getView(nv)->add(this, true);
else else
osg::Group::traverse(nv); osg::Group::traverse(nv);
} }
@ -114,6 +114,11 @@ void QuadTreeNode::setLodCallback(LodCallback *lodCallback)
mLodCallback = lodCallback; mLodCallback = lodCallback;
} }
LodCallback *QuadTreeNode::getLodCallback()
{
return mLodCallback;
}
void QuadTreeNode::setViewDataMap(ViewDataMap *map) void QuadTreeNode::setViewDataMap(ViewDataMap *map)
{ {
mViewDataMap = map; mViewDataMap = map;

@ -66,6 +66,8 @@ namespace Terrain
/// Set the Lod callback to use for determining when to stop traversing further down the quad tree. /// Set the Lod callback to use for determining when to stop traversing further down the quad tree.
void setLodCallback(LodCallback* lodCallback); void setLodCallback(LodCallback* lodCallback);
LodCallback* getLodCallback();
/// Set the view data map that the finally used nodes for a given camera/intersection are pushed onto. /// Set the view data map that the finally used nodes for a given camera/intersection are pushed onto.
void setViewDataMap(ViewDataMap* map); void setViewDataMap(ViewDataMap* map);

@ -1,5 +1,7 @@
#include "quadtreeworld.hpp" #include "quadtreeworld.hpp"
#include <osgUtil/CullVisitor>
#include <components/sceneutil/workqueue.hpp> #include <components/sceneutil/workqueue.hpp>
#include "quadtreenode.hpp" #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; i<node->getNumChildren(); ++i)
traverse(node->getChild(i), vd, cv, visible);
}
}
void QuadTreeWorld::accept(osg::NodeVisitor &nv) void QuadTreeWorld::accept(osg::NodeVisitor &nv)
{ {
if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR)// && nv.getVisitorType() != osg::NodeVisitor::INTERSECTION_VISITOR) if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR)// && nv.getVisitorType() != osg::NodeVisitor::INTERSECTION_VISITOR)
return; return;
mRootNode->traverse(nv);
ViewData* vd = mRootNode->getView(nv); ViewData* vd = mRootNode->getView(nv);
if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
{
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv);
traverse(mRootNode.get(), vd, cv, true);
}
else
mRootNode->traverse(nv);
for (unsigned int i=0; i<vd->getNumEntries(); ++i) for (unsigned int i=0; i<vd->getNumEntries(); ++i)
{ {
ViewData::Entry& entry = vd->getEntry(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 = mChunkManager->getChunk(entry.mNode->getSize(), entry.mNode->getCenter(), lod);
} }
entry.mRenderingNode->accept(nv); if (entry.mVisible)
entry.mRenderingNode->accept(nv);
} }
vd->reset(nv.getTraversalNumber()); vd->reset(nv.getTraversalNumber());

@ -12,14 +12,14 @@ ViewData::ViewData()
} }
void ViewData::add(QuadTreeNode *node) void ViewData::add(QuadTreeNode *node, bool visible)
{ {
int index = mNumEntries++; int index = mNumEntries++;
mEntries.resize(index+1); mEntries.resize(index+1);
Entry& entry = mEntries[index]; Entry& entry = mEntries[index];
if (entry.set(node)) if (entry.set(node, visible))
mChanged = true; mChanged = true;
} }
@ -37,7 +37,7 @@ void ViewData::reset(unsigned int frame)
{ {
// clear any unused entries // clear any unused entries
for (unsigned int i=mNumEntries; i<mEntries.size(); ++i) for (unsigned int i=mNumEntries; i<mEntries.size(); ++i)
mEntries[i].set(NULL); mEntries[i].set(NULL, false);
// reset index for next frame // reset index for next frame
mNumEntries = 0; mNumEntries = 0;
@ -48,19 +48,21 @@ void ViewData::reset(unsigned int frame)
void ViewData::clear() void ViewData::clear()
{ {
for (unsigned int i=0; i<mEntries.size(); ++i) for (unsigned int i=0; i<mEntries.size(); ++i)
mEntries[i].set(NULL); mEntries[i].set(NULL, false);
mNumEntries = 0; mNumEntries = 0;
mFrameLastUsed = 0; mFrameLastUsed = 0;
} }
ViewData::Entry::Entry() ViewData::Entry::Entry()
: mNode(NULL) : mNode(NULL)
, mVisible(true)
{ {
} }
bool ViewData::Entry::set(QuadTreeNode *node) bool ViewData::Entry::set(QuadTreeNode *node, bool visible)
{ {
mVisible = visible;
if (node == mNode) if (node == mNode)
return false; return false;
else else

@ -16,7 +16,7 @@ namespace Terrain
public: public:
ViewData(); ViewData();
void add(QuadTreeNode* node); void add(QuadTreeNode* node, bool visible);
void reset(unsigned int frame); void reset(unsigned int frame);
@ -26,9 +26,10 @@ namespace Terrain
{ {
Entry(); Entry();
bool set(QuadTreeNode* node); bool set(QuadTreeNode* node, bool visible);
QuadTreeNode* mNode; QuadTreeNode* mNode;
bool mVisible;
osg::ref_ptr<osg::Node> mRenderingNode; osg::ref_ptr<osg::Node> mRenderingNode;
}; };

Loading…
Cancel
Save