mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 15:29:55 +00:00
Add preloading implementation to QuadTreeWorld
This commit is contained in:
parent
9db71e3f62
commit
4baa795152
7 changed files with 82 additions and 10 deletions
|
@ -108,7 +108,7 @@ void QuadTreeNode::traverse(osg::NodeVisitor &nv)
|
|||
return;
|
||||
}
|
||||
|
||||
if ((mLodCallback && mLodCallback->isSufficientDetail(this, nv)) || !getNumChildren())
|
||||
if ((mLodCallback && mLodCallback->isSufficientDetail(this, nv.getEyePoint())) || !getNumChildren())
|
||||
getView(nv)->add(this, true);
|
||||
else
|
||||
osg::Group::traverse(nv);
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Terrain
|
|||
public:
|
||||
virtual ~LodCallback() {}
|
||||
|
||||
virtual bool isSufficientDetail(QuadTreeNode *node, osg::NodeVisitor &nv) = 0;
|
||||
virtual bool isSufficientDetail(QuadTreeNode *node, const osg::Vec3f& eyePoint) = 0;
|
||||
};
|
||||
|
||||
class ViewDataMap;
|
||||
|
|
|
@ -70,9 +70,9 @@ namespace Terrain
|
|||
class DefaultLodCallback : public LodCallback
|
||||
{
|
||||
public:
|
||||
virtual bool isSufficientDetail(QuadTreeNode* node, osg::NodeVisitor& nv)
|
||||
virtual bool isSufficientDetail(QuadTreeNode* node, const osg::Vec3f& eyePoint)
|
||||
{
|
||||
float dist = distance(node->getBoundingBox(), nv.getEyePoint());
|
||||
float dist = distance(node->getBoundingBox(), eyePoint);
|
||||
int nativeLodLevel = Log2(static_cast<unsigned int>(node->getSize()*4));
|
||||
int lodLevel = Log2(static_cast<unsigned int>(dist/2048.0));
|
||||
|
||||
|
@ -238,20 +238,22 @@ QuadTreeWorld::~QuadTreeWorld()
|
|||
}
|
||||
|
||||
|
||||
void traverse(QuadTreeNode* node, ViewData* vd, osgUtil::CullVisitor* cv, bool visible)
|
||||
void traverse(QuadTreeNode* node, ViewData* vd, osg::NodeVisitor* nv, const osg::Vec3f& eyePoint, bool visible)
|
||||
{
|
||||
if (!node->hasValidBounds())
|
||||
return;
|
||||
|
||||
visible = visible && !cv->isCulled(node->getBoundingBox());
|
||||
bool stopTraversal = (node->getLodCallback() && node->getLodCallback()->isSufficientDetail(node, *cv)) || !node->getNumChildren();
|
||||
if (nv && nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
|
||||
visible = visible && !static_cast<osgUtil::CullVisitor*>(nv)->isCulled(node->getBoundingBox());
|
||||
|
||||
bool stopTraversal = (node->getLodCallback() && node->getLodCallback()->isSufficientDetail(node, eyePoint)) || !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);
|
||||
traverse(node->getChild(i), vd, nv, eyePoint, visible);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,7 +315,7 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv)
|
|||
if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
|
||||
{
|
||||
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv);
|
||||
traverse(mRootNode.get(), vd, cv, true);
|
||||
traverse(mRootNode.get(), vd, cv, cv->getEyePoint(), true);
|
||||
}
|
||||
else
|
||||
mRootNode->traverse(nv);
|
||||
|
@ -374,6 +376,31 @@ void QuadTreeWorld::enable(bool enabled)
|
|||
mRootNode->setNodeMask(enabled ? ~0 : 0);
|
||||
}
|
||||
|
||||
View* QuadTreeWorld::createView()
|
||||
{
|
||||
ViewData* vd = mViewDataMap->createOrReuseView();
|
||||
vd->setPersistent(true);
|
||||
return vd;
|
||||
}
|
||||
|
||||
void QuadTreeWorld::removeView(View *view)
|
||||
{
|
||||
mViewDataMap->removeView(static_cast<ViewData*>(view));
|
||||
}
|
||||
|
||||
void QuadTreeWorld::preload(View *view, const osg::Vec3f &eyePoint)
|
||||
{
|
||||
ensureQuadTreeBuilt();
|
||||
|
||||
ViewData* vd = static_cast<ViewData*>(view);
|
||||
traverse(mRootNode.get(), vd, NULL, eyePoint, false);
|
||||
|
||||
for (unsigned int i=0; i<vd->getNumEntries(); ++i)
|
||||
{
|
||||
ViewData::Entry& entry = vd->getEntry(i);
|
||||
loadRenderingNode(entry, vd, mChunkManager.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,10 @@ namespace Terrain
|
|||
|
||||
virtual void enable(bool enabled);
|
||||
|
||||
View* createView();
|
||||
void removeView(View* view);
|
||||
void preload(View* view, const osg::Vec3f& eyePoint);
|
||||
|
||||
private:
|
||||
void ensureQuadTreeBuilt();
|
||||
|
||||
|
|
|
@ -12,6 +12,11 @@ ViewData::ViewData()
|
|||
|
||||
}
|
||||
|
||||
ViewData::~ViewData()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ViewData::add(QuadTreeNode *node, bool visible)
|
||||
{
|
||||
unsigned int index = mNumEntries++;
|
||||
|
@ -121,6 +126,13 @@ ViewData *ViewDataMap::createOrReuseView()
|
|||
}
|
||||
}
|
||||
|
||||
void ViewDataMap::removeView(ViewData* vd)
|
||||
{
|
||||
vd->setPersistent(false);
|
||||
vd->clear();
|
||||
mUnusedViews.push_back(vd);
|
||||
}
|
||||
|
||||
void ViewDataMap::clearUnusedViews(unsigned int frame)
|
||||
{
|
||||
for (Map::iterator it = mViews.begin(); it != mViews.end(); )
|
||||
|
|
|
@ -6,15 +6,18 @@
|
|||
|
||||
#include <osg/Node>
|
||||
|
||||
#include "world.hpp"
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
|
||||
class QuadTreeNode;
|
||||
|
||||
class ViewData
|
||||
class ViewData : public View
|
||||
{
|
||||
public:
|
||||
ViewData();
|
||||
~ViewData();
|
||||
|
||||
void add(QuadTreeNode* node, bool visible);
|
||||
|
||||
|
@ -42,6 +45,7 @@ namespace Terrain
|
|||
Entry& getEntry(unsigned int i);
|
||||
|
||||
bool getPersistent() const { return mPersistent; }
|
||||
void setPersistent(bool persistent) { mPersistent = persistent; }
|
||||
|
||||
osg::Object* getViewer() const { return mViewer.get(); }
|
||||
void setViewer(osg::Object* viewer) { mViewer = viewer; }
|
||||
|
@ -66,6 +70,7 @@ namespace Terrain
|
|||
ViewData* getViewData(osg::Object* viewer, bool ref);
|
||||
|
||||
ViewData* createOrReuseView();
|
||||
void removeView(ViewData* view);
|
||||
|
||||
void clearUnusedViews(unsigned int frame);
|
||||
|
||||
|
|
|
@ -28,6 +28,19 @@ namespace Terrain
|
|||
class ChunkManager;
|
||||
class CompositeMapRenderer;
|
||||
|
||||
/**
|
||||
* @brief A View is a collection of rendering objects that are visible from a given camera/intersection.
|
||||
* The base View class is part of the interface for usage in conjunction with preload feature.
|
||||
*/
|
||||
class View
|
||||
{
|
||||
public:
|
||||
virtual ~View() {}
|
||||
|
||||
/// Reset internal structure so that the next addition to the view will override the previous frame's contents.
|
||||
virtual void reset(unsigned int frame) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The basic interface for a terrain world. How the terrain chunks are paged and displayed
|
||||
* is up to the implementation.
|
||||
|
@ -66,6 +79,17 @@ namespace Terrain
|
|||
|
||||
virtual void enable(bool enabled) {}
|
||||
|
||||
/// Create a View to use with preload feature. If a View is returned, it will remain valid until the user calls 'removeView' or the World is destroyed.
|
||||
/// @note Not thread safe.
|
||||
virtual View* createView() { return NULL; }
|
||||
|
||||
/// Remove a View that was previously created with 'createView'.
|
||||
/// @note Not thread safe.
|
||||
virtual void removeView(View* view) {}
|
||||
|
||||
/// @note Thread safe, as long as you do not attempt to load into the same view from multiple threads.
|
||||
virtual void preload(View* view, const osg::Vec3f& eyePoint) {}
|
||||
|
||||
Storage* getStorage() { return mStorage; }
|
||||
|
||||
protected:
|
||||
|
|
Loading…
Reference in a new issue