Use the custom LineSegmentIntersector for QuadTree to simplify traversal

code
pull/2325/head
bzzt 6 years ago committed by Andrei Kortunov
parent ce4e8be9ac
commit cb6d27fb12

@ -154,18 +154,21 @@ void QuadTreeNode::traverseTo(ViewData* vd, float size, const osg::Vec2f& center
} }
} }
void QuadTreeNode::traverse(osg::NodeVisitor &nv) void QuadTreeNode::intersect(ViewData* vd, TerrainLineIntersector* intersector)
{ {
if (!hasValidBounds()) if (!hasValidBounds())
return; return;
bool needsUpdate = true; if (!intersector->intersectAndClip(getBoundingBox()))
ViewData* vd = getView(nv, needsUpdate); return;
if ((mLodCallback && mLodCallback->isSufficientDetail(this, distance(vd->getViewPoint()))) || !getNumChildren()) if (getNumChildren() == 0)
vd->add(this, true); vd->add(this, true);
else else
osg::Group::traverse(nv); {
for (unsigned int i=0; i<getNumChildren(); ++i)
getChild(i)->intersect(vd, intersector);
}
} }
void QuadTreeNode::setLodCallback(LodCallback *lodCallback) void QuadTreeNode::setLodCallback(LodCallback *lodCallback)

@ -2,12 +2,31 @@
#define OPENMW_COMPONENTS_TERRAIN_QUADTREENODE_H #define OPENMW_COMPONENTS_TERRAIN_QUADTREENODE_H
#include <osg/Group> #include <osg/Group>
#include <osgUtil/LineSegmentIntersector>
#include "defs.hpp" #include "defs.hpp"
namespace Terrain namespace Terrain
{ {
class TerrainLineIntersector : public osgUtil::LineSegmentIntersector
{
public:
TerrainLineIntersector(osgUtil::LineSegmentIntersector* intersector, osg::Matrix& matrix) :
osgUtil::LineSegmentIntersector(intersector->getStart() * matrix, intersector->getEnd() * matrix)
{
setPrecisionHint(intersector->getPrecisionHint());
_intersectionLimit = intersector->getIntersectionLimit();
_parent = intersector;
}
bool intersectAndClip(const osg::BoundingBox& bbInput)
{
osg::Vec3d s(_start), e(_end);
return osgUtil::LineSegmentIntersector::intersectAndClip(s, e, bbInput);
}
};
enum ChildDirection enum ChildDirection
{ {
NW = 0, NW = 0,
@ -72,9 +91,6 @@ namespace Terrain
/// center in cell coordinates /// center in cell coordinates
const osg::Vec2f& getCenter() const; 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. /// 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. /// 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); void traverse(ViewData* vd, osg::NodeVisitor* nv, const osg::Vec3f& viewPoint, bool visible, float maxDist);
@ -82,6 +98,9 @@ namespace Terrain
/// Traverse to a specific node and add only that node. /// Traverse to a specific node and add only that node.
void traverseTo(ViewData* vd, float size, const osg::Vec2f& center); void traverseTo(ViewData* vd, float size, const osg::Vec2f& center);
/// Adds all leaf nodes which intersect the line from start to end
void intersect(ViewData* vd, TerrainLineIntersector* intersector);
/// Set the Lod callback to use for determining when to stop traversing further down the quad tree. /// Set the Lod callback to use for determining when to stop traversing further down the quad tree.
void setLodCallback(LodCallback* lodCallback); void setLodCallback(LodCallback* lodCallback);

@ -360,7 +360,18 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv)
mRootNode->traverse(vd, &nv, cv->getViewPoint(), true, mViewDistance); mRootNode->traverse(vd, &nv, cv->getViewPoint(), true, mViewDistance);
} }
else else
mRootNode->traverse(nv); {
osgUtil::IntersectionVisitor* iv = static_cast<osgUtil::IntersectionVisitor*>(&nv);
osgUtil::LineSegmentIntersector* lineIntsersector = dynamic_cast<osgUtil::LineSegmentIntersector*>(iv->getIntersector());
if (!lineIntsersector)
throw std::runtime_error("Can not update QuadTreeWorld - the LineSegmentIntersector expected");
osg::Matrix matrix = osg::Matrix::identity();
if (lineIntsersector->getCoordinateFrame() == osgUtil::Intersector::CoordinateFrame::MODEL && iv->getModelMatrix() == 0)
matrix = lineIntsersector->getTransformation(*iv, osgUtil::Intersector::CoordinateFrame::MODEL);
osg::ref_ptr<TerrainLineIntersector> terrainIntersector (new TerrainLineIntersector(lineIntsersector, matrix));
mRootNode->intersect(vd, terrainIntersector);
}
} }
else if (isCullVisitor) else if (isCullVisitor)
{ {

Loading…
Cancel
Save