/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 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. */ #ifndef OSGUTIL_INTERSECTVISITOR #define OSGUTIL_INTERSECTVISITOR 1 #include #include #include #include #include #include #include #include namespace osgUtil { class OSGUTIL_EXPORT Hit { /** Describes a point in space produced by an intersection of a line with a scene. * A Hit is always on a surface as rendered by the Open Scene Graph scene (usually * a triangle or other primitive, but a special hit handler could return a * different value perhaps: a sphere shape might return a Hit on the true sphere * rather than the approximate tesselated sphere rendered. */ public: Hit(); Hit(const Hit& hit); ~Hit(); Hit& operator = (const Hit& hit); typedef std::vector VecIndexList; bool operator < (const Hit& hit) const { if (_originalLineSegmenthit._originalLineSegment) return false; return _ratio _originalLineSegment; osg::ref_ptr _localLineSegment; osg::NodePath _nodePath; osg::ref_ptr _geode; osg::ref_ptr _drawable; osg::ref_ptr _matrix; osg::ref_ptr _inverse; VecIndexList _vecIndexList; int _primitiveIndex; osg::Vec3 _intersectPoint; osg::Vec3 _intersectNormal; }; /** Basic visitor for ray based collisions of a scene.*/ class OSGUTIL_EXPORT IntersectVisitor : public osg::NodeVisitor { public: IntersectVisitor(); virtual ~IntersectVisitor(); void reset(); /** Add a line segment to use for intersection testing during scene traversal.*/ void addLineSegment(osg::LineSegment* seg); typedef std::vector HitList; typedef std::map LineSegmentHitListMap; HitList& getHitList(osg::LineSegment* seg) { return _segHitList[seg]; } int getNumHits(osg::LineSegment* seg) { return _segHitList[seg].size(); } bool hits(); enum LODSelectionMode { USE_HEIGHEST_LEVEL_OF_DETAIL, USE_SEGMENT_START_POINT_AS_EYE_POINT_FOR_LOD_LEVEL_SELECTION }; void setLODSelectionMode(LODSelectionMode mode) { _lodSelectionMode = mode; } LODSelectionMode getLODSelectionMode() const { return _lodSelectionMode; } /** Set the eye point in local coordinates. * This is a pseudo-EyePoint for billboarding and LOD purposes. * It is copied from the Start point of the most-recently-added segment * of the intersection ray set (IntersectState::_segList). */ void setEyePoint(const osg::Vec3& eye) { _pseudoEyePoint = eye; } virtual osg::Vec3 getEyePoint() const { return _pseudoEyePoint; } /** Get the distance from a point to the eye point, distance value in local coordinate system. * This is calculated using the pseudo-EyePoint (above) when doing LOD calculcations. */ virtual float getDistanceToEyePoint(const osg::Vec3& pos, bool withLODScale) const; virtual void apply(osg::Node&); virtual void apply(osg::Geode& node); virtual void apply(osg::Billboard& node); virtual void apply(osg::Group& node); virtual void apply(osg::Transform& node); virtual void apply(osg::Switch& node); virtual void apply(osg::LOD& node); protected: class IntersectState : public osg::Referenced { public: IntersectState(); osg::ref_ptr _matrix; osg::ref_ptr _inverse; typedef std::pair,osg::ref_ptr > LineSegmentPair; typedef std::vector< LineSegmentPair > LineSegmentList; LineSegmentList _segList; typedef unsigned int LineSegmentMask; typedef std::vector LineSegmentMaskStack; LineSegmentMaskStack _segmentMaskStack; bool isCulled(const osg::BoundingSphere& bs,LineSegmentMask& segMaskOut); bool isCulled(const osg::BoundingBox& bb,LineSegmentMask& segMaskOut); void addLineSegmentPair(osg::LineSegment* first,osg::LineSegment* second) { _segList.push_back(LineSegmentPair(first,second)); } protected: ~IntersectState(); }; bool intersect(osg::Drawable& gset); void pushMatrix(const osg::Matrix& matrix); void popMatrix(); bool enterNode(osg::Node& node); void leaveNode(); typedef std::vector > IntersectStateStack; IntersectStateStack _intersectStateStack; LineSegmentHitListMap _segHitList; LODSelectionMode _lodSelectionMode; osg::Vec3 _pseudoEyePoint; }; } #endif