diff --git a/include/osg/State b/include/osg/State index de38ae86f..8830890e8 100644 --- a/include/osg/State +++ b/include/osg/State @@ -120,10 +120,16 @@ class OSG_EXPORT State : public Referenced /** Pop stateset off state stack.*/ void popStateSet(); - + /** pop all statesets off state stack, ensuring it is empty ready for the next frame. * Note, to return OpenGL to default state, one should do any state.popAllStatSets(); state.apply().*/ void popAllStateSets(); + + /** Insert stateset onto state stack.*/ + void insertStateSet(unsigned int pos,const StateSet* dstate); + + /** Pop stateset off state stack.*/ + void removeStateSet(unsigned int pos); /** Get the number of StateSet's on the StateSet stack.*/ unsigned int getStateSetStackSize() { return _stateStateStack.size(); } diff --git a/include/osgUtil/StateGraph b/include/osgUtil/StateGraph index b71188647..66df68b8d 100644 --- a/include/osgUtil/StateGraph +++ b/include/osgUtil/StateGraph @@ -46,7 +46,7 @@ class OSGUTIL_EXPORT StateGraph : public osg::Referenced typedef std::map< const osg::StateSet*, osg::ref_ptr > ChildList; typedef std::vector< osg::ref_ptr > LeafList; - StateGraph* _parent; + StateGraph* _parent; const osg::StateSet* _stateset; int _depth; @@ -279,6 +279,19 @@ class OSGUTIL_EXPORT StateGraph : public osg::Referenced } + inline static int numToPop(osg::State& state,StateGraph* sg_curr) + { + int numToPop = 0; + // need to pop back all statesets and matrices. + while (sg_curr) + { + if (sg_curr->_stateset) ++numToPop; + sg_curr = sg_curr->_parent; + } + + return numToPop; + } + private: /// disallow copy construction. diff --git a/src/osg/State.cpp b/src/osg/State.cpp index 5e5d91f01..9602bf9d8 100644 --- a/src/osg/State.cpp +++ b/src/osg/State.cpp @@ -178,6 +178,7 @@ void State::setInitialViewMatrix(const osg::RefMatrix* matrix) void State::pushStateSet(const StateSet* dstate) { + _stateStateStack.push_back(dstate); if (dstate) { @@ -203,10 +204,14 @@ void State::pushStateSet(const StateSet* dstate) pushUniformList(_uniformMap,dstate->getUniformList()); } + + // osg::notify(osg::NOTICE)<<"State::pushStateSet()"<<_stateStateStack.size()<pos) + { + tempStack.push_back(_stateStateStack.back()); + popStateSet(); + } + + // push our new stateset + pushStateSet(dstate); + + // push back the original ones + for(StateSetStack::reverse_iterator itr = tempStack.rbegin(); + itr != tempStack.rend(); + ++itr) + { + pushStateSet(*itr); + } + +} + +void State::removeStateSet(unsigned int pos) +{ + if (pos >= _stateStateStack.size()) + { + osg::notify(osg::NOTICE)<<"Warning: State::removeStateSet("<pos) + { + tempStack.push_back(_stateStateStack.back()); + popStateSet(); + } + + // remove the intended StateSet as well + popStateSet(); + + // push back the original ones that were above the remove StateSet + for(StateSetStack::reverse_iterator itr = tempStack.rbegin(); + itr != tempStack.rend(); + ++itr) + { + pushStateSet(*itr); + } +} + void State::captureCurrentState(StateSet& stateset) const { // empty the stateset first. diff --git a/src/osgUtil/RenderBin.cpp b/src/osgUtil/RenderBin.cpp index c862d0e25..a36c64fea 100644 --- a/src/osgUtil/RenderBin.cpp +++ b/src/osgUtil/RenderBin.cpp @@ -370,12 +370,31 @@ void RenderBin::draw(osg::RenderInfo& renderInfo,RenderLeaf*& previous) else drawImplementation(renderInfo,previous); } +#define NEW_STATECODE +//#define OLD_STATECODE + void RenderBin::drawImplementation(osg::RenderInfo& renderInfo,RenderLeaf*& previous) { osg::State& state = *renderInfo.getState(); // osg::notify(osg::NOTICE)<<"begin RenderBin::drawImplementation "<_parent) : 0); + if (numToPop>1) --numToPop; + unsigned int insertStateSetPosition = state.getStateSetStackSize() - numToPop; + + if (_stateset.valid()) + { + state.insertStateSet(insertStateSetPosition, _stateset.get()); + } + +#else + unsigned int stateSetStackSize = state.getStateSetStackSize(); previous = 0; @@ -386,8 +405,11 @@ void RenderBin::drawImplementation(osg::RenderInfo& renderInfo,RenderLeaf*& prev // now its safe to push RenderBin's StateSet as we now know its the root. state.pushStateSet(_stateset.get()); + state.apply(); } - + +#endif +#endif // draw first set of draw bins. RenderBinList::iterator rbitr; @@ -457,12 +479,25 @@ void RenderBin::drawImplementation(osg::RenderInfo& renderInfo,RenderLeaf*& prev rbitr->second->draw(renderInfo,previous); } +#ifndef OLD_STATECODE +#ifdef NEW_STATECODE + + if (_stateset.valid()) + { + state.removeStateSet(insertStateSetPosition); + state.apply(); + } + +#else if (stateSetStackSize!=state.getStateSetStackSize()) { state.popStateSetStackToSize(stateSetStackSize); } previous = 0; +#endif +#endif + // osg::notify(osg::NOTICE)<<"end RenderBin::drawImplementation "<