Skip to content

Commit

Permalink
Move traverse methods to the QuadTreeNode
Browse files Browse the repository at this point in the history
  • Loading branch information
bzzt authored and akortunov committed Jun 5, 2019
1 parent a02f730 commit ce4e8be
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 50 deletions.
45 changes: 45 additions & 0 deletions components/terrain/quadtreenode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,51 @@ void QuadTreeNode::initNeighbours()
getChild(i)->initNeighbours();
}

void QuadTreeNode::traverse(ViewData* vd, osg::NodeVisitor* nv, const osg::Vec3f& viewPoint, bool visible, float maxDist)
{
if (!hasValidBounds())
return;

if (nv && nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
visible = visible && !static_cast<osgUtil::CullVisitor*>(nv)->isCulled(mBoundingBox);

float dist = distance(viewPoint);
if (dist > maxDist)
return;

bool stopTraversal = (mLodCallback->isSufficientDetail(this, dist)) || !getNumChildren();

if (stopTraversal)
vd->add(this, visible);
else
{
for (unsigned int i=0; i<getNumChildren(); ++i)
getChild(i)->traverse(vd, nv, viewPoint, visible, maxDist);
}
}

void QuadTreeNode::traverseTo(ViewData* vd, float size, const osg::Vec2f& center)
{
if (!hasValidBounds())
return;

if (getCenter().x() + getSize()/2.f <= center.x() - size/2.f
|| getCenter().x() - getSize()/2.f >= center.x() + size/2.f
|| getCenter().y() + getSize()/2.f <= center.y() - size/2.f
|| getCenter().y() - getSize()/2.f >= center.y() + size/2.f)
return;

bool stopTraversal = (getSize() == size);

if (stopTraversal)
vd->add(this, true);
else
{
for (unsigned int i=0; i<getNumChildren(); ++i)
getChild(i)->traverseTo(vd, size, center);
}
}

void QuadTreeNode::traverse(osg::NodeVisitor &nv)
{
if (!hasValidBounds())
Expand Down
8 changes: 8 additions & 0 deletions components/terrain/quadtreenode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,16 @@ namespace Terrain
/// center in cell coordinates
const osg::Vec2f& getCenter() const;

/// Traverse the child tree and populate the ViewData
virtual void traverse(osg::NodeVisitor& nv);

/// Optimized version of traverse() that doesn't incur the overhead of NodeVisitor double-dispatch or fetching the various variables.
/// Note this doesn't do any culling for non-cull visitors (e.g. intersections) so it shouldn't be used for those.
void traverse(ViewData* vd, osg::NodeVisitor* nv, const osg::Vec3f& viewPoint, bool visible, float maxDist);

/// Traverse to a specific node and add only that node.
void traverseTo(ViewData* vd, float size, const osg::Vec2f& center);

/// Set the Lod callback to use for determining when to stop traversing further down the quad tree.
void setLodCallback(LodCallback* lodCallback);

Expand Down
54 changes: 4 additions & 50 deletions components/terrain/quadtreeworld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,52 +246,6 @@ QuadTreeWorld::~QuadTreeWorld()
mViewDataMap->clear();
}


void traverse(QuadTreeNode* node, ViewData* vd, osg::NodeVisitor* nv, LodCallback* lodCallback, const osg::Vec3f& viewPoint, bool visible, float maxDist)
{
if (!node->hasValidBounds())
return;

if (nv && nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
visible = visible && !static_cast<osgUtil::CullVisitor*>(nv)->isCulled(node->getBoundingBox());

float dist = node->distance(viewPoint);
if (dist > maxDist)
return;

bool stopTraversal = (lodCallback && lodCallback->isSufficientDetail(node, dist)) || !node->getNumChildren();

if (stopTraversal)
vd->add(node, visible);
else
{
for (unsigned int i=0; i<node->getNumChildren(); ++i)
traverse(node->getChild(i), vd, nv, lodCallback, viewPoint, visible, maxDist);
}
}

void traverseToCell(QuadTreeNode* node, ViewData* vd, int cellX, int cellY)
{
if (!node->hasValidBounds())
return;

if (node->getCenter().x() + node->getSize()/2.f <= cellX
|| node->getCenter().x() - node->getSize()/2.f >= cellX+1
|| node->getCenter().y() + node->getSize()/2.f <= cellY
|| node->getCenter().y() - node->getSize()/2.f >= cellY+1)
return;

bool stopTraversal = !node->getNumChildren();

if (stopTraversal)
vd->add(node, true);
else
{
for (unsigned int i=0; i<node->getNumChildren(); ++i)
traverseToCell(node->getChild(i), vd, cellX, cellY);
}
}

/// get the level of vertex detail to render this node at, expressed relative to the native resolution of the data set.
unsigned int getVertexLod(QuadTreeNode* node, int vertexLodMod)
{
Expand Down Expand Up @@ -400,10 +354,10 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv)
int x,y;
stream >> x;
stream >> y;
traverseToCell(mRootNode.get(), vd, x,y);
mRootNode->traverseTo(vd, 1, osg::Vec2f(x+0.5,y+0.5));
}
else
traverse(mRootNode.get(), vd, cv, mRootNode->getLodCallback(), cv->getViewPoint(), true, mViewDistance);
mRootNode->traverse(vd, &nv, cv->getViewPoint(), true, mViewDistance);
}
else
mRootNode->traverse(nv);
Expand Down Expand Up @@ -483,7 +437,7 @@ void QuadTreeWorld::cacheCell(View *view, int x, int y)
{
ensureQuadTreeBuilt();
ViewData* vd = static_cast<ViewData*>(view);
traverseToCell(mRootNode.get(), vd, x, y);
mRootNode->traverseTo(vd, 1, osg::Vec2f(x+0.5f,y+0.5f));

for (unsigned int i=0; i<vd->getNumEntries(); ++i)
{
Expand All @@ -503,7 +457,7 @@ void QuadTreeWorld::preload(View *view, const osg::Vec3f &viewPoint, std::atomic

ViewData* vd = static_cast<ViewData*>(view);
vd->setViewPoint(viewPoint);
traverse(mRootNode.get(), vd, nullptr, mRootNode->getLodCallback(), viewPoint, false, mViewDistance);
mRootNode->traverse(vd, nullptr, viewPoint, false, mViewDistance);

for (unsigned int i=0; i<vd->getNumEntries() && !abort; ++i)
{
Expand Down

0 comments on commit ce4e8be

Please sign in to comment.