openscenegraph
IntersectionVisitor
Go to the documentation of this file.
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
14#ifndef OSGUTIL_INTERSECTIONVISITOR
15#define OSGUTIL_INTERSECTIONVISITOR 1
16
17#include <osg/NodeVisitor>
18#include <osg/Drawable>
19#include <osgUtil/Export>
20
21#include <list>
22
23namespace osgUtil
24{
25
26// forward declare to allow Intersector to reference it.
27class IntersectionVisitor;
28
29/** Pure virtual base class for implementing custom intersection technique.
30 * To implement a specific intersection technique on must override all
31 * the pure virtual methods, concrete examples of how to do this can be seen in
32 * the LineSegmentIntersector. */
33class Intersector : public osg::Referenced
34{
35 public:
36
37 enum CoordinateFrame
38 {
39 WINDOW,
40 PROJECTION,
41 VIEW,
42 MODEL
43 };
44
45 enum IntersectionLimit
46 {
47 NO_LIMIT,
48 LIMIT_ONE_PER_DRAWABLE,
49 LIMIT_ONE,
50 LIMIT_NEAREST
51 };
52
53 Intersector(CoordinateFrame cf=MODEL, IntersectionLimit il=NO_LIMIT):
54 _coordinateFrame(cf),
55 _intersectionLimit(il),
56 _disabledCount(0),
57 _precisionHint(USE_DOUBLE_CALCULATIONS) {}
58
59 void setCoordinateFrame(CoordinateFrame cf) { _coordinateFrame = cf; }
60
61 CoordinateFrame getCoordinateFrame() const { return _coordinateFrame; }
62
63 void setIntersectionLimit(IntersectionLimit limit) { _intersectionLimit = limit; }
64
65 IntersectionLimit getIntersectionLimit() const { return _intersectionLimit; }
66
67 virtual Intersector* clone(osgUtil::IntersectionVisitor& iv) = 0;
68
69 virtual bool enter(const osg::Node& node) = 0;
70
71 virtual void leave() = 0;
72
73 virtual void intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable) = 0;
74
75 virtual void reset() { _disabledCount = 0; }
76
77 virtual bool containsIntersections() = 0;
78
79 inline bool disabled() const { return _disabledCount!=0; }
80
81 inline void incrementDisabledCount() { ++_disabledCount; }
82
83 inline void decrementDisabledCount() { if (_disabledCount>0) --_disabledCount; }
84
85 inline bool reachedLimit() { return _intersectionLimit == LIMIT_ONE && containsIntersections(); }
86
87 /** Hint to precision used in the internal intersections calculations.*/
88 enum PrecisionHint
89 {
90 USE_DOUBLE_CALCULATIONS,
91 USE_FLOAT_CALCULATIONS
92 };
93
94 /** Set the hint to what precision to use in the intersections calculations.*/
95 void setPrecisionHint(PrecisionHint hint) { _precisionHint = hint; }
96
97 /** Get the hint to what precision should be used in the intersections calculations.*/
98 PrecisionHint getPrecisionHint() const { return _precisionHint; }
99
100protected:
101
102 CoordinateFrame _coordinateFrame;
103 IntersectionLimit _intersectionLimit;
104 unsigned int _disabledCount;
105 PrecisionHint _precisionHint;
106};
107
108
109/** Concrete class for passing multiple intersectors through the scene graph.
110 * To be used in conjunction with IntersectionVisitor. */
111class OSGUTIL_EXPORT IntersectorGroup : public Intersector
112{
113 public:
114
115 IntersectorGroup();
116
117 /** Add an Intersector. */
118 void addIntersector(Intersector* intersector);
119
120 typedef std::vector< osg::ref_ptr<Intersector> > Intersectors;
121
122 /** Get the list of intersector. */
123 Intersectors& getIntersectors() { return _intersectors; }
124
125 /** Clear the list of intersectors.*/
126 void clear();
127
128 public:
129
130 virtual Intersector* clone(osgUtil::IntersectionVisitor& iv);
131
132 virtual bool enter(const osg::Node& node);
133
134 virtual void leave();
135
136 virtual void intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable);
137
138 virtual void reset();
139
140 virtual bool containsIntersections();
141
142 protected:
143
144 Intersectors _intersectors;
145
146};
147
148/** IntersectionVisitor is used to testing for intersections with the scene, traversing the scene using generic osgUtil::Intersector's to test against the scene.
149 * To implement different types of intersection techniques, one implements custom versions of the osgUtil::Intersector, and then
150 * pass the constructed intersector to the IntersectionVisitor.*/
151class OSGUTIL_EXPORT IntersectionVisitor : public osg::NodeVisitor
152{
153 public:
154
155 /** Callback used to implement the reading of external files, allowing support for paged databases to be
156 * integrated with IntersectionVisitor. A concrete implementation can be found in osgDB.
157 * Note, this loose coupling approach is required as osgUtil is independent from osgDB where the file reading
158 * is implemented, and osgDB itself is dependent upon osgUtil so a circular dependency would result from
159 * tighter integration.*/
160 struct ReadCallback : public osg::Referenced
161 {
162 virtual osg::ref_ptr<osg::Node> readNodeFile(const std::string& filename) = 0;
163 };
164
165
166 IntersectionVisitor(Intersector* intersector=0, ReadCallback* readCallback=0);
167
168 META_NodeVisitor(osgUtil, IntersectionVisitor)
169
170 /** Convert 'this' into a osgUtil::IntersectionVisitor pointer if Object is a IntersectionVisitor, otherwise return 0.
171 * Equivalent to dynamic_cast<osgUtil::IntersectionVisitor*>(this).*/
172 virtual osgUtil::IntersectionVisitor* asIntersectionVisitor() { return this; }
173
174 /** convert 'const this' into a const osgUtil::IntersectionVisitor pointer if Object is a IntersectionVisitor, otherwise return 0.
175 * Equivalent to dynamic_cast<const osgUtil::IntersectionVisitor*>(this).*/
176 virtual const osgUtil::IntersectionVisitor* asIntersectionVisitor() const { return this; }
177
178
179 virtual void reset();
180
181 /** Set the intersector that will be used to intersect with the scene, and to store any hits that occur.*/
182 void setIntersector(Intersector* intersector);
183
184 /** Get the intersector that will be used to intersect with the scene, and to store any hits that occur.*/
185 Intersector* getIntersector() { return _intersectorStack.empty() ? 0 : _intersectorStack.front().get(); }
186
187 /** Get the const intersector that will be used to intersect with the scene, and to store any hits that occur.*/
188 const Intersector* getIntersector() const { return _intersectorStack.empty() ? 0 : _intersectorStack.front().get(); }
189
190
191 /** Set whether the intersectors should use KdTrees when they are found on the scene graph.*/
192 void setUseKdTreeWhenAvailable(bool useKdTrees) { _useKdTreesWhenAvailable = useKdTrees; }
193
194 /** Set whether the intersectors should use KdTrees.*/
195 bool getUseKdTreeWhenAvailable() const { return _useKdTreesWhenAvailable; }
196
197 void setDoDummyTraversal(bool dummy) { _dummyTraversal = dummy; }
198 bool getDoDummyTraversal() const { return _dummyTraversal; }
199
200
201 /** Set the read callback.*/
202 void setReadCallback(ReadCallback* rc) { _readCallback = rc; }
203
204 /** Get the read callback.*/
205 ReadCallback* getReadCallback() { return _readCallback.get(); }
206
207 /** Get the const read callback.*/
208 const ReadCallback* getReadCallback() const { return _readCallback.get(); }
209
210
211 void pushWindowMatrix(osg::RefMatrix* matrix) { _windowStack.push_back(matrix); _eyePointDirty = true; }
212 void pushWindowMatrix(osg::Viewport* viewport) { _windowStack.push_back(new osg::RefMatrix( viewport->computeWindowMatrix()) ); _eyePointDirty = true; }
213 void popWindowMatrix() { _windowStack.pop_back(); _eyePointDirty = true; }
214 osg::RefMatrix* getWindowMatrix() { return _windowStack.empty() ? 0 : _windowStack.back().get(); }
215 const osg::RefMatrix* getWindowMatrix() const { return _windowStack.empty() ? 0 : _windowStack.back().get(); }
216
217 void pushProjectionMatrix(osg::RefMatrix* matrix) { _projectionStack.push_back(matrix); _eyePointDirty = true; }
218 void popProjectionMatrix() { _projectionStack.pop_back(); _eyePointDirty = true; }
219 osg::RefMatrix* getProjectionMatrix() { return _projectionStack.empty() ? 0 : _projectionStack.back().get(); }
220 const osg::RefMatrix* getProjectionMatrix() const { return _projectionStack.empty() ? 0 : _projectionStack.back().get(); }
221
222 void pushViewMatrix(osg::RefMatrix* matrix) { _viewStack.push_back(matrix); _eyePointDirty = true; }
223 void popViewMatrix() { _viewStack.pop_back(); _eyePointDirty = true; }
224 osg::RefMatrix* getViewMatrix() { return _viewStack.empty() ? 0 : _viewStack.back().get(); }
225 const osg::RefMatrix* getViewMatrix() const { return _viewStack.empty() ? 0 : _viewStack.back().get(); }
226
227 void pushModelMatrix(osg::RefMatrix* matrix) { _modelStack.push_back(matrix); _eyePointDirty = true; }
228 void popModelMatrix() { _modelStack.pop_back(); _eyePointDirty = true; }
229 osg::RefMatrix* getModelMatrix() { return _modelStack.empty() ? 0 : _modelStack.back().get(); }
230 const osg::RefMatrix* getModelMatrix() const { return _modelStack.empty() ? 0 : _modelStack.back().get(); }
231
232
233 /** Set the reference eye point that is used for nodes that require an eye point to position themselves, such as billboards.*/
234 void setReferenceEyePoint(const osg::Vec3& ep) { _referenceEyePoint = ep; _eyePointDirty = true; }
235
236 /** Get the reference eye point.*/
237 const osg::Vec3& getReferenceEyePoint() const { return _referenceEyePoint; }
238
239 /** Set the coordinate frame of the reference eye point.*/
240 void setReferenceEyePointCoordinateFrame(Intersector::CoordinateFrame cf) { _referenceEyePointCoordinateFrame = cf; }
241
242 /** Get the coordinate frame of the reference eye point.*/
243 Intersector::CoordinateFrame getReferenceEyePointCoordinateFrame() const { return _referenceEyePointCoordinateFrame; }
244
245
246 /** Get the eye point in the local coordinate frame a given traversal point.*/
247 virtual osg::Vec3 getEyePoint() const;
248
249 enum LODSelectionMode
250 {
251 USE_HIGHEST_LEVEL_OF_DETAIL,
252 USE_EYE_POINT_FOR_LOD_LEVEL_SELECTION
253 };
254
255 /** Set the LOD selection scheme.*/
256 void setLODSelectionMode(LODSelectionMode mode) { _lodSelectionMode = mode; }
257
258 /** Get the LOD selection scheme.*/
259 LODSelectionMode getLODSelectionMode() const { return _lodSelectionMode; }
260
261 /** Get the distance from a point to the eye point, distance value in local coordinate system.
262 * This is calculated using the pseudo-EyePoint (above) when doing LOD calculcations. */
263 virtual float getDistanceToEyePoint(const osg::Vec3& pos, bool withLODScale) const;
264
265 public:
266
267 virtual void apply(osg::Node& node);
268 virtual void apply(osg::Drawable& drawable);
269 virtual void apply(osg::Geode& geode);
270 virtual void apply(osg::Billboard& geode);
271 virtual void apply(osg::Group& group);
272 virtual void apply(osg::LOD& lod);
273 virtual void apply(osg::PagedLOD& lod);
274 virtual void apply(osg::Transform& transform);
275 virtual void apply(osg::Projection& projection);
276 virtual void apply(osg::Camera& camera);
277
278 protected:
279
280 inline bool enter(const osg::Node& node) { return _intersectorStack.empty() ? false : _intersectorStack.back()->enter(node); }
281 inline void leave() { _intersectorStack.back()->leave(); }
282 inline void intersect(osg::Drawable* drawable) { _intersectorStack.back()->intersect(*this, drawable); }
283 inline void push_clone() { _intersectorStack.push_back ( _intersectorStack.front()->clone(*this) ); }
284 inline void pop_clone() { if (_intersectorStack.size()>=2) _intersectorStack.pop_back(); }
285
286 typedef std::list< osg::ref_ptr<Intersector> > IntersectorStack;
287 IntersectorStack _intersectorStack;
288
289 bool _useKdTreesWhenAvailable;
290 bool _dummyTraversal;
291
292 osg::ref_ptr<ReadCallback> _readCallback;
293
294 typedef std::list< osg::ref_ptr<osg::RefMatrix> > MatrixStack;
295 MatrixStack _windowStack;
296 MatrixStack _projectionStack;
297 MatrixStack _viewStack;
298 MatrixStack _modelStack;
299
300 osg::Vec3 _referenceEyePoint;
301 Intersector::CoordinateFrame _referenceEyePointCoordinateFrame;
302 LODSelectionMode _lodSelectionMode;
303
304 mutable bool _eyePointDirty;
305 mutable osg::Vec3 _eyePoint;
306};
307
308}
309
310#endif
311