root/OpenSceneGraph/trunk/include/osgUtil/CullVisitor @ 13041

Revision 13041, 18.1 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 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_CULLVISITOR
15#define OSGUTIL_CULLVISITOR 1
16
17#include <map>
18#include <vector>
19
20#include <osg/NodeVisitor>
21#include <osg/BoundingSphere>
22#include <osg/BoundingBox>
23#include <osg/Matrix>
24#include <osg/Drawable>
25#include <osg/StateSet>
26#include <osg/State>
27#include <osg/ClearNode>
28#include <osg/Camera>
29#include <osg/Notify>
30
31#include <osg/CullStack>
32
33#include <osgUtil/StateGraph>
34#include <osgUtil/RenderStage>
35
36#include <osg/Vec3>
37
38namespace osgUtil {
39
40/**
41 * Basic NodeVisitor implementation for rendering a scene.
42 * This visitor traverses the scene graph, collecting transparent and
43 * opaque osg::Drawables into a depth sorted transparent bin and a state
44 * sorted opaque bin.  The opaque bin is rendered first, and then the
45 * transparent bin is rendered in order from the furthest osg::Drawable
46 * from the eye to the one nearest the eye.
47 */
48class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor, public osg::CullStack
49{
50    public:
51
52        typedef osg::Matrix::value_type value_type;
53
54
55        CullVisitor();
56
57        /// Copy constructor that does a shallow copy.
58        CullVisitor(const CullVisitor&);
59
60        META_NodeVisitor("osgUtil","CullVisitor")
61
62        /** Create a shallow copy of the CullVisitor, used by CullVisitor::create() to clone the prototype. */
63        virtual CullVisitor* clone() const { return new CullVisitor(*this); }
64
65        /** get the prototype singleton used by CullVisitor::create().*/
66        static osg::ref_ptr<CullVisitor>& prototype();
67
68        /** create a CullVisitor by cloning CullVisitor::prototype().*/
69        static CullVisitor* create();
70
71        virtual void reset();
72
73        struct Identifier : public osg::Referenced
74        {
75            Identifier() {}
76            virtual ~Identifier() {}
77        };
78
79        void setIdentifier(Identifier* identifier) { _identifier = identifier; }
80        Identifier* getIdentifier() { return _identifier.get(); }
81        const Identifier* getIdentifier() const { return _identifier.get(); }
82
83        virtual osg::Vec3 getEyePoint() const { return getEyeLocal(); }
84        virtual osg::Vec3 getViewPoint() const { return getViewPointLocal(); }
85
86        virtual float getDistanceToEyePoint(const osg::Vec3& pos, bool withLODScale) const;
87        virtual float getDistanceFromEyePoint(const osg::Vec3& pos, bool withLODScale) const;
88
89        virtual float getDistanceToViewPoint(const osg::Vec3& pos, bool withLODScale) const;
90
91        virtual void apply(osg::Node&);
92        virtual void apply(osg::Geode& node);
93        virtual void apply(osg::Billboard& node);
94        virtual void apply(osg::LightSource& node);
95        virtual void apply(osg::ClipNode& node);
96        virtual void apply(osg::TexGenNode& node);
97
98        virtual void apply(osg::Group& node);
99        virtual void apply(osg::Transform& node);
100        virtual void apply(osg::Projection& node);
101        virtual void apply(osg::Switch& node);
102        virtual void apply(osg::LOD& node);
103        virtual void apply(osg::ClearNode& node);
104        virtual void apply(osg::Camera& node);
105        virtual void apply(osg::OccluderNode& node);
106        virtual void apply(osg::OcclusionQueryNode& node);
107
108        /** Push state set on the current state group.
109          * If the state exists in a child state group of the current
110          * state group then move the current state group to that child.
111          * Otherwise, create a new state group for the state set, add
112          * it to the current state group then move the current state
113          * group pointer to the new state group.
114          */
115        inline void pushStateSet(const osg::StateSet* ss)
116        {
117            _currentStateGraph = _currentStateGraph->find_or_insert(ss);
118
119            if (_numberOfEncloseOverrideRenderBinDetails==0 && ss->useRenderBinDetails() && !ss->getBinName().empty())
120            {
121                _renderBinStack.push_back(_currentRenderBin);
122
123                _currentRenderBin = ss->getNestRenderBins() ?
124                    _currentRenderBin->find_or_insert(ss->getBinNumber(),ss->getBinName()) :
125                    _currentRenderBin->getStage()->find_or_insert(ss->getBinNumber(),ss->getBinName());
126            }
127
128            if (ss->getRenderBinMode()==osg::StateSet::OVERRIDE_RENDERBIN_DETAILS)
129            {
130                ++_numberOfEncloseOverrideRenderBinDetails;
131            }
132        }
133
134        /** Pop the top state set and hence associated state group.
135          * Move the current state group to the parent of the popped
136          * state group.
137          */
138        inline void popStateSet()
139        {
140            const osg::StateSet* ss = _currentStateGraph->getStateSet();
141            if (ss->getRenderBinMode()==osg::StateSet::OVERRIDE_RENDERBIN_DETAILS)
142            {
143                --_numberOfEncloseOverrideRenderBinDetails;
144            }
145            if (_numberOfEncloseOverrideRenderBinDetails==0 && ss->useRenderBinDetails() && !ss->getBinName().empty())
146            {
147                if (_renderBinStack.empty())
148                {
149                    _currentRenderBin = _currentRenderBin->getStage();
150                }
151                else
152                {
153                    _currentRenderBin = _renderBinStack.back();
154                    _renderBinStack.pop_back();
155                }
156            }
157            _currentStateGraph = _currentStateGraph->_parent;
158        }
159
160        inline void setStateGraph(StateGraph* rg)
161        {
162            _rootStateGraph = rg;
163            _currentStateGraph = rg;
164        }
165
166        inline StateGraph* getRootStateGraph()
167        {
168            return _rootStateGraph.get();
169        }
170
171        inline StateGraph* getCurrentStateGraph()
172        {
173            return _currentStateGraph;
174        }
175
176        inline void setRenderStage(RenderStage* rg)
177        {
178            _rootRenderStage = rg;
179            _currentRenderBin = rg;
180        }
181
182        inline RenderStage* getRenderStage()
183        {
184            return _rootRenderStage.get();
185        }
186
187        inline RenderStage* getCurrentRenderStage()
188        {
189            return _currentRenderBin->getStage();
190        }
191
192        inline osg::Camera* getCurrentCamera()
193        {
194            return getCurrentRenderStage()->getCamera();
195        }
196
197        inline RenderBin* getCurrentRenderBin()
198        {
199            return _currentRenderBin;
200        }
201
202        inline void setCurrentRenderBin(RenderBin* rb)
203        {
204            _currentRenderBin = rb;
205        }
206
207        void setCalculatedNearPlane(value_type value) { _computed_znear = value; }
208        inline value_type getCalculatedNearPlane() const { return _computed_znear; }
209
210        void setCalculatedFarPlane(value_type value) { _computed_zfar = value; }
211        inline value_type getCalculatedFarPlane() const { return _computed_zfar; }
212
213        value_type computeNearestPointInFrustum(const osg::Matrix& matrix, const osg::Polytope::PlaneList& planes,const osg::Drawable& drawable);
214        value_type computeFurthestPointInFrustum(const osg::Matrix& matrix, const osg::Polytope::PlaneList& planes,const osg::Drawable& drawable);
215
216        bool updateCalculatedNearFar(const osg::Matrix& matrix,const osg::BoundingBox& bb);
217
218        bool updateCalculatedNearFar(const osg::Matrix& matrix,const osg::Drawable& drawable, bool isBillboard=false);
219
220        void updateCalculatedNearFar(const osg::Vec3& pos);
221
222        /** Add a drawable to current render graph.*/
223        inline void addDrawable(osg::Drawable* drawable,osg::RefMatrix* matrix);
224
225        /** Add a drawable and depth to current render graph.*/
226        inline void addDrawableAndDepth(osg::Drawable* drawable,osg::RefMatrix* matrix,float depth);
227
228        /** Add an attribute which is positioned relative to the modelview matrix.*/
229        inline void addPositionedAttribute(osg::RefMatrix* matrix,const osg::StateAttribute* attr);
230
231        /** Add an attribute which is positioned relative to the modelview matrix.*/
232        inline void addPositionedTextureAttribute(unsigned int textureUnit, osg::RefMatrix* matrix,const osg::StateAttribute* attr);
233
234
235        /** compute near plane based on the polgon intersection of primtives in near plane candidate list of drawables.
236          * Note, you have to set ComputeNearFarMode to COMPUTE_NEAR_FAR_USING_PRIMITIVES to be able to near plane candidate drawables to be recorded by the cull traversal. */
237        void computeNearPlane();
238
239        /** Re-implement CullStack's popProjectionMatrix() adding clamping of the projection matrix to
240          * the computed near and far.*/
241        virtual void popProjectionMatrix();
242
243
244        /** CullVisitor's default clamping of the projection float matrix to computed near and far values.
245          * Note, do not call this method directly, use clampProjectionMatrix(..) instead, unless you want to bypass the callback.*/
246        virtual bool clampProjectionMatrixImplementation(osg::Matrixf& projection, double& znear, double& zfar) const;
247
248        /** CullVisitor's default clamping of the projection double matrix to computed near and far values.
249          * Note, do not call this method directly, use clampProjectionMatrix(..) instead, unless you want to bypass the callback.*/
250        virtual bool clampProjectionMatrixImplementation(osg::Matrixd& projection, double& znear, double& zfar) const;
251
252        /** Clamp the projection float matrix to computed near and far values, use callback if it exists,
253          * otherwise use default CullVisitor implementation.*/
254        inline bool clampProjectionMatrix(osg::Matrixf& projection, value_type& znear, value_type& zfar) const
255        {
256            double zn = znear;
257            double zf = zfar;
258            bool result = false;
259            if (_clampProjectionMatrixCallback.valid()) result = _clampProjectionMatrixCallback->clampProjectionMatrixImplementation(projection, zn, zf);
260            else result = clampProjectionMatrixImplementation(projection, zn, zf);
261
262            if (result)
263            {
264                znear = zn;
265                zfar = zf;
266                return true;
267            }
268            else
269                return false;
270        }
271
272        /** Clamp the projection double matrix to computed near and far values, use callback if it exists,
273          * otherwise use default CullVisitor implementation.*/
274        inline bool clampProjectionMatrix(osg::Matrixd& projection, value_type& znear, value_type& zfar) const
275        {
276            double zn = znear;
277            double zf = zfar;
278            bool result = false;
279
280            if (_clampProjectionMatrixCallback.valid()) result = _clampProjectionMatrixCallback->clampProjectionMatrixImplementation(projection, zn, zf);
281            else result = clampProjectionMatrixImplementation(projection, zn, zf);
282
283            if (result)
284            {
285                znear = zn;
286                zfar = zf;
287                return true;
288            }
289            else
290                return false;
291        }
292
293
294        void setState(osg::State* state) { _renderInfo.setState(state); }
295        osg::State* getState() { return _renderInfo.getState(); }
296        const osg::State* getState() const { return _renderInfo.getState(); }
297
298        void setRenderInfo(osg::RenderInfo& renderInfo) { _renderInfo = renderInfo; }
299        osg::RenderInfo& getRenderInfo() { return _renderInfo; }
300        const osg::RenderInfo& getRenderInfo() const { return _renderInfo; }
301
302    protected:
303
304        virtual ~CullVisitor();
305
306        /** Prevent unwanted copy operator.*/
307        CullVisitor& operator = (const CullVisitor&) { return *this; }
308
309        inline void handle_cull_callbacks_and_traverse(osg::Node& node)
310        {
311            osg::NodeCallback* callback = node.getCullCallback();
312            if (callback) (*callback)(&node,this);
313            else traverse(node);
314        }
315
316        inline void handle_cull_callbacks_and_accept(osg::Node& node,osg::Node* acceptNode)
317        {
318            osg::NodeCallback* callback = node.getCullCallback();
319            if (callback) (*callback)(&node,this);
320            else acceptNode->accept(*this);
321        }
322
323        osg::ref_ptr<StateGraph>                                   _rootStateGraph;
324        StateGraph*                                                _currentStateGraph;
325
326        osg::ref_ptr<RenderStage>                                   _rootRenderStage;
327        RenderBin*                                                  _currentRenderBin;
328        std::vector<RenderBin*>                                     _renderBinStack;
329
330        unsigned int             _traversalNumber;
331
332        value_type               _computed_znear;
333        value_type               _computed_zfar;
334
335
336        typedef std::vector< osg::ref_ptr<RenderLeaf> > RenderLeafList;
337        RenderLeafList _reuseRenderLeafList;
338        unsigned int _currentReuseRenderLeafIndex;
339
340        inline RenderLeaf* createOrReuseRenderLeaf(osg::Drawable* drawable,osg::RefMatrix* projection,osg::RefMatrix* matrix, float depth=0.0f);
341
342        unsigned int _numberOfEncloseOverrideRenderBinDetails;
343
344        osg::RenderInfo         _renderInfo;
345
346
347        struct MatrixPlanesDrawables
348        {
349            MatrixPlanesDrawables():
350                _drawable(0)
351            {
352            }
353
354            void set(const osg::Matrix& matrix, const osg::Drawable* drawable, const osg::Polytope& frustum)
355            {
356                _matrix = matrix;
357                _drawable = drawable;
358                if (!_planes.empty()) _planes.clear();
359
360                // create a new list of planes from the active walls of the frustum.
361                osg::Polytope::ClippingMask result_mask = frustum.getResultMask();
362                osg::Polytope::ClippingMask selector_mask = 0x1;
363                for(osg::Polytope::PlaneList::const_iterator itr=frustum.getPlaneList().begin();
364                    itr!=frustum.getPlaneList().end();
365                    ++itr)
366                {
367                    if (result_mask&selector_mask) _planes.push_back(*itr);
368                    selector_mask <<= 1;
369                }
370            }
371
372            MatrixPlanesDrawables(const MatrixPlanesDrawables& mpd):
373                _matrix(mpd._matrix),
374                _drawable(mpd._drawable),
375                _planes(mpd._planes) {}
376
377            MatrixPlanesDrawables& operator = (const MatrixPlanesDrawables& mpd)
378            {
379                _matrix = mpd._matrix;
380                _drawable = mpd._drawable;
381                _planes = mpd._planes;
382                return *this;
383            }
384
385            osg::Matrix                 _matrix;
386            const osg::Drawable*        _drawable;
387            osg::Polytope::PlaneList    _planes;
388        };
389
390        typedef std::multimap<value_type, MatrixPlanesDrawables>   DistanceMatrixDrawableMap;
391        DistanceMatrixDrawableMap                                  _nearPlaneCandidateMap;
392        DistanceMatrixDrawableMap                                  _farPlaneCandidateMap;
393
394        osg::ref_ptr<Identifier> _identifier;
395};
396
397inline void CullVisitor::addDrawable(osg::Drawable* drawable,osg::RefMatrix* matrix)
398{
399    if (_currentStateGraph->leaves_empty())
400    {
401        // this is first leaf to be added to StateGraph
402        // and therefore should not already know to current render bin,
403        // so need to add it.
404        _currentRenderBin->addStateGraph(_currentStateGraph);
405    }
406    //_currentStateGraph->addLeaf(new RenderLeaf(drawable,matrix));
407    _currentStateGraph->addLeaf(createOrReuseRenderLeaf(drawable,_projectionStack.back().get(),matrix));
408}
409
410/** Add a drawable and depth to current render graph.*/
411inline void CullVisitor::addDrawableAndDepth(osg::Drawable* drawable,osg::RefMatrix* matrix,float depth)
412{
413    if (_currentStateGraph->leaves_empty())
414    {
415        // this is first leaf to be added to StateGraph
416        // and therefore should not already know to current render bin,
417        // so need to add it.
418        _currentRenderBin->addStateGraph(_currentStateGraph);
419    }
420    //_currentStateGraph->addLeaf(new RenderLeaf(drawable,matrix,depth));
421    _currentStateGraph->addLeaf(createOrReuseRenderLeaf(drawable,_projectionStack.back().get(),matrix,depth));
422}
423
424/** Add an attribute which is positioned relative to the modelview matrix.*/
425inline void CullVisitor::addPositionedAttribute(osg::RefMatrix* matrix,const osg::StateAttribute* attr)
426{
427    _currentRenderBin->getStage()->addPositionedAttribute(matrix,attr);
428}
429
430/** Add an attribute which is positioned relative to the modelview matrix.*/
431inline void CullVisitor::addPositionedTextureAttribute(unsigned int textureUnit, osg::RefMatrix* matrix,const osg::StateAttribute* attr)
432{
433    _currentRenderBin->getStage()->addPositionedTextureAttribute(textureUnit,matrix,attr);
434}
435
436inline RenderLeaf* CullVisitor::createOrReuseRenderLeaf(osg::Drawable* drawable,osg::RefMatrix* projection,osg::RefMatrix* matrix, float depth)
437{
438    // Skips any already reused renderleaf.
439    while (_currentReuseRenderLeafIndex<_reuseRenderLeafList.size() &&
440           _reuseRenderLeafList[_currentReuseRenderLeafIndex]->referenceCount()>1)
441    {
442        osg::notify(osg::NOTICE)<<"Warning:createOrReuseRenderLeaf() skipping multiply refrenced entry."<< std::endl;
443        ++_currentReuseRenderLeafIndex;
444    }
445
446    // If still within list, element must be singularly referenced then return it to be reused.
447    if (_currentReuseRenderLeafIndex<_reuseRenderLeafList.size())
448    {
449        RenderLeaf* renderleaf = _reuseRenderLeafList[_currentReuseRenderLeafIndex++].get();
450        renderleaf->set(drawable,projection,matrix,depth,_traversalNumber++);
451        return renderleaf;
452    }
453
454    // Otherwise need to create new renderleaf.
455    RenderLeaf* renderleaf = new RenderLeaf(drawable,projection,matrix,depth,_traversalNumber++);
456    _reuseRenderLeafList.push_back(renderleaf);
457    ++_currentReuseRenderLeafIndex;
458    return renderleaf;
459}
460
461
462}
463
464#endif
465
Note: See TracBrowser for help on using the browser.