mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 15:59:54 +00:00
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.
This commit is contained in:
parent
f19a88be9d
commit
8c151364df
5 changed files with 48 additions and 11 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "quadtreeworld.hpp"
|
||||
|
||||
#include <osgUtil/CullVisitor>
|
||||
|
||||
#include <components/sceneutil/workqueue.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)
|
||||
{
|
||||
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<osgUtil::CullVisitor*>(&nv);
|
||||
traverse(mRootNode.get(), vd, cv, true);
|
||||
}
|
||||
else
|
||||
mRootNode->traverse(nv);
|
||||
|
||||
for (unsigned int i=0; i<vd->getNumEntries(); ++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());
|
||||
|
|
|
@ -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<mEntries.size(); ++i)
|
||||
mEntries[i].set(NULL);
|
||||
mEntries[i].set(NULL, false);
|
||||
|
||||
// reset index for next frame
|
||||
mNumEntries = 0;
|
||||
|
@ -48,19 +48,21 @@ void ViewData::reset(unsigned int frame)
|
|||
void ViewData::clear()
|
||||
{
|
||||
for (unsigned int i=0; i<mEntries.size(); ++i)
|
||||
mEntries[i].set(NULL);
|
||||
mEntries[i].set(NULL, false);
|
||||
mNumEntries = 0;
|
||||
mFrameLastUsed = 0;
|
||||
}
|
||||
|
||||
ViewData::Entry::Entry()
|
||||
: mNode(NULL)
|
||||
, mVisible(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool ViewData::Entry::set(QuadTreeNode *node)
|
||||
bool ViewData::Entry::set(QuadTreeNode *node, bool visible)
|
||||
{
|
||||
mVisible = visible;
|
||||
if (node == mNode)
|
||||
return false;
|
||||
else
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace Terrain
|
|||
public:
|
||||
ViewData();
|
||||
|
||||
void add(QuadTreeNode* node);
|
||||
void add(QuadTreeNode* node, bool visible);
|
||||
|
||||
void reset(unsigned int frame);
|
||||
|
||||
|
@ -26,9 +26,10 @@ namespace Terrain
|
|||
{
|
||||
Entry();
|
||||
|
||||
bool set(QuadTreeNode* node);
|
||||
bool set(QuadTreeNode* node, bool visible);
|
||||
|
||||
QuadTreeNode* mNode;
|
||||
bool mVisible;
|
||||
|
||||
osg::ref_ptr<osg::Node> mRenderingNode;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue