Fixed bug associated with complex RenderBin setup.

This commit is contained in:
Robert Osfield 2007-04-16 12:18:56 +00:00
parent 68a6882d04
commit 9db23e0b22
4 changed files with 117 additions and 3 deletions

View File

@ -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(); }

View File

@ -46,7 +46,7 @@ class OSGUTIL_EXPORT StateGraph : public osg::Referenced
typedef std::map< const osg::StateSet*, osg::ref_ptr<StateGraph> > ChildList;
typedef std::vector< osg::ref_ptr<RenderLeaf> > 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.

View File

@ -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()<<std::endl;
}
void State::popAllStateSets()
{
// osg::notify(osg::NOTICE)<<"State::popAllStateSets()"<<_stateStateStack.size()<<std::endl;
while (!_stateStateStack.empty()) popStateSet();
applyProjectionMatrix(0);
@ -217,8 +222,11 @@ void State::popAllStateSets()
void State::popStateSet()
{
// osg::notify(osg::NOTICE)<<"State::popStateSet()"<<_stateStateStack.size()<<std::endl;
if (_stateStateStack.empty()) return;
const StateSet* dstate = _stateStateStack.back();
if (dstate)
@ -251,6 +259,58 @@ void State::popStateSet()
_stateStateStack.pop_back();
}
void State::insertStateSet(unsigned int pos,const StateSet* dstate)
{
StateSetStack tempStack;
// first pop the StateSet above the position we need to insert at
while (_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<<") out of range"<<std::endl;
return;
}
// record the StateSet above the one we intend to remove
StateSetStack tempStack;
while (_stateStateStack.size()-1>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.

View File

@ -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 "<<className()<<" sortMode "<<getSortMode()<<std::endl;
#ifndef OLD_STATECODE
#ifdef NEW_STATECODE
unsigned int numToPop = (previous ? StateGraph::numToPop(state, previous->_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 "<<className()<<std::endl;
}