You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
8.2 KiB
228 lines
8.2 KiB
/* -*-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. |
|
*/ |
|
|
|
#ifndef OSGUTIL_INTERSECTVISITOR |
|
#define OSGUTIL_INTERSECTVISITOR 1 |
|
|
|
#include <osg/NodeVisitor> |
|
#include <osg/LineSegment> |
|
#include <osg/Geode> |
|
#include <osg/Matrix> |
|
#include <osg/Transform> |
|
|
|
#include <osgUtil/Export> |
|
|
|
#include <map> |
|
#include <set> |
|
#include <vector> |
|
|
|
namespace osgUtil { |
|
|
|
|
|
class OSGUTIL_EXPORT Hit |
|
{ |
|
/** Deprecated */ |
|
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 (hit._originalLineSegment<_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(); } |
|
osg::NodePath& getNodePath() { return _nodePath; } |
|
const osg::NodePath& getNodePath() const { return _nodePath; } |
|
osg::Geode* getGeode() { return _geode.get(); } |
|
const osg::Geode* getGeode() const { return _geode.get(); } |
|
osg::Drawable* getDrawable() { return _drawable.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; |
|
|
|
|
|
}; |
|
|
|
|
|
/** Deprecated - use IntersectionVisitor instead.*/ |
|
class OSGUTIL_EXPORT IntersectVisitor : public osg::NodeVisitor |
|
{ |
|
public: |
|
|
|
IntersectVisitor(); |
|
virtual ~IntersectVisitor(); |
|
|
|
META_NodeVisitor("osgUtil","IntersectVisitor") |
|
|
|
void reset(); |
|
|
|
/** Add a line segment to use for intersection testing during scene traversal. |
|
* Note, a maximum of 32 line segments can be added to a IntersectVistor, |
|
* adding more than this will result in warning being emitted to the console |
|
* and the excess segments being ignored.*/ |
|
void addLineSegment(osg::LineSegment* seg); |
|
|
|
typedef std::vector<Hit> HitList; |
|
typedef std::map<const osg::LineSegment*,HitList > LineSegmentHitListMap; |
|
|
|
HitList& getHitList(const osg::LineSegment* seg) { return _segHitList[seg]; } |
|
|
|
int getNumHits(const osg::LineSegment* seg) { return _segHitList[seg].size(); } |
|
|
|
LineSegmentHitListMap& getSegHitList() { return _segHitList; } |
|
|
|
bool hits(); |
|
|
|
enum LODSelectionMode |
|
{ |
|
USE_HIGHEST_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; |
|
|
|
|
|
/** 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> _view_matrix; |
|
osg::ref_ptr<osg::RefMatrix> _view_inverse; |
|
osg::ref_ptr<osg::RefMatrix> _model_matrix; |
|
osg::ref_ptr<osg::RefMatrix> _model_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 addLineSegment(osg::LineSegment* seg); |
|
|
|
protected: |
|
|
|
~IntersectState(); |
|
|
|
}; |
|
|
|
bool intersect(osg::Drawable& gset); |
|
|
|
void pushMatrix(osg::RefMatrix* matrix, osg::Transform::ReferenceFrame rf); |
|
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; |
|
}; |
|
|
|
/** Picking intersection visitor specialises the IntersectVistor to allow more convinient handling of mouse picking.*/ |
|
class OSGUTIL_EXPORT PickVisitor : public osgUtil::IntersectVisitor |
|
{ |
|
public: |
|
|
|
PickVisitor(const osg::Viewport* viewport, const osg::Matrixd& proj, const osg::Matrixd& view, float mx, float my); |
|
|
|
void runNestedPickVisitor(osg::Node& node, const osg::Viewport* viewport, const osg::Matrix& proj, const osg::Matrix& view, float mx, float my); |
|
|
|
void apply(osg::Projection& projection); |
|
|
|
void apply(osg::Camera& camera); |
|
|
|
protected: |
|
|
|
float _mx; |
|
float _my; |
|
|
|
osg::ref_ptr<const osg::Viewport> _lastViewport; |
|
osg::Matrixd _lastProjectionMatrix; |
|
osg::Matrixd _lastViewMatrix; |
|
}; |
|
|
|
} |
|
|
|
#endif |
|
|
|
|