Preliminary rendering of QuadTreeWorld

pull/185/head
scrawl 8 years ago
parent e36bdb490e
commit 7d004bf757

@ -5,46 +5,7 @@
#include <osgUtil/CullVisitor>
#include "defs.hpp"
namespace
{
float distance(const osg::BoundingBox& box, const osg::Vec3f& v)
{
if (box.contains(v))
return 0;
else
{
osg::Vec3f maxDist(0,0,0);
if (v.x() < box.xMin())
maxDist.x() = box.xMin() - v.x();
else if (v.x() > box.xMax())
maxDist.x() = v.x() - box.xMax();
if (v.y() < box.yMin())
maxDist.y() = box.yMin() - v.y();
else if (v.y() > box.yMax())
maxDist.y() = v.y() - box.yMax();
if (v.z() < box.zMin())
maxDist.z() = box.zMin() - v.z();
else if (v.z() > box.zMax())
maxDist.z() = v.z() - box.zMax();
return maxDist.length();
}
}
int Log2( int n )
{
assert(n > 0);
int targetlevel = 0;
while (n >>= 1) ++targetlevel;
return targetlevel;
}
}
#include "viewdata.hpp"
namespace Terrain
{
@ -104,6 +65,10 @@ QuadTreeNode::QuadTreeNode(QuadTreeNode* parent, ChildDirection direction, float
mNeighbours[i] = 0;
}
QuadTreeNode::~QuadTreeNode()
{
}
QuadTreeNode* QuadTreeNode::getParent()
{
return mParent;
@ -125,18 +90,47 @@ void QuadTreeNode::initNeighbours()
void QuadTreeNode::traverse(osg::NodeVisitor &nv)
{
if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR)
return;
if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
{
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv);
// do another culling test against bounding box as its much more accurate than the bounding sphere.
if (cv->isCulled(mBoundingBox))
return;
}
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv);
if ((mLodCallback && mLodCallback->isSufficientDetail(this, nv)) || !getNumChildren())
getView(nv)->add(this);
else
osg::Group::traverse(nv);
}
// do another culling test against bounding box as its much more accurate than the bounding sphere.
if (cv->isCulled(mBoundingBox))
return;
void QuadTreeNode::setLodCallback(LodCallback *lodCallback)
{
mLodCallback = lodCallback;
}
//float dist = distance(getBoundingBox(), nv.getEyePoint());
void QuadTreeNode::setViewDataMap(ViewDataMap *map)
{
mViewDataMap = map;
}
osg::Group::traverse(nv);
ViewDataMap *QuadTreeNode::getViewDataMap()
{
return mViewDataMap;
}
ViewData* QuadTreeNode::getView(osg::NodeVisitor &nv)
{
if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
{
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv);
return mViewDataMap->getViewData(cv->getCurrentCamera(), true);
}
else // INTERSECTION_VISITOR
{
return mViewDataMap->getViewData(&nv, false);
}
}
void QuadTreeNode::setBoundingBox(const osg::BoundingBox &boundingBox)

@ -17,10 +17,23 @@ namespace Terrain
Root
};
class QuadTreeNode;
class LodCallback : public osg::Referenced
{
public:
virtual ~LodCallback() {}
virtual bool isSufficientDetail(QuadTreeNode *node, osg::NodeVisitor &nv) = 0;
};
class ViewDataMap;
class ViewData;
class QuadTreeNode : public osg::Group
{
public:
QuadTreeNode(QuadTreeNode* parent, ChildDirection dir, float size, const osg::Vec2f& center);
virtual ~QuadTreeNode();
QuadTreeNode* getParent();
@ -49,6 +62,17 @@ namespace Terrain
virtual void traverse(osg::NodeVisitor& nv);
/// Set the Lod callback to use for determining when to stop traversing further down the quad tree.
void setLodCallback(LodCallback* lodCallback);
/// Set the view data map that the finally used nodes for a given camera/intersection are pushed onto.
void setViewDataMap(ViewDataMap* map);
ViewDataMap* getViewDataMap();
/// Create or retrieve a view for the given traversal.
ViewData* getView(osg::NodeVisitor& nv);
private:
QuadTreeNode* mParent;
@ -59,6 +83,10 @@ namespace Terrain
osg::BoundingBox mBoundingBox;
float mSize;
osg::Vec2f mCenter;
osg::ref_ptr<LodCallback> mLodCallback;
osg::ref_ptr<ViewDataMap> mViewDataMap;
};
}

@ -4,10 +4,8 @@
#include "quadtreenode.hpp"
#include "storage.hpp"
#include <osg/io_utils>
#include <osg/Timer>
#include "viewdata.hpp"
#include "chunkmanager.hpp"
namespace
{
@ -29,11 +27,57 @@ namespace
return 1 << depth;
}
int Log2( unsigned int n )
{
int targetlevel = 0;
while (n >>= 1) ++targetlevel;
return targetlevel;
}
float distance(const osg::BoundingBox& box, const osg::Vec3f& v)
{
if (box.contains(v))
return 0;
else
{
osg::Vec3f maxDist(0,0,0);
if (v.x() < box.xMin())
maxDist.x() = box.xMin() - v.x();
else if (v.x() > box.xMax())
maxDist.x() = v.x() - box.xMax();
if (v.y() < box.yMin())
maxDist.y() = box.yMin() - v.y();
else if (v.y() > box.yMax())
maxDist.y() = v.y() - box.yMax();
if (v.z() < box.zMin())
maxDist.z() = box.zMin() - v.z();
else if (v.z() > box.zMax())
maxDist.z() = v.z() - box.zMax();
return maxDist.length();
}
}
}
namespace Terrain
{
class DefaultLodCallback : public LodCallback
{
public:
virtual bool isSufficientDetail(QuadTreeNode* node, osg::NodeVisitor& nv)
{
float dist = distance(node->getBoundingBox(), nv.getEyePoint());
int nativeLodLevel = Log2(static_cast<unsigned int>(node->getSize()*4));
int lodLevel = Log2(static_cast<unsigned int>(dist/2048.0));
return nativeLodLevel <= lodLevel;
}
};
class RootNode : public QuadTreeNode
{
@ -84,6 +128,7 @@ public:
float centerY = (mMinY+mMaxY)/2.f + (size-origSizeY)/2.f;
mRootNode = new RootNode(size, osg::Vec2f(centerX, centerY));
mRootNode->setViewDataMap(new ViewDataMap);
addChildren(mRootNode);
mRootNode->initNeighbours();
@ -125,6 +170,8 @@ public:
}
osg::ref_ptr<QuadTreeNode> node = new QuadTreeNode(parent, direction, size, center);
node->setLodCallback(new DefaultLodCallback);
node->setViewDataMap(parent->getViewDataMap());
parent->addChild(node);
if (center.x() - size > mMaxX
@ -190,10 +237,28 @@ QuadTreeWorld::~QuadTreeWorld()
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;
mRootNode->traverse(nv);
ViewData* vd = mRootNode->getView(nv);
for (unsigned int i=0; i<vd->getNumEntries(); ++i)
{
ViewData::Entry& entry = vd->getEntry(i);
if (!entry.mRenderingNode)
{
int lod = Log2(int(entry.mNode->getSize()));
entry.mRenderingNode = mChunkManager->getChunk(entry.mNode->getSize(), entry.mNode->getCenter(), lod);
}
entry.mRenderingNode->accept(nv);
}
vd->reset(nv.getTraversalNumber());
mRootNode->getViewDataMap()->clearUnusedViews(nv.getTraversalNumber());
}
void QuadTreeWorld::loadCell(int x, int y)

Loading…
Cancel
Save