#include #include #include using namespace osg; using namespace osgUtil; // register a RenderStage prototype with the RenderBin prototype list. RegisterRenderBinProxy s_registerRenderBinProxy; #ifdef __DARWIN_OSX__ // PJA 10/1/02 - this is a hack to get OS X to build, if this code is included in DepthSortedBin.cpp it isnt executed // register a RenderStage prototype with the RenderBin prototype list. #include RegisterRenderBinProxy s_registerDepthSortedBinProxy; #endif typedef std::map< std::string, osg::ref_ptr > RenderBinPrototypeList; RenderBinPrototypeList* renderBinPrototypeList() { static RenderBinPrototypeList s_renderBinPrototypeList; return &s_renderBinPrototypeList; } RenderBin* RenderBin::createRenderBin(const std::string& binName) { // cout << "creating RB "<find(binName); if (itr != renderBinPrototypeList()->end()) return dynamic_cast(itr->second->cloneType()); else return NULL; } void RenderBin::addRenderBinPrototype(RenderBin* proto) { if (proto) { (*renderBinPrototypeList())[proto->className()] = proto; // cout << "Adding RB "<className()<find(proto->className()); if (itr != renderBinPrototypeList()->end()) renderBinPrototypeList()->erase(itr); } } RenderBin::RenderBin() { _binNum = 0; _parent = NULL; _stage = NULL; } RenderBin::~RenderBin() { } void RenderBin::reset() { _renderGraphList.clear(); _bins.clear(); } void RenderBin::sort() { for(RenderBinList::iterator itr = _bins.begin(); itr!=_bins.end(); ++itr) { itr->second->sort(); } sort_local(); } struct StateSortFunctor { const bool operator() (const RenderGraph* lhs,const RenderGraph* rhs) { return (*(lhs->_stateset)<*(rhs->_stateset)); } }; void RenderBin::sort_local() { // now sort the list into acending depth order. // std::sort(_renderGraphList.begin(),_renderGraphList.end(),StateSortFunctor()); } RenderBin* RenderBin::find_or_insert(int binNum,const std::string& binName) { // search for appropriate bin. RenderBinList::iterator itr = _bins.find(binNum); if (itr!=_bins.end()) return itr->second.get(); // create a renderin bin and insert into bin list. RenderBin* rb = RenderBin::createRenderBin(binName); if (rb) { RenderStage* rs = dynamic_cast(rb); if (rs) { rs->_binNum = binNum; rs->_parent = NULL; rs->_stage = rs; _stage->addToDependencyList(rs); } else { rb->_binNum = binNum; rb->_parent = this; rb->_stage = _stage; _bins[binNum] = rb; } } return rb; } void RenderBin::draw(osg::State& state,RenderLeaf*& previous) { // draw first set of draw bins. RenderBinList::iterator itr; for(itr = _bins.begin(); itr->first<0 && itr!=_bins.end(); ++itr) { itr->second->draw(state,previous); } draw_local(state,previous); for(; itr!=_bins.end(); ++itr) { itr->second->draw(state,previous); } } void RenderBin::draw_local(osg::State& state,RenderLeaf*& previous) { sort_local(); // draw local bin. for(RenderGraphList::iterator oitr=_renderGraphList.begin(); oitr!=_renderGraphList.end(); ++oitr) { for(RenderGraph::LeafList::iterator dw_itr = (*oitr)->_leaves.begin(); dw_itr != (*oitr)->_leaves.end(); ++dw_itr) { RenderLeaf* rl = dw_itr->get(); rl->render(state,previous); previous = rl; } } } // stats bool RenderBin::getStats(osg::Statistics* primStats) { // different by return type - collects the stats in this renderrBin bool somestats=false; for(RenderGraphList::iterator oitr=_renderGraphList.begin(); oitr!=_renderGraphList.end(); ++oitr) { for(RenderGraph::LeafList::iterator dw_itr = (*oitr)->_leaves.begin(); dw_itr != (*oitr)->_leaves.end(); ++dw_itr) { RenderLeaf* rl = dw_itr->get(); Drawable* dw= rl->_drawable; primStats->addOpaque(); // number of geosets if (rl->_modelview.get()) primStats->addMatrix(); // number of matrices if (dw) { // then tot up the types 1-14 // commenting out as having intrusive stats in base classes is // undersirable. dw->getStats(*primStats); // use sub-class to find the stats for each drawable // use an AttributeOption to get the stats we require. dw->applyAttributeOperation(*primStats); } } somestats=true; } return somestats; } void RenderBin::getPrims(osg::Statistics* primStats) { static int ndepth; ndepth++; for(RenderBinList::iterator itr = _bins.begin(); itr!=_bins.end(); ++itr) { primStats->addBins(1); itr->second->getPrims(primStats); } getStats(primStats); ndepth--; } bool RenderBin::getPrims(osg::Statistics* primStats, const int nbin) { // collect stats for array of bins, maximum nbin // (which will be modified on next call if array of primStats is too small); // return 1 for OK; static int ndepth; bool ok=false; ndepth++; int nb=primStats[0].getBins(); if (nbsecond->getPrims(primStats, nbin)) ok = true; } ok=true; ndepth--; return ok; }