Initial work on adding KdTree support for PolytopeIntersector.

This commit is contained in:
Robert Osfield
2017-04-19 18:18:46 +01:00
parent b77301350b
commit 265efb85a1
6 changed files with 157 additions and 0 deletions

View File

@@ -158,6 +158,32 @@ class OSG_EXPORT KdTree : public osg::Shape
TriangleList& getTriangles() { return _triangles; }
const TriangleList& getTriangles() const { return _triangles; }
template<class IntersectFunctor>
void intersect(IntersectFunctor& functor, const KdNode& node) const
{
if (node.first<0)
{
// treat as a leaf
int istart = -node.first-1;
int iend = istart + node.second;
for(int i=istart; i<iend; ++i)
{
const KdTree::Triangle& tri = _triangles[i];
// OSG_NOTICE<<" tri("<<tri.p1<<","<<tri.p2<<","<<tri.p3<<")"<<std::endl;
functor.intersect(_vertices.get(), i, tri.p0, tri.p1, tri.p2);
}
}
else if (functor.intersect(node.bb))
{
if (node.first>0) intersect(functor, _kdNodes[node.first]);
if (node.second>0) intersect(functor, _kdNodes[node.second]);
}
}
protected:

View File

@@ -358,6 +358,9 @@ class OSG_EXPORT Polytope
return true;
}
/** Check whether any part of a triangle is contained within the polytope.*/
bool contains(const osg::Vec3f& v0, const osg::Vec3f& v1, const osg::Vec3f& v2) const;
/** Transform the clipping set by matrix. Note, this operations carries out
* the calculation of the inverse of the matrix since a plane must

View File

@@ -44,6 +44,13 @@ class OSGUTIL_EXPORT PolytopeIntersector : public Intersector
* In VIEW and MODEL coordinates (clip space cube) creates a five sided polytope box that has a front face at 0.0 and sides around box xMin, yMin, xMax, yMax.*/
PolytopeIntersector(CoordinateFrame cf, double xMin, double yMin, double xMax, double yMax);
/** Get the Polytope used by the intersector.*/
osg::Polytope& getPolytope() { return _polytope;}
/** Get the const Polytope used by the intersector.*/
const osg::Polytope& getPolytope() const { return _polytope;}
typedef osg::Plane::Vec3_type Vec3_type;
struct Intersection

View File

@@ -338,6 +338,7 @@ SET(TARGET_SRC
PolygonMode.cpp
PolygonOffset.cpp
PolygonStipple.cpp
Polytope.cpp
PositionAttitudeTransform.cpp
PrimitiveSet.cpp
PrimitiveRestartIndex.cpp

26
src/osg/Polytope.cpp Normal file
View File

@@ -0,0 +1,26 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 20017 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osg/Polytope>
#include <osg/Notify>
using namespace osg;
bool Polytope::contains(const osg::Vec3f& v0, const osg::Vec3f& v1, const osg::Vec3f& v2) const
{
if (contains(v0)) return true;
if (contains(v1)) return true;
if (contains(v2)) return true;
return false;
}

View File

@@ -15,6 +15,7 @@
#include <osgUtil/PolytopeIntersector>
#include <osg/Geometry>
#include <osg/KdTree>
#include <osg/Notify>
#include <osg/io_utils>
#include <osg/TemplatePrimitiveFunctor>
@@ -561,6 +562,69 @@ void PolytopeIntersector::leave()
// do nothing.
}
struct IntersectFunctor
{
IntersectFunctor(osgUtil::PolytopeIntersector* pi):
_polytopeIntersector(pi),
_numHits(0),
_numMisses(0)
{
}
struct Hit
{
Hit(int in_pi, unsigned int in_p0, unsigned int in_p1, unsigned int in_p2):
primitiveIndex(in_pi),
p0(in_p0),
p1(in_p1),
p2(in_p2) {}
Hit():
primitiveIndex(0),
p0(0),
p1(0),
p2(0) {}
int primitiveIndex;
unsigned int p0;
unsigned int p1;
unsigned int p2;
};
typedef std::vector<Hit> Hits;
bool intersect(const osg::BoundingBox& bb)
{
return _polytopeIntersector->getPolytope().contains(bb);
}
bool intersect(const osg::Vec3Array* vertices, int i, unsigned int p0, unsigned int p1, unsigned int p2)
{
if (_polytopeIntersector->getPolytope().contains((*vertices)[p0], (*vertices)[p1], (*vertices)[p2]))
{
++_numHits;
_hits.push_back(Hit(i, p0, p1, p2));
return true;
}
else
{
++_numMisses;
return false;
}
}
osgUtil::PolytopeIntersector* _polytopeIntersector;
Hits _hits;
unsigned int _numHits;
unsigned int _numMisses;
};
void PolytopeIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable)
{
@@ -568,6 +632,36 @@ void PolytopeIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Drawa
if ( !_polytope.contains( drawable->getBoundingBox() ) ) return;
osg::KdTree* kdTree = iv.getUseKdTreeWhenAvailable() ? dynamic_cast<osg::KdTree*>(drawable->getShape()) : 0;
if (kdTree)
{
IntersectFunctor intersector(this);
kdTree->intersect(intersector, kdTree->getNode(0));
for(IntersectFunctor::Hits::iterator itr = intersector._hits.begin();
itr != intersector._hits.end();
++itr)
{
IntersectFunctor::Hit& hit = *itr;
Intersection intersection;
intersection.primitiveIndex = hit.primitiveIndex;
intersection.nodePath = iv.getNodePath();
intersection.drawable = drawable;
intersection.matrix = iv.getModelMatrix();
//OSG_NOTICE<<"Inserting intersection.primitiveIndex="<<intersection.primitiveIndex<<std::endl;
insertIntersection(intersection);
}
//OSG_NOTICE<<"NumHits "<<intersector._numHits<<std::endl;
//OSG_NOTICE<<"NumMisses "<<intersector._numMisses<<std::endl;
return;
}
osg::TemplatePrimitiveFunctor<PolytopeIntersectorUtils::PolytopePrimitiveIntersector> func;
func.setPolytope( _polytope, _referencePlane );
func.setDimensionMask( _dimensionMask );