From ce4e8be9ac468a4297d8f2bf59d846b98190a20f Mon Sep 17 00:00:00 2001 From: bzzt Date: Wed, 20 Feb 2019 13:37:00 +0000 Subject: [PATCH] Move traverse methods to the QuadTreeNode --- components/terrain/quadtreenode.cpp | 45 +++++++++++++++++++++++ components/terrain/quadtreenode.hpp | 8 +++++ components/terrain/quadtreeworld.cpp | 54 +++------------------------- 3 files changed, 57 insertions(+), 50 deletions(-) diff --git a/components/terrain/quadtreenode.cpp b/components/terrain/quadtreenode.cpp index 141803cf7..6072ee904 100644 --- a/components/terrain/quadtreenode.cpp +++ b/components/terrain/quadtreenode.cpp @@ -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(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; itraverse(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; itraverseTo(vd, size, center); + } +} + void QuadTreeNode::traverse(osg::NodeVisitor &nv) { if (!hasValidBounds()) diff --git a/components/terrain/quadtreenode.hpp b/components/terrain/quadtreenode.hpp index 9f7c7bbb7..aca05cfed 100644 --- a/components/terrain/quadtreenode.hpp +++ b/components/terrain/quadtreenode.hpp @@ -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); diff --git a/components/terrain/quadtreeworld.cpp b/components/terrain/quadtreeworld.cpp index 499e268dc..430fcd025 100644 --- a/components/terrain/quadtreeworld.cpp +++ b/components/terrain/quadtreeworld.cpp @@ -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(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; igetNumChildren(); ++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; igetNumChildren(); ++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) { @@ -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); @@ -483,7 +437,7 @@ void QuadTreeWorld::cacheCell(View *view, int x, int y) { ensureQuadTreeBuilt(); ViewData* vd = static_cast(view); - traverseToCell(mRootNode.get(), vd, x, y); + mRootNode->traverseTo(vd, 1, osg::Vec2f(x+0.5f,y+0.5f)); for (unsigned int i=0; igetNumEntries(); ++i) { @@ -503,7 +457,7 @@ void QuadTreeWorld::preload(View *view, const osg::Vec3f &viewPoint, std::atomic ViewData* vd = static_cast(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; igetNumEntries() && !abort; ++i) {