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())
return;
bool needsUpdate = true;
ViewData* vd = getView(nv, needsUpdate);
if (!intersector->intersectAndClip(getBoundingBox()))
return;
if ((mLodCallback && mLodCallback->isSufficientDetail(this, distance(vd->getViewPoint()))) || !getNumChildren())
if (getNumChildren() == 0)
vd->add(this, true);
else
osg::Group::traverse(nv);
{
for (unsigned int i=0; i<getNumChildren(); ++i)
getChild(i)->intersect(vd, intersector);
}
}
void QuadTreeNode::setLodCallback(LodCallback *lodCallback)

@ -2,12 +2,31 @@
#define OPENMW_COMPONENTS_TERRAIN_QUADTREENODE_H
#include <osg/Group>
#include <osgUtil/LineSegmentIntersector>
#include "defs.hpp"
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
{
NW = 0,
@ -72,9 +91,6 @@ 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);
@ -82,6 +98,9 @@ namespace Terrain
/// Traverse to a specific node and add only that node.
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.
void setLodCallback(LodCallback* lodCallback);

@ -360,7 +360,18 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv)
mRootNode->traverse(vd, &nv, cv->getViewPoint(), true, mViewDistance);
}
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)
{

Loading…
Cancel
Save