OpenSceneGraph/include/osgUtil/IntersectVisitor
2004-09-26 18:39:34 +00:00

163 lines
5.3 KiB
C++

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 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 <osg/NodeVisitor>
#include <osg/LineSegment>
#include <osg/Geode>
#include <osg/Matrix>
#include <osgUtil/Export>
#include <map>
#include <set>
#include <vector>
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<int> VecIndexList;
bool operator < (const Hit& hit) const
{
if (_originalLineSegment<hit._originalLineSegment) return true;
if (_originalLineSegment>hit._originalLineSegment) return false;
return _ratio<hit._ratio;
}
const osg::Vec3& getLocalIntersectPoint() const { return _intersectPoint; }
const osg::Vec3& getLocalIntersectNormal() const { return _intersectNormal; }
const osg::Vec3 getWorldIntersectPoint() const { if (_matrix.valid()) return _intersectPoint*(*_matrix); else return _intersectPoint; }
const osg::Vec3 getWorldIntersectNormal() const ;
float _ratio;
osg::ref_ptr<osg::LineSegment> _originalLineSegment;
osg::ref_ptr<osg::LineSegment> _localLineSegment;
osg::NodePath _nodePath;
osg::ref_ptr<osg::Geode> _geode;
osg::ref_ptr<osg::Drawable> _drawable;
osg::ref_ptr<osg::RefMatrix> _matrix;
osg::ref_ptr<osg::RefMatrix> _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<Hit> HitList;
typedef std::map<osg::LineSegment*,HitList > LineSegmentHitListMap;
HitList& getHitList(osg::LineSegment* seg) { return _segHitList[seg]; }
int getNumHits(osg::LineSegment* seg) { return _segHitList[seg].size(); }
bool hits();
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<osg::RefMatrix> _matrix;
osg::ref_ptr<osg::RefMatrix> _inverse;
typedef std::pair<osg::ref_ptr<osg::LineSegment>,osg::ref_ptr<osg::LineSegment> > LineSegmentPair;
typedef std::vector< LineSegmentPair > LineSegmentList;
LineSegmentList _segList;
typedef unsigned int LineSegmentMask;
typedef std::vector<LineSegmentMask> 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<osg::ref_ptr<IntersectState> > IntersectStateStack;
IntersectStateStack _intersectStateStack;
osg::NodePath _nodePath;
LineSegmentHitListMap _segHitList;
};
}
#endif