openscenegraph
CullingSet
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 OSG_CullingSet
15#define OSG_CullingSet 1
16
17#include <osg/Polytope>
18#include <osg/ShadowVolumeOccluder>
19#include <osg/Viewport>
20
21#include <math.h>
22
23
24namespace osg {
25
26#define COMPILE_WITH_SHADOW_OCCLUSION_CULLING
27
28/** A CullingSet class which contains a frustum and a list of occluders. */
29class OSG_EXPORT CullingSet : public Referenced
30{
31
32 public:
33
34 typedef std::pair< osg::ref_ptr<osg::StateSet>, osg::Polytope > StateFrustumPair;
35 typedef std::vector< StateFrustumPair > StateFrustumList;
36
37 CullingSet();
38
39 CullingSet(const CullingSet& cs):
40 Referenced(),
41 _mask(cs._mask),
42 _frustum(cs._frustum),
43 _stateFrustumList(cs._stateFrustumList),
44 _occluderList(cs._occluderList),
45 _pixelSizeVector(cs._pixelSizeVector),
46 _smallFeatureCullingPixelSize(cs._smallFeatureCullingPixelSize)
47 {
48 }
49
50 CullingSet(const CullingSet& cs,const Matrix& matrix, const Vec4& pixelSizeVector):
51 _mask(cs._mask),
52 _frustum(cs._frustum),
53 _stateFrustumList(cs._stateFrustumList),
54 _occluderList(cs._occluderList),
55 _pixelSizeVector(pixelSizeVector),
56 _smallFeatureCullingPixelSize(cs._smallFeatureCullingPixelSize)
57 {
58 _frustum.transformProvidingInverse(matrix);
59 for(OccluderList::iterator itr=_occluderList.begin();
60 itr!=_occluderList.end();
61 ++itr)
62 {
63 itr->transformProvidingInverse(matrix);
64 }
65 }
66
67 CullingSet& operator = (const CullingSet& cs)
68 {
69 if (this==&cs) return *this;
70
71 _mask = cs._mask;
72 _frustum = cs._frustum;
73 _stateFrustumList = cs._stateFrustumList;
74 _occluderList = cs._occluderList;
75 _pixelSizeVector = cs._pixelSizeVector;
76 _smallFeatureCullingPixelSize = cs._smallFeatureCullingPixelSize;
77
78 return *this;
79 }
80
81
82 inline void set(const CullingSet& cs)
83 {
84 _mask = cs._mask;
85 _frustum = cs._frustum;
86 _stateFrustumList = cs._stateFrustumList;
87 _occluderList = cs._occluderList;
88 _pixelSizeVector = cs._pixelSizeVector;
89 _smallFeatureCullingPixelSize = cs._smallFeatureCullingPixelSize;
90 }
91
92 inline void set(const CullingSet& cs,const Matrix& matrix, const Vec4& pixelSizeVector)
93 {
94 _mask = cs._mask;
95 _stateFrustumList = cs._stateFrustumList;
96 _occluderList = cs._occluderList;
97 _pixelSizeVector = pixelSizeVector;
98 _smallFeatureCullingPixelSize = cs._smallFeatureCullingPixelSize;
99
100 //_frustum = cs._frustum;
101 //_frustum.transformProvidingInverse(matrix);
102
103 _frustum.setAndTransformProvidingInverse(cs._frustum,matrix);
104
105 for(StateFrustumList::iterator sitr=_stateFrustumList.begin();
106 sitr!=_stateFrustumList.end();
107 ++sitr)
108 {
109 sitr->second.transformProvidingInverse(matrix);
110 }
111
112 for(OccluderList::iterator oitr=_occluderList.begin();
113 oitr!=_occluderList.end();
114 ++oitr)
115 {
116 oitr->transformProvidingInverse(matrix);
117 }
118
119 }
120
121 typedef std::vector<ShadowVolumeOccluder> OccluderList;
122
123 typedef int Mask;
124
125 enum MaskValues
126 {
127 NO_CULLING = 0x0,
128 VIEW_FRUSTUM_SIDES_CULLING = 0x1,
129 NEAR_PLANE_CULLING = 0x2,
130 FAR_PLANE_CULLING = 0x4,
131 VIEW_FRUSTUM_CULLING = VIEW_FRUSTUM_SIDES_CULLING|
132 NEAR_PLANE_CULLING|
133 FAR_PLANE_CULLING,
134 SMALL_FEATURE_CULLING = 0x8,
135 SHADOW_OCCLUSION_CULLING = 0x10,
136 DEFAULT_CULLING = VIEW_FRUSTUM_SIDES_CULLING|
137 SMALL_FEATURE_CULLING|
138 SHADOW_OCCLUSION_CULLING,
139 ENABLE_ALL_CULLING = VIEW_FRUSTUM_CULLING|
140 SMALL_FEATURE_CULLING|
141 SHADOW_OCCLUSION_CULLING
142 };
143
144 void setCullingMask(Mask mask) { _mask = mask; }
145 Mask getCullingMask() const { return _mask; }
146
147 void setFrustum(Polytope& cv) { _frustum = cv; }
148
149 Polytope& getFrustum() { return _frustum; }
150 const Polytope& getFrustum() const { return _frustum; }
151
152 void addStateFrustum(StateSet* stateset, Polytope& polytope) { _stateFrustumList.push_back(StateFrustumPair(stateset,polytope)); }
153
154 void getStateFrustumList(StateFrustumList& sfl) { _stateFrustumList = sfl; }
155 StateFrustumList& getStateFrustumList() { return _stateFrustumList; }
156
157 void addOccluder(ShadowVolumeOccluder& cv) { _occluderList.push_back(cv); }
158
159 void setPixelSizeVector(const Vec4& v) { _pixelSizeVector = v; }
160
161 Vec4& getPixelSizeVector() { return _pixelSizeVector; }
162 const Vec4& getPixelSizeVector() const { return _pixelSizeVector; }
163
164 /** Threshold at which small features are culled.
165 \param value Bounding volume size in screen space. Default is 2.0. */
166 void setSmallFeatureCullingPixelSize(float value) { _smallFeatureCullingPixelSize=value; }
167
168 float& getSmallFeatureCullingPixelSize() { return _smallFeatureCullingPixelSize; }
169
170 float getSmallFeatureCullingPixelSize() const { return _smallFeatureCullingPixelSize; }
171
172
173 /** Compute the pixel of an object at position v, with specified radius.*/
174 float pixelSize(const Vec3& v,float radius) const { return radius/(v*_pixelSizeVector); }
175
176 /** Compute the pixel of a bounding sphere.*/
177 float pixelSize(const BoundingSphere& bs) const { return bs.radius()/(bs.center()*_pixelSizeVector); }
178
179 /** Compute the pixel of an object at position v, with specified radius. fabs()ed to always be positive. */
180 float clampedPixelSize(const Vec3& v,float radius) const { return fabs(pixelSize(v, radius)); }
181
182 /** Compute the pixel of a bounding sphere. fabs()ed to always be positive. */
183 float clampedPixelSize(const BoundingSphere& bs) const { return fabs(pixelSize(bs)); }
184
185
186 inline bool isCulled(const std::vector<Vec3>& vertices)
187 {
188 if (_mask&VIEW_FRUSTUM_CULLING)
189 {
190 // is it outside the view frustum...
191 if (!_frustum.contains(vertices)) return true;
192 }
193
194 if (_mask&SMALL_FEATURE_CULLING)
195 {
196 }
197
198 if (_mask&SHADOW_OCCLUSION_CULLING)
199 {
200 // is it in one of the shadow occluder volumes.
201 if (!_occluderList.empty())
202 {
203 for(OccluderList::iterator itr=_occluderList.begin();
204 itr!=_occluderList.end();
205 ++itr)
206 {
207 if (itr->contains(vertices)) return true;
208 }
209 }
210 }
211
212 return false;
213 }
214
215 inline bool isCulled(const BoundingBox& bb)
216 {
217 if (_mask&VIEW_FRUSTUM_CULLING)
218 {
219 // is it outside the view frustum...
220 if (!_frustum.contains(bb)) return true;
221 }
222
223 if (_mask&SMALL_FEATURE_CULLING)
224 {
225 }
226
227 if (_mask&SHADOW_OCCLUSION_CULLING)
228 {
229 // is it in one of the shadow occluder volumes.
230 if (!_occluderList.empty())
231 {
232 for(OccluderList::iterator itr=_occluderList.begin();
233 itr!=_occluderList.end();
234 ++itr)
235 {
236 if (itr->contains(bb)) return true;
237 }
238 }
239 }
240
241 return false;
242 }
243
244 inline bool isCulled(const BoundingSphere& bs)
245 {
246 if (_mask&VIEW_FRUSTUM_CULLING)
247 {
248 // is it outside the view frustum...
249 if (!_frustum.contains(bs)) return true;
250 }
251
252 if (_mask&SMALL_FEATURE_CULLING)
253 {
254 if (((bs.center()*_pixelSizeVector)*_smallFeatureCullingPixelSize)>bs.radius()) return true;
255 }
256#ifdef COMPILE_WITH_SHADOW_OCCLUSION_CULLING
257 if (_mask&SHADOW_OCCLUSION_CULLING)
258 {
259 // is it in one of the shadow occluder volumes.
260 if (!_occluderList.empty())
261 {
262 for(OccluderList::iterator itr=_occluderList.begin();
263 itr!=_occluderList.end();
264 ++itr)
265 {
266 if (itr->contains(bs)) return true;
267 }
268 }
269 }
270#endif
271 return false;
272 }
273
274 inline void pushCurrentMask()
275 {
276 _frustum.pushCurrentMask();
277
278 if (!_stateFrustumList.empty())
279 {
280 for(StateFrustumList::iterator itr=_stateFrustumList.begin();
281 itr!=_stateFrustumList.end();
282 ++itr)
283 {
284 itr->second.pushCurrentMask();
285 }
286 }
287
288
289#ifdef COMPILE_WITH_SHADOW_OCCLUSION_CULLING
290 if (!_occluderList.empty())
291 {
292 for(OccluderList::iterator itr=_occluderList.begin();
293 itr!=_occluderList.end();
294 ++itr)
295 {
296 itr->pushCurrentMask();
297 }
298 }
299#endif
300 }
301
302 inline void popCurrentMask()
303 {
304 _frustum.popCurrentMask();
305
306 if (!_stateFrustumList.empty())
307 {
308 for(StateFrustumList::iterator itr=_stateFrustumList.begin();
309 itr!=_stateFrustumList.end();
310 ++itr)
311 {
312 itr->second.popCurrentMask();
313 }
314 }
315
316#ifdef COMPILE_WITH_SHADOW_OCCLUSION_CULLING
317 if (!_occluderList.empty())
318 {
319 for(OccluderList::iterator itr=_occluderList.begin();
320 itr!=_occluderList.end();
321 ++itr)
322 {
323 itr->popCurrentMask();
324 }
325 }
326#endif
327 }
328
329 inline void resetCullingMask()
330 {
331 _frustum.setResultMask(_frustum.getCurrentMask());
332 }
333
334 void disableAndPushOccludersCurrentMask(NodePath& nodePath);
335
336 void popOccludersCurrentMask(NodePath& nodePath);
337
338 static osg::Vec4 computePixelSizeVector(const Viewport& W, const Matrix& P, const Matrix& M);
339
340 virtual ~CullingSet();
341
342
343 protected:
344
345
346 Mask _mask;
347 Polytope _frustum;
348 StateFrustumList _stateFrustumList;
349 OccluderList _occluderList;
350 Vec4 _pixelSizeVector;
351 float _smallFeatureCullingPixelSize;
352
353};
354
355} // end of namespace
356
357#endif