/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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 #include #include #include #include using namespace osgUtil; namespace PolytopeIntersectorUtils { struct Settings : public osg::Referenced { Settings() : _polytopeIntersector(0), _iv(0), _drawable(0), _limitOneIntersection(false), _primitiveMask( PolytopeIntersector::ALL_PRIMITIVES ) {} osgUtil::PolytopeIntersector* _polytopeIntersector; osgUtil::IntersectionVisitor* _iv; osg::Drawable* _drawable; osg::ref_ptr _vertices; bool _limitOneIntersection; unsigned int _primitiveMask; }; template struct IntersectFunctor { typedef typename Vec3::value_type value_type; typedef Vec3 vec_type; typedef std::vector Vertices; Vertices src, dest; osg::ref_ptr _settings; unsigned int _primitiveIndex; bool _hit; IntersectFunctor(): _primitiveIndex(0), _hit(false) { src.reserve(10); dest.reserve(10); } bool enter(const osg::BoundingBox& bb) { if (_settings->_polytopeIntersector->getPolytope().contains(bb)) { _settings->_polytopeIntersector->getPolytope().pushCurrentMask(); return true; } else { return false; } } void leave() { _settings->_polytopeIntersector->getPolytope().popCurrentMask(); } void addIntersection() { vec_type center(0.0,0.0,0.0); double maxDistance = -DBL_MAX; const osg::Plane& referencePlane = _settings->_polytopeIntersector->getReferencePlane(); for(typename Vertices::iterator itr = src.begin(); itr != src.end(); ++itr) { center += *itr; double d = referencePlane.distance(*itr); if (d>maxDistance) maxDistance = d; } center /= value_type(src.size()); PolytopeIntersector::Intersection intersection; intersection.primitiveIndex = _primitiveIndex; intersection.distance = referencePlane.distance(center); intersection.maxDistance = maxDistance; intersection.nodePath = _settings->_iv->getNodePath(); intersection.drawable = _settings->_drawable; intersection.matrix = _settings->_iv->getModelMatrix(); intersection.localIntersectionPoint = center; if (src.size()=0.0) { dest.push_back(*v_previous); } if (d_previous*d_current<0.0) { // edge crosses plane so insert the vertex between them. value_type distance = d_previous-d_current; value_type r_current = d_previous/distance; vec_type v_new = (*v_previous)*(1.0-r_current) + (*v_current)*r_current; dest.push_back(v_new); } d_previous = d_current; v_previous = v_current; } if (d_previous>=0.0) { dest.push_back(*v_previous); } if (dest.size()<=1) { // OSG_NOTICE<<"Polytope::contains() All points on triangle culled, dest.size()="<