123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- /* -*-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_INTERSECTIONVISITOR
- #define OSGUTIL_INTERSECTIONVISITOR 1
- #include <osg/NodeVisitor>
- #include <osg/Drawable>
- #include <osgUtil/Export>
- #include <list>
- namespace osgUtil
- {
- // forward declare to allow Intersector to reference it.
- class IntersectionVisitor;
- /** Pure virtual base class for implementing custom intersection technique.
- * To implement a specific intersection technique on must override all
- * the pure virtual methods, concrete examples of how to do this can be seen in
- * the LineSegmentIntersector. */
- class Intersector : public osg::Referenced
- {
- public:
- enum CoordinateFrame
- {
- WINDOW,
- PROJECTION,
- VIEW,
- MODEL
- };
- enum IntersectionLimit
- {
- NO_LIMIT,
- LIMIT_ONE_PER_DRAWABLE,
- LIMIT_ONE,
- LIMIT_NEAREST
- };
- Intersector(CoordinateFrame cf=MODEL, IntersectionLimit il=NO_LIMIT):
- _coordinateFrame(cf),
- _intersectionLimit(il),
- _disabledCount(0),
- _precisionHint(USE_DOUBLE_CALCULATIONS) {}
- void setCoordinateFrame(CoordinateFrame cf) { _coordinateFrame = cf; }
- CoordinateFrame getCoordinateFrame() const { return _coordinateFrame; }
- void setIntersectionLimit(IntersectionLimit limit) { _intersectionLimit = limit; }
- IntersectionLimit getIntersectionLimit() const { return _intersectionLimit; }
- virtual Intersector* clone(osgUtil::IntersectionVisitor& iv) = 0;
- virtual bool enter(const osg::Node& node) = 0;
- virtual void leave() = 0;
- virtual void intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable) = 0;
- virtual void reset() { _disabledCount = 0; }
- virtual bool containsIntersections() = 0;
- inline bool disabled() const { return _disabledCount!=0; }
- inline void incrementDisabledCount() { ++_disabledCount; }
- inline void decrementDisabledCount() { if (_disabledCount>0) --_disabledCount; }
- inline bool reachedLimit() { return _intersectionLimit == LIMIT_ONE && containsIntersections(); }
- /** Hint to precision used in the internal intersections calculations.*/
- enum PrecisionHint
- {
- USE_DOUBLE_CALCULATIONS,
- USE_FLOAT_CALCULATIONS
- };
- /** Set the hint to what precision to use in the intersections calculations.*/
- void setPrecisionHint(PrecisionHint hint) { _precisionHint = hint; }
- /** Get the hint to what precision should be used in the intersections calculations.*/
- PrecisionHint getPrecisionHint() const { return _precisionHint; }
- protected:
- CoordinateFrame _coordinateFrame;
- IntersectionLimit _intersectionLimit;
- unsigned int _disabledCount;
- PrecisionHint _precisionHint;
- };
- /** Concrete class for passing multiple intersectors through the scene graph.
- * To be used in conjunction with IntersectionVisitor. */
- class OSGUTIL_EXPORT IntersectorGroup : public Intersector
- {
- public:
- IntersectorGroup();
- /** Add an Intersector. */
- void addIntersector(Intersector* intersector);
- typedef std::vector< osg::ref_ptr<Intersector> > Intersectors;
- /** Get the list of intersector. */
- Intersectors& getIntersectors() { return _intersectors; }
- /** Clear the list of intersectors.*/
- void clear();
- public:
- virtual Intersector* clone(osgUtil::IntersectionVisitor& iv);
- virtual bool enter(const osg::Node& node);
- virtual void leave();
- virtual void intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable);
- virtual void reset();
- virtual bool containsIntersections();
- protected:
- Intersectors _intersectors;
- };
- /** IntersectionVisitor is used to testing for intersections with the scene, traversing the scene using generic osgUtil::Intersector's to test against the scene.
- * To implement different types of intersection techniques, one implements custom versions of the osgUtil::Intersector, and then
- * pass the constructed intersector to the IntersectionVisitor.*/
- class OSGUTIL_EXPORT IntersectionVisitor : public osg::NodeVisitor
- {
- public:
- /** Callback used to implement the reading of external files, allowing support for paged databases to be
- * integrated with IntersectionVisitor. A concrete implementation can be found in osgDB.
- * Note, this loose coupling approach is required as osgUtil is independent from osgDB where the file reading
- * is implemented, and osgDB itself is dependent upon osgUtil so a circular dependency would result from
- * tighter integration.*/
- struct ReadCallback : public osg::Referenced
- {
- virtual osg::ref_ptr<osg::Node> readNodeFile(const std::string& filename) = 0;
- };
- IntersectionVisitor(Intersector* intersector=0, ReadCallback* readCallback=0);
- META_NodeVisitor(osgUtil, IntersectionVisitor)
- /** Convert 'this' into a osgUtil::IntersectionVisitor pointer if Object is a IntersectionVisitor, otherwise return 0.
- * Equivalent to dynamic_cast<osgUtil::IntersectionVisitor*>(this).*/
- virtual osgUtil::IntersectionVisitor* asIntersectionVisitor() { return this; }
- /** convert 'const this' into a const osgUtil::IntersectionVisitor pointer if Object is a IntersectionVisitor, otherwise return 0.
- * Equivalent to dynamic_cast<const osgUtil::IntersectionVisitor*>(this).*/
- virtual const osgUtil::IntersectionVisitor* asIntersectionVisitor() const { return this; }
- virtual void reset();
- /** Set the intersector that will be used to intersect with the scene, and to store any hits that occur.*/
- void setIntersector(Intersector* intersector);
- /** Get the intersector that will be used to intersect with the scene, and to store any hits that occur.*/
- Intersector* getIntersector() { return _intersectorStack.empty() ? 0 : _intersectorStack.front().get(); }
- /** Get the const intersector that will be used to intersect with the scene, and to store any hits that occur.*/
- const Intersector* getIntersector() const { return _intersectorStack.empty() ? 0 : _intersectorStack.front().get(); }
- /** Set whether the intersectors should use KdTrees when they are found on the scene graph.*/
- void setUseKdTreeWhenAvailable(bool useKdTrees) { _useKdTreesWhenAvailable = useKdTrees; }
- /** Set whether the intersectors should use KdTrees.*/
- bool getUseKdTreeWhenAvailable() const { return _useKdTreesWhenAvailable; }
- void setDoDummyTraversal(bool dummy) { _dummyTraversal = dummy; }
- bool getDoDummyTraversal() const { return _dummyTraversal; }
- /** Set the read callback.*/
- void setReadCallback(ReadCallback* rc) { _readCallback = rc; }
- /** Get the read callback.*/
- ReadCallback* getReadCallback() { return _readCallback.get(); }
- /** Get the const read callback.*/
- const ReadCallback* getReadCallback() const { return _readCallback.get(); }
- void pushWindowMatrix(osg::RefMatrix* matrix) { _windowStack.push_back(matrix); _eyePointDirty = true; }
- void pushWindowMatrix(osg::Viewport* viewport) { _windowStack.push_back(new osg::RefMatrix( viewport->computeWindowMatrix()) ); _eyePointDirty = true; }
- void popWindowMatrix() { _windowStack.pop_back(); _eyePointDirty = true; }
- osg::RefMatrix* getWindowMatrix() { return _windowStack.empty() ? 0 : _windowStack.back().get(); }
- const osg::RefMatrix* getWindowMatrix() const { return _windowStack.empty() ? 0 : _windowStack.back().get(); }
- void pushProjectionMatrix(osg::RefMatrix* matrix) { _projectionStack.push_back(matrix); _eyePointDirty = true; }
- void popProjectionMatrix() { _projectionStack.pop_back(); _eyePointDirty = true; }
- osg::RefMatrix* getProjectionMatrix() { return _projectionStack.empty() ? 0 : _projectionStack.back().get(); }
- const osg::RefMatrix* getProjectionMatrix() const { return _projectionStack.empty() ? 0 : _projectionStack.back().get(); }
- void pushViewMatrix(osg::RefMatrix* matrix) { _viewStack.push_back(matrix); _eyePointDirty = true; }
- void popViewMatrix() { _viewStack.pop_back(); _eyePointDirty = true; }
- osg::RefMatrix* getViewMatrix() { return _viewStack.empty() ? 0 : _viewStack.back().get(); }
- const osg::RefMatrix* getViewMatrix() const { return _viewStack.empty() ? 0 : _viewStack.back().get(); }
- void pushModelMatrix(osg::RefMatrix* matrix) { _modelStack.push_back(matrix); _eyePointDirty = true; }
- void popModelMatrix() { _modelStack.pop_back(); _eyePointDirty = true; }
- osg::RefMatrix* getModelMatrix() { return _modelStack.empty() ? 0 : _modelStack.back().get(); }
- const osg::RefMatrix* getModelMatrix() const { return _modelStack.empty() ? 0 : _modelStack.back().get(); }
- /** Set the reference eye point that is used for nodes that require an eye point to position themselves, such as billboards.*/
- void setReferenceEyePoint(const osg::Vec3& ep) { _referenceEyePoint = ep; _eyePointDirty = true; }
- /** Get the reference eye point.*/
- const osg::Vec3& getReferenceEyePoint() const { return _referenceEyePoint; }
- /** Set the coordinate frame of the reference eye point.*/
- void setReferenceEyePointCoordinateFrame(Intersector::CoordinateFrame cf) { _referenceEyePointCoordinateFrame = cf; }
- /** Get the coordinate frame of the reference eye point.*/
- Intersector::CoordinateFrame getReferenceEyePointCoordinateFrame() const { return _referenceEyePointCoordinateFrame; }
- /** Get the eye point in the local coordinate frame a given traversal point.*/
- virtual osg::Vec3 getEyePoint() const;
- enum LODSelectionMode
- {
- USE_HIGHEST_LEVEL_OF_DETAIL,
- USE_EYE_POINT_FOR_LOD_LEVEL_SELECTION
- };
- /** Set the LOD selection scheme.*/
- void setLODSelectionMode(LODSelectionMode mode) { _lodSelectionMode = mode; }
- /** Get the LOD selection scheme.*/
- LODSelectionMode getLODSelectionMode() const { return _lodSelectionMode; }
- /** 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;
- public:
- virtual void apply(osg::Node& node);
- virtual void apply(osg::Drawable& drawable);
- virtual void apply(osg::Geode& geode);
- virtual void apply(osg::Billboard& geode);
- virtual void apply(osg::Group& group);
- virtual void apply(osg::LOD& lod);
- virtual void apply(osg::PagedLOD& lod);
- virtual void apply(osg::Transform& transform);
- virtual void apply(osg::Projection& projection);
- virtual void apply(osg::Camera& camera);
- protected:
- inline bool enter(const osg::Node& node) { return _intersectorStack.empty() ? false : _intersectorStack.back()->enter(node); }
- inline void leave() { _intersectorStack.back()->leave(); }
- inline void intersect(osg::Drawable* drawable) { _intersectorStack.back()->intersect(*this, drawable); }
- inline void push_clone() { _intersectorStack.push_back ( _intersectorStack.front()->clone(*this) ); }
- inline void pop_clone() { if (_intersectorStack.size()>=2) _intersectorStack.pop_back(); }
- typedef std::list< osg::ref_ptr<Intersector> > IntersectorStack;
- IntersectorStack _intersectorStack;
- bool _useKdTreesWhenAvailable;
- bool _dummyTraversal;
- osg::ref_ptr<ReadCallback> _readCallback;
- typedef std::list< osg::ref_ptr<osg::RefMatrix> > MatrixStack;
- MatrixStack _windowStack;
- MatrixStack _projectionStack;
- MatrixStack _viewStack;
- MatrixStack _modelStack;
- osg::Vec3 _referenceEyePoint;
- Intersector::CoordinateFrame _referenceEyePointCoordinateFrame;
- LODSelectionMode _lodSelectionMode;
- mutable bool _eyePointDirty;
- mutable osg::Vec3 _eyePoint;
- };
- }
- #endif
|