openscenegraph
CullStack
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_CULLSTACK
15#define OSG_CULLSTACK 1
16
17#include <osg/CullingSet>
18#include <osg/CullSettings>
19#include <osg/Viewport>
20#include <osg/fast_back_stack>
21#include <osg/Transform>
22
23namespace osg {
24
25/** A CullStack class which accumulates the current project, modelview matrices
26and the CullingSet. */
27class OSG_EXPORT CullStack : public osg::CullSettings
28{
29
30 public:
31
32
33 CullStack();
34 CullStack(const CullStack& cs);
35
36 ~CullStack();
37
38 typedef std::vector<ShadowVolumeOccluder> OccluderList;
39
40 void reset();
41
42 void pushCullingSet();
43 void popCullingSet();
44
45 void setOccluderList(const ShadowVolumeOccluderList& svol) { _occluderList = svol; }
46 ShadowVolumeOccluderList& getOccluderList() { return _occluderList; }
47 const ShadowVolumeOccluderList& getOccluderList() const { return _occluderList; }
48
49 void pushViewport(osg::Viewport* viewport);
50 void popViewport();
51
52 void pushProjectionMatrix(osg::RefMatrix* matrix);
53 void popProjectionMatrix();
54
55 void pushModelViewMatrix(osg::RefMatrix* matrix, Transform::ReferenceFrame referenceFrame);
56 void popModelViewMatrix();
57
58 inline float getFrustumVolume() { if (_frustumVolume<0.0f) computeFrustumVolume(); return _frustumVolume; }
59
60
61 /** Compute the pixel size of an object at position v, with specified radius.*/
62 float pixelSize(const Vec3& v,float radius) const
63 {
64 return getCurrentCullingSet().pixelSize(v,radius);
65 }
66
67 /** Compute the pixel size of the bounding sphere.*/
68 float pixelSize(const BoundingSphere& bs) const
69 {
70 return pixelSize(bs.center(),bs.radius());
71 }
72
73 /** Compute the pixel size of an object at position v, with specified radius. fabs()ed to always be positive. */
74 float clampedPixelSize(const Vec3& v,float radius) const
75 {
76 return getCurrentCullingSet().clampedPixelSize(v,radius);
77 }
78
79 /** Compute the pixel size of the bounding sphere. fabs()ed to always be positive. */
80 float clampedPixelSize(const BoundingSphere& bs) const
81 {
82 return clampedPixelSize(bs.center(),bs.radius());
83 }
84
85 inline void disableAndPushOccludersCurrentMask(NodePath& nodePath)
86 {
87 getCurrentCullingSet().disableAndPushOccludersCurrentMask(nodePath);
88 }
89
90 inline void popOccludersCurrentMask(NodePath& nodePath)
91 {
92 getCurrentCullingSet().popOccludersCurrentMask(nodePath);
93 }
94
95 inline bool isCulled(const std::vector<Vec3>& vertices)
96 {
97 return getCurrentCullingSet().isCulled(vertices);
98 }
99
100 inline bool isCulled(const BoundingBox& bb)
101 {
102 return bb.valid() && getCurrentCullingSet().isCulled(bb);
103 }
104
105 inline bool isCulled(const BoundingSphere& bs)
106 {
107 return getCurrentCullingSet().isCulled(bs);
108 }
109
110 inline bool isCulled(const osg::Node& node)
111 {
112 if (node.isCullingActive())
113 {
114 return getCurrentCullingSet().isCulled(node.getBound());
115 }
116 else
117 {
118 getCurrentCullingSet().resetCullingMask();
119 return false;
120 }
121 }
122
123 inline void pushCurrentMask()
124 {
125 getCurrentCullingSet().pushCurrentMask();
126 }
127
128 inline void popCurrentMask()
129 {
130 getCurrentCullingSet().popCurrentMask();
131 }
132
133
134 typedef std::vector< CullingSet > CullingStack;
135
136 inline CullingStack& getClipSpaceCullingStack() { return _clipspaceCullingStack; }
137
138 inline CullingStack& getProjectionCullingStack() { return _projectionCullingStack; }
139
140 inline CullingStack& getModelViewCullingStack() { return _modelviewCullingStack; }
141
142 inline CullingSet& getCurrentCullingSet() { return *_back_modelviewCullingStack; }
143 inline const CullingSet& getCurrentCullingSet() const { return *_back_modelviewCullingStack; }
144
145 inline osg::Viewport* getViewport();
146 inline const osg::Viewport* getViewport() const;
147
148 inline osg::RefMatrix* getModelViewMatrix();
149 inline const osg::RefMatrix* getModelViewMatrix() const;
150
151 inline osg::RefMatrix* getProjectionMatrix();
152 inline const osg::RefMatrix* getProjectionMatrix() const;
153
154 inline osg::Matrix getWindowMatrix() const;
155 inline const osg::RefMatrix* getMVPW();
156
157 inline const osg::Vec3& getReferenceViewPoint() const { return _referenceViewPoints.back(); }
158 inline void pushReferenceViewPoint(const osg::Vec3& viewPoint) { _referenceViewPoints.push_back(viewPoint); }
159 inline void popReferenceViewPoint() { _referenceViewPoints.pop_back(); }
160
161 inline const osg::Vec3& getEyeLocal() const { return _eyePointStack.back(); }
162
163 inline const osg::Vec3& getViewPointLocal() const { return _viewPointStack.back(); }
164
165 inline const osg::Vec3 getUpLocal() const
166 {
167 const osg::Matrix& matrix = *_modelviewStack.back();
168 return osg::Vec3(matrix(0,1),matrix(1,1),matrix(2,1));
169 }
170
171 inline const osg::Vec3 getLookVectorLocal() const
172 {
173 const osg::Matrix& matrix = *_modelviewStack.back();
174 return osg::Vec3(-matrix(0,2),-matrix(1,2),-matrix(2,2));
175 }
176
177 typedef fast_back_stack< ref_ptr<RefMatrix> > MatrixStack;
178
179 MatrixStack& getProjectionStack() { return _projectionStack; }
180 const MatrixStack& getProjectionStack() const { return _projectionStack; }
181
182 MatrixStack& getModelViewStack() { return _modelviewStack; }
183 const MatrixStack& getModelViewStack() const { return _modelviewStack; }
184
185 MatrixStack& getMVPWStack() { return _MVPW_Stack; }
186 const MatrixStack& getMVPWStack() const { return _MVPW_Stack; }
187
188 protected:
189
190 // base set of shadow volume occluder to use in culling.
191 ShadowVolumeOccluderList _occluderList;
192
193
194 MatrixStack _projectionStack;
195
196 MatrixStack _modelviewStack;
197 MatrixStack _MVPW_Stack;
198
199 typedef fast_back_stack<ref_ptr<Viewport> > ViewportStack;
200 ViewportStack _viewportStack;
201
202 typedef fast_back_stack<Vec3> EyePointStack;
203 EyePointStack _referenceViewPoints;
204 EyePointStack _eyePointStack;
205 EyePointStack _viewPointStack;
206
207 CullingStack _clipspaceCullingStack;
208 CullingStack _projectionCullingStack;
209
210 CullingStack _modelviewCullingStack;
211 unsigned int _index_modelviewCullingStack;
212 CullingSet* _back_modelviewCullingStack;
213
214 void computeFrustumVolume();
215 float _frustumVolume;
216
217 unsigned int _bbCornerNear;
218 unsigned int _bbCornerFar;
219
220 ref_ptr<osg::RefMatrix> _identity;
221
222 typedef std::vector< osg::ref_ptr<osg::RefMatrix> > MatrixList;
223 MatrixList _reuseMatrixList;
224 unsigned int _currentReuseMatrixIndex;
225
226 inline osg::RefMatrix* createOrReuseMatrix(const osg::Matrix& value);
227
228
229};
230
231inline osg::Viewport* CullStack::getViewport()
232{
233 return _viewportStack.empty() ? 0 : _viewportStack.back().get();
234}
235
236inline const osg::Viewport* CullStack::getViewport() const
237{
238 return _viewportStack.empty() ? 0 : _viewportStack.back().get();
239}
240
241inline osg::RefMatrix* CullStack::getModelViewMatrix()
242{
243 return _modelviewStack.empty() ? _identity.get() : _modelviewStack.back().get();
244}
245
246inline const osg::RefMatrix* CullStack::getModelViewMatrix() const
247{
248 return _modelviewStack.empty() ? _identity.get() : _modelviewStack.back().get();
249}
250
251inline osg::RefMatrix* CullStack::getProjectionMatrix()
252{
253 return _projectionStack.empty() ? _identity.get() : _projectionStack.back().get();
254}
255
256inline const osg::RefMatrix* CullStack::getProjectionMatrix() const
257{
258 return _projectionStack.empty() ? _identity.get() : _projectionStack.back().get();
259}
260
261inline osg::Matrix CullStack::getWindowMatrix() const
262{
263 if (!_viewportStack.empty())
264 {
265 osg::Viewport* viewport = _viewportStack.back().get();
266 return viewport->computeWindowMatrix();
267 }
268 else
269 {
270 return *_identity;
271 }
272}
273
274inline const osg::RefMatrix* CullStack::getMVPW()
275{
276 if (!_MVPW_Stack.empty())
277 {
278 if (!_MVPW_Stack.back())
279 {
280 _MVPW_Stack.back() = createOrReuseMatrix(*getModelViewMatrix());
281 (*_MVPW_Stack.back()) *= *(getProjectionMatrix());
282 (*_MVPW_Stack.back()) *= getWindowMatrix();
283 }
284 return _MVPW_Stack.back().get();
285 }
286 else
287 {
288 return _identity.get();
289 }
290}
291
292inline RefMatrix* CullStack::createOrReuseMatrix(const osg::Matrix& value)
293{
294 // skip of any already reused matrix.
295 while (_currentReuseMatrixIndex<_reuseMatrixList.size() &&
296 _reuseMatrixList[_currentReuseMatrixIndex]->referenceCount()>1)
297 {
298 ++_currentReuseMatrixIndex;
299 }
300
301 // if still within list, element must be singularly referenced
302 // there return it to be reused.
303 if (_currentReuseMatrixIndex<_reuseMatrixList.size())
304 {
305 RefMatrix* matrix = _reuseMatrixList[_currentReuseMatrixIndex++].get();
306 matrix->set(value);
307 return matrix;
308 }
309
310 // otherwise need to create new matrix.
311 osg::RefMatrix* matrix = new RefMatrix(value);
312 _reuseMatrixList.push_back(matrix);
313 ++_currentReuseMatrixIndex;
314 return matrix;
315}
316
317} // end of namespace
318
319#endif