199 lines
7.2 KiB
C++
199 lines
7.2 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 getRatio() const { return _ratio; }
|
|
const osg::LineSegment* getOriginalLineSegment() const { return _originalLineSegment.get(); }
|
|
const osg::LineSegment* getLocalLineSegment() const { return _localLineSegment.get(); }
|
|
const osg::NodePath& getNodePath() const { return _nodePath; }
|
|
const osg::Geode* getGeode() const { return _geode.get(); }
|
|
const osg::Drawable* getDrawable() const { return _drawable.get(); }
|
|
const osg::RefMatrix* getMatrix() const { return _matrix.get(); }
|
|
const osg::RefMatrix* getInverseMatrix() const { return _inverse.get(); }
|
|
const VecIndexList& getVecIndexList() const { return _vecIndexList; }
|
|
int getPrimitiveIndex() const { return _primitiveIndex; }
|
|
|
|
|
|
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();
|
|
|
|
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<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;
|
|
|
|
LineSegmentHitListMap _segHitList;
|
|
|
|
LODSelectionMode _lodSelectionMode;
|
|
osg::Vec3 _pseudoEyePoint;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|
|
|