root/OpenSceneGraph/trunk/src/osgUtil/RenderBin.cpp @ 13041

Revision 13041, 18.0 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-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#include <stdlib.h>
14#include <string.h>
15
16#include <osgUtil/RenderBin>
17#include <osgUtil/RenderStage>
18#include <osgUtil/Statistics>
19
20#include <osg/Notify>
21#include <osg/ApplicationUsage>
22#include <osg/AlphaFunc>
23
24#include <algorithm>
25
26using namespace osg;
27using namespace osgUtil;
28
29class RenderBinPrototypeList : osg::depends_on<OpenThreads::Mutex*, osg::Referenced::getGlobalReferencedMutex>,
30                               public osg::Referenced, public std::map< std::string, osg::ref_ptr<RenderBin> >
31{
32    public:
33        RenderBinPrototypeList()
34        {
35            add("RenderBin",new RenderBin(RenderBin::getDefaultRenderBinSortMode()));
36            add("StateSortedBin",new RenderBin(RenderBin::SORT_BY_STATE));
37            add("DepthSortedBin",new RenderBin(RenderBin::SORT_BACK_TO_FRONT));
38            add("SORT_BACK_TO_FRONT",new RenderBin(RenderBin::SORT_BACK_TO_FRONT));
39            add("SORT_FRONT_TO_BACK",new RenderBin(RenderBin::SORT_FRONT_TO_BACK));
40            add("TraversalOrderBin",new RenderBin(RenderBin::TRAVERSAL_ORDER));
41        }
42
43        void add(const std::string& name, RenderBin* bin)
44        {
45            (*this)[name] = bin;
46        }
47
48        ~RenderBinPrototypeList() {}
49};
50
51static RenderBinPrototypeList* renderBinPrototypeList()
52{
53    static osg::ref_ptr<RenderBinPrototypeList> s_renderBinPrototypeList = new  RenderBinPrototypeList;
54    return s_renderBinPrototypeList.get();
55}
56
57RenderBin* RenderBin::getRenderBinPrototype(const std::string& binName)
58{
59    RenderBinPrototypeList* list = renderBinPrototypeList();
60    if (list)
61    {
62        RenderBinPrototypeList::iterator itr = list->find(binName);
63        if (itr != list->end()) return itr->second.get();
64    }
65    return NULL;
66}
67
68RenderBin* RenderBin::createRenderBin(const std::string& binName)
69{
70    RenderBinPrototypeList* list = renderBinPrototypeList();
71    if (list)
72    {
73        RenderBin* prototype = getRenderBinPrototype(binName);
74        if (prototype) return dynamic_cast<RenderBin*>(prototype->clone(osg::CopyOp::DEEP_COPY_ALL));
75    }
76
77    OSG_WARN <<"Warning: RenderBin \""<<binName<<"\" implementation not found, using default RenderBin as a fallback."<<std::endl;
78    return new RenderBin;
79}
80
81void RenderBin::addRenderBinPrototype(const std::string& binName,RenderBin* proto)
82{
83    RenderBinPrototypeList* list = renderBinPrototypeList();
84    if (list && proto)
85    {
86        (*list)[binName] = proto;
87    }
88}
89
90void RenderBin::removeRenderBinPrototype(RenderBin* proto)
91{
92    RenderBinPrototypeList* list = renderBinPrototypeList();
93    if (list && proto)
94    {
95        for(RenderBinPrototypeList::iterator itr = list->begin();
96            itr != list->end();
97            ++itr)
98        {
99            if (itr->second == proto)
100            {
101                // OSG_NOTICE<<"Found protype, now erasing "<<itr->first<<std::endl;
102                list->erase(itr);
103                return;
104            }
105        }
106    }
107    // OSG_NOTICE<<"Not found protype"<<std::endl;
108}
109
110static bool s_defaultBinSortModeInitialized = false;
111static RenderBin::SortMode s_defaultBinSortMode = RenderBin::SORT_BY_STATE;
112static osg::ApplicationUsageProxy RenderBin_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_DEFAULT_BIN_SORT_MODE <type>","SORT_BY_STATE | SORT_BY_STATE_THEN_FRONT_TO_BACK | SORT_FRONT_TO_BACK | SORT_BACK_TO_FRONT");
113
114void RenderBin::setDefaultRenderBinSortMode(RenderBin::SortMode mode)
115{
116    s_defaultBinSortModeInitialized = true;
117    s_defaultBinSortMode = mode;
118}
119
120
121RenderBin::SortMode RenderBin::getDefaultRenderBinSortMode()
122{
123    if (!s_defaultBinSortModeInitialized)
124    {
125        s_defaultBinSortModeInitialized = true;
126
127        const char* str = getenv("OSG_DEFAULT_BIN_SORT_MODE");
128        if (str)
129        {
130            if (strcmp(str,"SORT_BY_STATE")==0) s_defaultBinSortMode = RenderBin::SORT_BY_STATE;
131            else if (strcmp(str,"SORT_BY_STATE_THEN_FRONT_TO_BACK")==0) s_defaultBinSortMode = RenderBin::SORT_BY_STATE_THEN_FRONT_TO_BACK;
132            else if (strcmp(str,"SORT_FRONT_TO_BACK")==0) s_defaultBinSortMode = RenderBin::SORT_FRONT_TO_BACK;
133            else if (strcmp(str,"SORT_BACK_TO_FRONT")==0) s_defaultBinSortMode = RenderBin::SORT_BACK_TO_FRONT;
134            else if (strcmp(str,"TRAVERSAL_ORDER")==0) s_defaultBinSortMode = RenderBin::TRAVERSAL_ORDER;
135        }
136    }
137
138    return s_defaultBinSortMode;
139}
140
141RenderBin::RenderBin()
142{
143    _binNum = 0;
144    _parent = NULL;
145    _stage = NULL;
146    _sorted = false;
147    _sortMode = getDefaultRenderBinSortMode();
148}
149
150RenderBin::RenderBin(SortMode mode)
151{
152    _binNum = 0;
153    _parent = NULL;
154    _stage = NULL;
155    _sorted = false;
156    _sortMode = mode;
157
158#if 1
159    if (_sortMode==SORT_BACK_TO_FRONT)
160    {
161        _stateset  = new osg::StateSet;
162        _stateset->setThreadSafeRefUnref(true);
163
164         // set up an alphafunc by default to speed up blending operations.
165#ifdef OSG_GL_FIXED_FUNCTION_AVAILABLE
166        osg::AlphaFunc* alphafunc = new osg::AlphaFunc;
167        alphafunc->setFunction(osg::AlphaFunc::GREATER,0.0f);
168        alphafunc->setThreadSafeRefUnref(true);
169
170        _stateset->setAttributeAndModes(alphafunc, osg::StateAttribute::ON);
171#endif
172    }
173#endif
174}
175
176RenderBin::RenderBin(const RenderBin& rhs,const CopyOp& copyop):
177        Object(rhs,copyop),
178        _binNum(rhs._binNum),
179        _parent(rhs._parent),
180        _stage(rhs._stage),
181        _bins(rhs._bins),
182        _stateGraphList(rhs._stateGraphList),
183        _renderLeafList(rhs._renderLeafList),
184        _sorted(rhs._sorted),
185        _sortMode(rhs._sortMode),
186        _sortCallback(rhs._sortCallback),
187        _drawCallback(rhs._drawCallback),
188        _stateset(rhs._stateset)
189{
190
191}
192
193RenderBin::~RenderBin()
194{
195}
196
197void RenderBin::reset()
198{
199    _stateGraphList.clear();
200    _renderLeafList.clear();
201    _bins.clear();
202    _sorted = false;
203}
204
205void RenderBin::sort()
206{
207    if (_sorted) return;
208
209    for(RenderBinList::iterator itr = _bins.begin();
210        itr!=_bins.end();
211        ++itr)
212    {
213        itr->second->sort();
214    }
215
216    if (_sortCallback.valid())
217    {
218        _sortCallback->sortImplementation(this);
219    }
220    else sortImplementation();
221
222    _sorted = true;
223}
224
225void RenderBin::setSortMode(SortMode mode)
226{
227    _sortMode = mode;
228}
229
230void RenderBin::sortImplementation()
231{
232    switch(_sortMode)
233    {
234        case(SORT_BY_STATE):
235            sortByState();
236            break;
237        case(SORT_BY_STATE_THEN_FRONT_TO_BACK):
238            sortByStateThenFrontToBack();
239            break;
240        case(SORT_FRONT_TO_BACK):
241            sortFrontToBack();
242            break;
243        case(SORT_BACK_TO_FRONT):
244            sortBackToFront();
245            break;
246        case(TRAVERSAL_ORDER):
247            sortTraversalOrder();
248            break;
249    }
250}
251
252struct SortByStateFunctor
253{
254    bool operator() (const StateGraph* lhs,const StateGraph* rhs) const
255    {
256        return (*(lhs->_stateset)<*(rhs->_stateset));
257    }
258};
259
260void RenderBin::sortByState()
261{
262    //OSG_NOTICE<<"sortByState()"<<std::endl;
263    // actually we'll do nothing right now, as fine grained sorting by state
264    // appears to cost more to do than it saves in draw.  The contents of
265    // the StateGraph leaves is already coarse grained sorted, this
266    // sorting is as a function of the cull traversal.
267    // cout << "doing sortByState "<<this<<endl;
268}
269
270
271struct StateGraphFrontToBackSortFunctor
272{
273    bool operator() (const StateGraph* lhs,const StateGraph* rhs) const
274    {
275        return (lhs->_minimumDistance<rhs->_minimumDistance);
276    }
277};
278
279void RenderBin::sortByStateThenFrontToBack()
280{
281    for(StateGraphList::iterator itr=_stateGraphList.begin();
282        itr!=_stateGraphList.end();
283        ++itr)
284    {
285        (*itr)->sortFrontToBack();
286        (*itr)->getMinimumDistance();
287    }
288    std::sort(_stateGraphList.begin(),_stateGraphList.end(),StateGraphFrontToBackSortFunctor());
289}
290
291struct FrontToBackSortFunctor
292{
293    bool operator() (const RenderLeaf* lhs,const RenderLeaf* rhs) const
294    {
295        return (lhs->_depth<rhs->_depth);
296    }
297};
298
299
300void RenderBin::sortFrontToBack()
301{
302    copyLeavesFromStateGraphListToRenderLeafList();
303
304    // now sort the list into acending depth order.
305    std::sort(_renderLeafList.begin(),_renderLeafList.end(),FrontToBackSortFunctor());
306
307//    cout << "sort front to back"<<endl;
308}
309
310struct BackToFrontSortFunctor
311{
312    bool operator() (const RenderLeaf* lhs,const RenderLeaf* rhs) const
313    {
314        return (rhs->_depth<lhs->_depth);
315    }
316};
317
318void RenderBin::sortBackToFront()
319{
320    copyLeavesFromStateGraphListToRenderLeafList();
321
322    // now sort the list into acending depth order.
323    std::sort(_renderLeafList.begin(),_renderLeafList.end(),BackToFrontSortFunctor());
324
325//    cout << "sort back to front"<<endl;
326}
327
328
329struct TraversalOrderFunctor
330{
331    bool operator() (const RenderLeaf* lhs,const RenderLeaf* rhs) const
332    {
333        return (lhs->_traversalNumber<rhs->_traversalNumber);
334    }
335};
336
337void RenderBin::sortTraversalOrder()
338{
339    copyLeavesFromStateGraphListToRenderLeafList();
340
341    // now sort the list into acending depth order.
342    std::sort(_renderLeafList.begin(),_renderLeafList.end(),TraversalOrderFunctor());
343}
344
345void RenderBin::copyLeavesFromStateGraphListToRenderLeafList()
346{
347    _renderLeafList.clear();
348
349    int totalsize=0;
350    StateGraphList::iterator itr;
351    for(itr=_stateGraphList.begin();
352        itr!=_stateGraphList.end();
353        ++itr)
354    {
355        totalsize += (*itr)->_leaves.size();
356    }
357
358    _renderLeafList.reserve(totalsize);
359
360    bool detectedNaN = false;
361
362    // first copy all the leaves from the render graphs into the leaf list.
363    for(itr=_stateGraphList.begin();
364        itr!=_stateGraphList.end();
365        ++itr)
366    {
367        for(StateGraph::LeafList::iterator dw_itr = (*itr)->_leaves.begin();
368            dw_itr != (*itr)->_leaves.end();
369            ++dw_itr)
370        {
371            if (!osg::isNaN((*dw_itr)->_depth))
372            {
373                _renderLeafList.push_back(dw_itr->get());
374            }
375            else
376            {
377                detectedNaN = true;
378            }
379        }
380    }
381
382    if (detectedNaN) OSG_NOTICE<<"Warning: RenderBin::copyLeavesFromStateGraphListToRenderLeafList() detected NaN depth values, database may be corrupted."<<std::endl;
383
384    // empty the render graph list to prevent it being drawn along side the render leaf list (see drawImplementation.)
385    _stateGraphList.clear();
386}
387
388RenderBin* RenderBin::find_or_insert(int binNum,const std::string& binName)
389{
390    // search for appropriate bin.
391    RenderBinList::iterator itr = _bins.find(binNum);
392    if (itr!=_bins.end()) return itr->second.get();
393
394    // create a rendering bin and insert into bin list.
395    RenderBin* rb = RenderBin::createRenderBin(binName);
396    if (rb)
397    {
398
399        RenderStage* rs = dynamic_cast<RenderStage*>(rb);
400        if (rs)
401        {
402            rs->_binNum = binNum;
403            rs->_parent = NULL;
404            rs->_stage = rs;
405            _stage->addPreRenderStage(rs);
406        }
407        else
408        {
409            rb->_binNum = binNum;
410            rb->_parent = this;
411            rb->_stage = _stage;
412            _bins[binNum] = rb;
413        }
414    }
415    return rb;
416}
417
418void RenderBin::draw(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
419{
420    if (_drawCallback.valid())
421    {
422        _drawCallback->drawImplementation(this,renderInfo,previous);
423    }
424    else drawImplementation(renderInfo,previous);
425}
426
427void RenderBin::drawImplementation(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
428{
429    osg::State& state = *renderInfo.getState();
430
431    // OSG_NOTICE<<"begin RenderBin::drawImplementation "<<className()<<" sortMode "<<getSortMode()<<std::endl;
432
433
434    unsigned int numToPop = (previous ? StateGraph::numToPop(previous->_parent) : 0);
435    if (numToPop>1) --numToPop;
436    unsigned int insertStateSetPosition = state.getStateSetStackSize() - numToPop;
437
438    if (_stateset.valid())
439    {
440        state.insertStateSet(insertStateSetPosition, _stateset.get());
441    }
442
443
444    // draw first set of draw bins.
445    RenderBinList::iterator rbitr;
446    for(rbitr = _bins.begin();
447        rbitr!=_bins.end() && rbitr->first<0;
448        ++rbitr)
449    {
450        rbitr->second->draw(renderInfo,previous);
451    }
452
453    // draw fine grained ordering.
454    for(RenderLeafList::iterator rlitr= _renderLeafList.begin();
455        rlitr!= _renderLeafList.end();
456        ++rlitr)
457    {
458        RenderLeaf* rl = *rlitr;
459        rl->render(renderInfo,previous);
460        previous = rl;
461    }
462
463
464    bool draw_forward = true; //(_sortMode!=SORT_BY_STATE) || (state.getFrameStamp()->getFrameNumber() % 2)==0;
465
466    // draw coarse grained ordering.
467    if (draw_forward)
468    {
469        for(StateGraphList::iterator oitr=_stateGraphList.begin();
470            oitr!=_stateGraphList.end();
471            ++oitr)
472        {
473
474            for(StateGraph::LeafList::iterator dw_itr = (*oitr)->_leaves.begin();
475                dw_itr != (*oitr)->_leaves.end();
476                ++dw_itr)
477            {
478                RenderLeaf* rl = dw_itr->get();
479                rl->render(renderInfo,previous);
480                previous = rl;
481
482            }
483        }
484    }
485    else
486    {
487        for(StateGraphList::reverse_iterator oitr=_stateGraphList.rbegin();
488            oitr!=_stateGraphList.rend();
489            ++oitr)
490        {
491
492            for(StateGraph::LeafList::iterator dw_itr = (*oitr)->_leaves.begin();
493                dw_itr != (*oitr)->_leaves.end();
494                ++dw_itr)
495            {
496                RenderLeaf* rl = dw_itr->get();
497                rl->render(renderInfo,previous);
498                previous = rl;
499
500            }
501        }
502    }
503
504    // draw post bins.
505    for(;
506        rbitr!=_bins.end();
507        ++rbitr)
508    {
509        rbitr->second->draw(renderInfo,previous);
510    }
511
512    if (_stateset.valid())
513    {
514        state.removeStateSet(insertStateSetPosition);
515        // state.apply();
516    }
517
518
519    // OSG_NOTICE<<"end RenderBin::drawImplementation "<<className()<<std::endl;
520}
521
522// stats
523bool RenderBin::getStats(Statistics& stats) const
524{
525    stats.addBins(1);
526
527    // different by return type - collects the stats in this renderrBin
528    bool statsCollected = false;
529    stats.addOrderedLeaves(_renderLeafList.size());
530    // draw fine grained ordering.
531    for(RenderLeafList::const_iterator dw_itr = _renderLeafList.begin();
532        dw_itr != _renderLeafList.end();
533        ++dw_itr)
534    {
535        const RenderLeaf* rl = *dw_itr;
536        const Drawable* dw= rl->getDrawable();
537        stats.addDrawable(); // number of geosets
538
539        const Geometry* geom = dw->asGeometry();
540        if (geom)
541        {
542            if (geom->areFastPathsUsed())
543                stats.addFastDrawable();
544        }
545
546        if (rl->_modelview.get())
547        {
548            stats.addMatrix(); // number of matrices
549        }
550
551        if (dw)
552        {
553              // then tot up the primitive types and no vertices.
554              dw->accept(stats); // use sub-class to find the stats for each drawable
555        }
556        statsCollected = true;
557    }
558    stats.addStateGraphs(_stateGraphList.size());
559    for(StateGraphList::const_iterator oitr=_stateGraphList.begin();
560        oitr!=_stateGraphList.end();
561        ++oitr)
562    {
563
564        for(StateGraph::LeafList::const_iterator dw_itr = (*oitr)->_leaves.begin();
565            dw_itr != (*oitr)->_leaves.end();
566            ++dw_itr)
567        {
568            const RenderLeaf* rl = dw_itr->get();
569            const Drawable* dw= rl->getDrawable();
570            stats.addDrawable(); // number of geosets
571
572            const Geometry* geom = dw->asGeometry();
573            if (geom)
574            {
575                if (geom->areFastPathsUsed())
576                    stats.addFastDrawable();
577            }
578
579            if (rl->_modelview.get()) stats.addMatrix(); // number of matrices
580            if (dw)
581            {
582                // then tot up the primitive types and no vertices.
583                dw->accept(stats); // use sub-class to find the stats for each drawable
584            }
585        }
586        statsCollected = true;
587    }
588
589    // now collects stats for any subbins.
590    for(RenderBinList::const_iterator itr = _bins.begin();
591        itr!=_bins.end();
592        ++itr)
593    {
594        if (itr->second->getStats(stats))
595        {
596            statsCollected = true;
597        }
598    }
599
600    return statsCollected;
601}
602
603unsigned int RenderBin::computeNumberOfDynamicRenderLeaves() const
604{
605    unsigned int count = 0;
606
607    // draw first set of draw bins.
608    RenderBinList::const_iterator rbitr;
609    for(rbitr = _bins.begin();
610        rbitr!=_bins.end() && rbitr->first<0;
611        ++rbitr)
612    {
613        count += rbitr->second->computeNumberOfDynamicRenderLeaves();
614    }
615
616    // draw fine grained ordering.
617    for(RenderLeafList::const_iterator rlitr= _renderLeafList.begin();
618        rlitr!= _renderLeafList.end();
619        ++rlitr)
620    {
621        RenderLeaf* rl = *rlitr;
622        if (rl->_dynamic) ++count;
623    }
624
625
626    // draw coarse grained ordering.
627    for(StateGraphList::const_iterator oitr=_stateGraphList.begin();
628        oitr!=_stateGraphList.end();
629        ++oitr)
630    {
631
632        for(StateGraph::LeafList::const_iterator dw_itr = (*oitr)->_leaves.begin();
633            dw_itr != (*oitr)->_leaves.end();
634            ++dw_itr)
635        {
636            RenderLeaf* rl = dw_itr->get();
637            if (rl->_dynamic) ++count;
638        }
639    }
640
641    // draw post bins.
642    for(;
643        rbitr!=_bins.end();
644        ++rbitr)
645    {
646        count += rbitr->second->computeNumberOfDynamicRenderLeaves();
647    }
648
649    return count;
650}
651
652
653void RenderBin::releaseGLObjects(osg::State* state) const
654{
655    if (_stateset) _stateset->releaseGLObjects(state);
656
657    for(RenderBinList::const_iterator itr = _bins.begin();
658        itr != _bins.end();
659        ++itr)
660    {
661        itr->second->releaseGLObjects(state);
662    }
663}
Note: See TracBrowser for help on using the browser.