IntersectionVisitor 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
  2. *
  3. * This library is open source and may be redistributed and/or modified under
  4. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  5. * (at your option) any later version. The full license is in LICENSE file
  6. * included with this distribution, and on the openscenegraph.org website.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * OpenSceneGraph Public License for more details.
  12. */
  13. #ifndef OSGUTIL_INTERSECTIONVISITOR
  14. #define OSGUTIL_INTERSECTIONVISITOR 1
  15. #include <osg/NodeVisitor>
  16. #include <osg/Drawable>
  17. #include <osgUtil/Export>
  18. #include <list>
  19. namespace osgUtil
  20. {
  21. // forward declare to allow Intersector to reference it.
  22. class IntersectionVisitor;
  23. /** Pure virtual base class for implementing custom intersection technique.
  24. * To implement a specific intersection technique on must override all
  25. * the pure virtual methods, concrete examples of how to do this can be seen in
  26. * the LineSegmentIntersector. */
  27. class Intersector : public osg::Referenced
  28. {
  29. public:
  30. enum CoordinateFrame
  31. {
  32. WINDOW,
  33. PROJECTION,
  34. VIEW,
  35. MODEL
  36. };
  37. enum IntersectionLimit
  38. {
  39. NO_LIMIT,
  40. LIMIT_ONE_PER_DRAWABLE,
  41. LIMIT_ONE,
  42. LIMIT_NEAREST
  43. };
  44. Intersector(CoordinateFrame cf=MODEL, IntersectionLimit il=NO_LIMIT):
  45. _coordinateFrame(cf),
  46. _intersectionLimit(il),
  47. _disabledCount(0),
  48. _precisionHint(USE_DOUBLE_CALCULATIONS) {}
  49. void setCoordinateFrame(CoordinateFrame cf) { _coordinateFrame = cf; }
  50. CoordinateFrame getCoordinateFrame() const { return _coordinateFrame; }
  51. void setIntersectionLimit(IntersectionLimit limit) { _intersectionLimit = limit; }
  52. IntersectionLimit getIntersectionLimit() const { return _intersectionLimit; }
  53. virtual Intersector* clone(osgUtil::IntersectionVisitor& iv) = 0;
  54. virtual bool enter(const osg::Node& node) = 0;
  55. virtual void leave() = 0;
  56. virtual void intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable) = 0;
  57. virtual void reset() { _disabledCount = 0; }
  58. virtual bool containsIntersections() = 0;
  59. inline bool disabled() const { return _disabledCount!=0; }
  60. inline void incrementDisabledCount() { ++_disabledCount; }
  61. inline void decrementDisabledCount() { if (_disabledCount>0) --_disabledCount; }
  62. inline bool reachedLimit() { return _intersectionLimit == LIMIT_ONE && containsIntersections(); }
  63. /** Hint to precision used in the internal intersections calculations.*/
  64. enum PrecisionHint
  65. {
  66. USE_DOUBLE_CALCULATIONS,
  67. USE_FLOAT_CALCULATIONS
  68. };
  69. /** Set the hint to what precision to use in the intersections calculations.*/
  70. void setPrecisionHint(PrecisionHint hint) { _precisionHint = hint; }
  71. /** Get the hint to what precision should be used in the intersections calculations.*/
  72. PrecisionHint getPrecisionHint() const { return _precisionHint; }
  73. protected:
  74. CoordinateFrame _coordinateFrame;
  75. IntersectionLimit _intersectionLimit;
  76. unsigned int _disabledCount;
  77. PrecisionHint _precisionHint;
  78. };
  79. /** Concrete class for passing multiple intersectors through the scene graph.
  80. * To be used in conjunction with IntersectionVisitor. */
  81. class OSGUTIL_EXPORT IntersectorGroup : public Intersector
  82. {
  83. public:
  84. IntersectorGroup();
  85. /** Add an Intersector. */
  86. void addIntersector(Intersector* intersector);
  87. typedef std::vector< osg::ref_ptr<Intersector> > Intersectors;
  88. /** Get the list of intersector. */
  89. Intersectors& getIntersectors() { return _intersectors; }
  90. /** Clear the list of intersectors.*/
  91. void clear();
  92. public:
  93. virtual Intersector* clone(osgUtil::IntersectionVisitor& iv);
  94. virtual bool enter(const osg::Node& node);
  95. virtual void leave();
  96. virtual void intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable);
  97. virtual void reset();
  98. virtual bool containsIntersections();
  99. protected:
  100. Intersectors _intersectors;
  101. };
  102. /** IntersectionVisitor is used to testing for intersections with the scene, traversing the scene using generic osgUtil::Intersector's to test against the scene.
  103. * To implement different types of intersection techniques, one implements custom versions of the osgUtil::Intersector, and then
  104. * pass the constructed intersector to the IntersectionVisitor.*/
  105. class OSGUTIL_EXPORT IntersectionVisitor : public osg::NodeVisitor
  106. {
  107. public:
  108. /** Callback used to implement the reading of external files, allowing support for paged databases to be
  109. * integrated with IntersectionVisitor. A concrete implementation can be found in osgDB.
  110. * Note, this loose coupling approach is required as osgUtil is independent from osgDB where the file reading
  111. * is implemented, and osgDB itself is dependent upon osgUtil so a circular dependency would result from
  112. * tighter integration.*/
  113. struct ReadCallback : public osg::Referenced
  114. {
  115. virtual osg::ref_ptr<osg::Node> readNodeFile(const std::string& filename) = 0;
  116. };
  117. IntersectionVisitor(Intersector* intersector=0, ReadCallback* readCallback=0);
  118. META_NodeVisitor(osgUtil, IntersectionVisitor)
  119. /** Convert 'this' into a osgUtil::IntersectionVisitor pointer if Object is a IntersectionVisitor, otherwise return 0.
  120. * Equivalent to dynamic_cast<osgUtil::IntersectionVisitor*>(this).*/
  121. virtual osgUtil::IntersectionVisitor* asIntersectionVisitor() { return this; }
  122. /** convert 'const this' into a const osgUtil::IntersectionVisitor pointer if Object is a IntersectionVisitor, otherwise return 0.
  123. * Equivalent to dynamic_cast<const osgUtil::IntersectionVisitor*>(this).*/
  124. virtual const osgUtil::IntersectionVisitor* asIntersectionVisitor() const { return this; }
  125. virtual void reset();
  126. /** Set the intersector that will be used to intersect with the scene, and to store any hits that occur.*/
  127. void setIntersector(Intersector* intersector);
  128. /** Get the intersector that will be used to intersect with the scene, and to store any hits that occur.*/
  129. Intersector* getIntersector() { return _intersectorStack.empty() ? 0 : _intersectorStack.front().get(); }
  130. /** Get the const intersector that will be used to intersect with the scene, and to store any hits that occur.*/
  131. const Intersector* getIntersector() const { return _intersectorStack.empty() ? 0 : _intersectorStack.front().get(); }
  132. /** Set whether the intersectors should use KdTrees when they are found on the scene graph.*/
  133. void setUseKdTreeWhenAvailable(bool useKdTrees) { _useKdTreesWhenAvailable = useKdTrees; }
  134. /** Set whether the intersectors should use KdTrees.*/
  135. bool getUseKdTreeWhenAvailable() const { return _useKdTreesWhenAvailable; }
  136. void setDoDummyTraversal(bool dummy) { _dummyTraversal = dummy; }
  137. bool getDoDummyTraversal() const { return _dummyTraversal; }
  138. /** Set the read callback.*/
  139. void setReadCallback(ReadCallback* rc) { _readCallback = rc; }
  140. /** Get the read callback.*/
  141. ReadCallback* getReadCallback() { return _readCallback.get(); }
  142. /** Get the const read callback.*/
  143. const ReadCallback* getReadCallback() const { return _readCallback.get(); }
  144. void pushWindowMatrix(osg::RefMatrix* matrix) { _windowStack.push_back(matrix); _eyePointDirty = true; }
  145. void pushWindowMatrix(osg::Viewport* viewport) { _windowStack.push_back(new osg::RefMatrix( viewport->computeWindowMatrix()) ); _eyePointDirty = true; }
  146. void popWindowMatrix() { _windowStack.pop_back(); _eyePointDirty = true; }
  147. osg::RefMatrix* getWindowMatrix() { return _windowStack.empty() ? 0 : _windowStack.back().get(); }
  148. const osg::RefMatrix* getWindowMatrix() const { return _windowStack.empty() ? 0 : _windowStack.back().get(); }
  149. void pushProjectionMatrix(osg::RefMatrix* matrix) { _projectionStack.push_back(matrix); _eyePointDirty = true; }
  150. void popProjectionMatrix() { _projectionStack.pop_back(); _eyePointDirty = true; }
  151. osg::RefMatrix* getProjectionMatrix() { return _projectionStack.empty() ? 0 : _projectionStack.back().get(); }
  152. const osg::RefMatrix* getProjectionMatrix() const { return _projectionStack.empty() ? 0 : _projectionStack.back().get(); }
  153. void pushViewMatrix(osg::RefMatrix* matrix) { _viewStack.push_back(matrix); _eyePointDirty = true; }
  154. void popViewMatrix() { _viewStack.pop_back(); _eyePointDirty = true; }
  155. osg::RefMatrix* getViewMatrix() { return _viewStack.empty() ? 0 : _viewStack.back().get(); }
  156. const osg::RefMatrix* getViewMatrix() const { return _viewStack.empty() ? 0 : _viewStack.back().get(); }
  157. void pushModelMatrix(osg::RefMatrix* matrix) { _modelStack.push_back(matrix); _eyePointDirty = true; }
  158. void popModelMatrix() { _modelStack.pop_back(); _eyePointDirty = true; }
  159. osg::RefMatrix* getModelMatrix() { return _modelStack.empty() ? 0 : _modelStack.back().get(); }
  160. const osg::RefMatrix* getModelMatrix() const { return _modelStack.empty() ? 0 : _modelStack.back().get(); }
  161. /** Set the reference eye point that is used for nodes that require an eye point to position themselves, such as billboards.*/
  162. void setReferenceEyePoint(const osg::Vec3& ep) { _referenceEyePoint = ep; _eyePointDirty = true; }
  163. /** Get the reference eye point.*/
  164. const osg::Vec3& getReferenceEyePoint() const { return _referenceEyePoint; }
  165. /** Set the coordinate frame of the reference eye point.*/
  166. void setReferenceEyePointCoordinateFrame(Intersector::CoordinateFrame cf) { _referenceEyePointCoordinateFrame = cf; }
  167. /** Get the coordinate frame of the reference eye point.*/
  168. Intersector::CoordinateFrame getReferenceEyePointCoordinateFrame() const { return _referenceEyePointCoordinateFrame; }
  169. /** Get the eye point in the local coordinate frame a given traversal point.*/
  170. virtual osg::Vec3 getEyePoint() const;
  171. enum LODSelectionMode
  172. {
  173. USE_HIGHEST_LEVEL_OF_DETAIL,
  174. USE_EYE_POINT_FOR_LOD_LEVEL_SELECTION
  175. };
  176. /** Set the LOD selection scheme.*/
  177. void setLODSelectionMode(LODSelectionMode mode) { _lodSelectionMode = mode; }
  178. /** Get the LOD selection scheme.*/
  179. LODSelectionMode getLODSelectionMode() const { return _lodSelectionMode; }
  180. /** Get the distance from a point to the eye point, distance value in local coordinate system.
  181. * This is calculated using the pseudo-EyePoint (above) when doing LOD calculcations. */
  182. virtual float getDistanceToEyePoint(const osg::Vec3& pos, bool withLODScale) const;
  183. public:
  184. virtual void apply(osg::Node& node);
  185. virtual void apply(osg::Drawable& drawable);
  186. virtual void apply(osg::Geode& geode);
  187. virtual void apply(osg::Billboard& geode);
  188. virtual void apply(osg::Group& group);
  189. virtual void apply(osg::LOD& lod);
  190. virtual void apply(osg::PagedLOD& lod);
  191. virtual void apply(osg::Transform& transform);
  192. virtual void apply(osg::Projection& projection);
  193. virtual void apply(osg::Camera& camera);
  194. protected:
  195. inline bool enter(const osg::Node& node) { return _intersectorStack.empty() ? false : _intersectorStack.back()->enter(node); }
  196. inline void leave() { _intersectorStack.back()->leave(); }
  197. inline void intersect(osg::Drawable* drawable) { _intersectorStack.back()->intersect(*this, drawable); }
  198. inline void push_clone() { _intersectorStack.push_back ( _intersectorStack.front()->clone(*this) ); }
  199. inline void pop_clone() { if (_intersectorStack.size()>=2) _intersectorStack.pop_back(); }
  200. typedef std::list< osg::ref_ptr<Intersector> > IntersectorStack;
  201. IntersectorStack _intersectorStack;
  202. bool _useKdTreesWhenAvailable;
  203. bool _dummyTraversal;
  204. osg::ref_ptr<ReadCallback> _readCallback;
  205. typedef std::list< osg::ref_ptr<osg::RefMatrix> > MatrixStack;
  206. MatrixStack _windowStack;
  207. MatrixStack _projectionStack;
  208. MatrixStack _viewStack;
  209. MatrixStack _modelStack;
  210. osg::Vec3 _referenceEyePoint;
  211. Intersector::CoordinateFrame _referenceEyePointCoordinateFrame;
  212. LODSelectionMode _lodSelectionMode;
  213. mutable bool _eyePointDirty;
  214. mutable osg::Vec3 _eyePoint;
  215. };
  216. }
  217. #endif