From 265efb85a11c559f7889a88996fb11d6e34e8141 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 19 Apr 2017 18:18:46 +0100 Subject: [PATCH] Initial work on adding KdTree support for PolytopeIntersector. --- include/osg/KdTree | 26 ++++++++ include/osg/Polytope | 3 + include/osgUtil/PolytopeIntersector | 7 +++ src/osg/CMakeLists.txt | 1 + src/osg/Polytope.cpp | 26 ++++++++ src/osgUtil/PolytopeIntersector.cpp | 94 +++++++++++++++++++++++++++++ 6 files changed, 157 insertions(+) create mode 100644 src/osg/Polytope.cpp diff --git a/include/osg/KdTree b/include/osg/KdTree index 2432bed9a..19b9fed22 100644 --- a/include/osg/KdTree +++ b/include/osg/KdTree @@ -158,6 +158,32 @@ class OSG_EXPORT KdTree : public osg::Shape TriangleList& getTriangles() { return _triangles; } const TriangleList& getTriangles() const { return _triangles; } + template + 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; i0) intersect(functor, _kdNodes[node.first]); + if (node.second>0) intersect(functor, _kdNodes[node.second]); + } + } + + protected: diff --git a/include/osg/Polytope b/include/osg/Polytope index 1e9c0c7a7..aa3d10097 100644 --- a/include/osg/Polytope +++ b/include/osg/Polytope @@ -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 diff --git a/include/osgUtil/PolytopeIntersector b/include/osgUtil/PolytopeIntersector index e3c91ee0b..1684db68b 100644 --- a/include/osgUtil/PolytopeIntersector +++ b/include/osgUtil/PolytopeIntersector @@ -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 diff --git a/src/osg/CMakeLists.txt b/src/osg/CMakeLists.txt index 2ab5f3ca1..503eca149 100644 --- a/src/osg/CMakeLists.txt +++ b/src/osg/CMakeLists.txt @@ -338,6 +338,7 @@ SET(TARGET_SRC PolygonMode.cpp PolygonOffset.cpp PolygonStipple.cpp + Polytope.cpp PositionAttitudeTransform.cpp PrimitiveSet.cpp PrimitiveRestartIndex.cpp diff --git a/src/osg/Polytope.cpp b/src/osg/Polytope.cpp new file mode 100644 index 000000000..65e876af2 --- /dev/null +++ b/src/osg/Polytope.cpp @@ -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 +#include + +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; +} diff --git a/src/osgUtil/PolytopeIntersector.cpp b/src/osgUtil/PolytopeIntersector.cpp index 10492d34e..62965b225 100644 --- a/src/osgUtil/PolytopeIntersector.cpp +++ b/src/osgUtil/PolytopeIntersector.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -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 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(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="< func; func.setPolytope( _polytope, _referencePlane ); func.setDimensionMask( _dimensionMask );