Add preloading implementation to QuadTreeWorld

0.6.1
scrawl 8 years ago
parent 9db71e3f62
commit 4baa795152

@ -108,7 +108,7 @@ void QuadTreeNode::traverse(osg::NodeVisitor &nv)
return; return;
} }
if ((mLodCallback && mLodCallback->isSufficientDetail(this, nv)) || !getNumChildren()) if ((mLodCallback && mLodCallback->isSufficientDetail(this, nv.getEyePoint())) || !getNumChildren())
getView(nv)->add(this, true); getView(nv)->add(this, true);
else else
osg::Group::traverse(nv); osg::Group::traverse(nv);

@ -23,7 +23,7 @@ namespace Terrain
public: public:
virtual ~LodCallback() {} virtual ~LodCallback() {}
virtual bool isSufficientDetail(QuadTreeNode *node, osg::NodeVisitor &nv) = 0; virtual bool isSufficientDetail(QuadTreeNode *node, const osg::Vec3f& eyePoint) = 0;
}; };
class ViewDataMap; class ViewDataMap;

@ -70,9 +70,9 @@ namespace Terrain
class DefaultLodCallback : public LodCallback class DefaultLodCallback : public LodCallback
{ {
public: 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 nativeLodLevel = Log2(static_cast<unsigned int>(node->getSize()*4));
int lodLevel = Log2(static_cast<unsigned int>(dist/2048.0)); 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()) if (!node->hasValidBounds())
return; return;
visible = visible && !cv->isCulled(node->getBoundingBox()); if (nv && nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
bool stopTraversal = (node->getLodCallback() && node->getLodCallback()->isSufficientDetail(node, *cv)) || !node->getNumChildren(); visible = visible && !static_cast<osgUtil::CullVisitor*>(nv)->isCulled(node->getBoundingBox());
bool stopTraversal = (node->getLodCallback() && node->getLodCallback()->isSufficientDetail(node, eyePoint)) || !node->getNumChildren();
if (stopTraversal) if (stopTraversal)
vd->add(node, visible); vd->add(node, visible);
else else
{ {
for (unsigned int i=0; i<node->getNumChildren(); ++i) 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) if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
{ {
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv); osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv);
traverse(mRootNode.get(), vd, cv, true); traverse(mRootNode.get(), vd, cv, cv->getEyePoint(), true);
} }
else else
mRootNode->traverse(nv); mRootNode->traverse(nv);
@ -374,6 +376,31 @@ void QuadTreeWorld::enable(bool enabled)
mRootNode->setNodeMask(enabled ? ~0 : 0); 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); virtual void enable(bool enabled);
View* createView();
void removeView(View* view);
void preload(View* view, const osg::Vec3f& eyePoint);
private: private:
void ensureQuadTreeBuilt(); void ensureQuadTreeBuilt();

@ -12,6 +12,11 @@ ViewData::ViewData()
} }
ViewData::~ViewData()
{
}
void ViewData::add(QuadTreeNode *node, bool visible) void ViewData::add(QuadTreeNode *node, bool visible)
{ {
unsigned int index = mNumEntries++; 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) void ViewDataMap::clearUnusedViews(unsigned int frame)
{ {
for (Map::iterator it = mViews.begin(); it != mViews.end(); ) for (Map::iterator it = mViews.begin(); it != mViews.end(); )

@ -6,15 +6,18 @@
#include <osg/Node> #include <osg/Node>
#include "world.hpp"
namespace Terrain namespace Terrain
{ {
class QuadTreeNode; class QuadTreeNode;
class ViewData class ViewData : public View
{ {
public: public:
ViewData(); ViewData();
~ViewData();
void add(QuadTreeNode* node, bool visible); void add(QuadTreeNode* node, bool visible);
@ -42,6 +45,7 @@ namespace Terrain
Entry& getEntry(unsigned int i); Entry& getEntry(unsigned int i);
bool getPersistent() const { return mPersistent; } bool getPersistent() const { return mPersistent; }
void setPersistent(bool persistent) { mPersistent = persistent; }
osg::Object* getViewer() const { return mViewer.get(); } osg::Object* getViewer() const { return mViewer.get(); }
void setViewer(osg::Object* viewer) { mViewer = viewer; } void setViewer(osg::Object* viewer) { mViewer = viewer; }
@ -66,6 +70,7 @@ namespace Terrain
ViewData* getViewData(osg::Object* viewer, bool ref); ViewData* getViewData(osg::Object* viewer, bool ref);
ViewData* createOrReuseView(); ViewData* createOrReuseView();
void removeView(ViewData* view);
void clearUnusedViews(unsigned int frame); void clearUnusedViews(unsigned int frame);

@ -28,6 +28,19 @@ namespace Terrain
class ChunkManager; class ChunkManager;
class CompositeMapRenderer; 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 * @brief The basic interface for a terrain world. How the terrain chunks are paged and displayed
* is up to the implementation. * is up to the implementation.
@ -66,6 +79,17 @@ namespace Terrain
virtual void enable(bool enabled) {} 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; } Storage* getStorage() { return mStorage; }
protected: protected:

Loading…
Cancel
Save