mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 21:53:51 +00:00
Use the custom LineSegmentIntersector for QuadTree to simplify traversal
code
This commit is contained in:
parent
ce4e8be9ac
commit
cb6d27fb12
3 changed files with 42 additions and 9 deletions
|
@ -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…
Reference in a new issue