2001-09-20 05:19:47 +08:00
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <osg/StateSet>
|
|
|
|
#include <osg/State>
|
|
|
|
#include <osg/Notify>
|
|
|
|
|
|
|
|
#include <osg/AlphaFunc>
|
|
|
|
#include <osg/Material>
|
|
|
|
#include <osg/CullFace>
|
|
|
|
#include <osg/FrontFace>
|
|
|
|
#include <osg/PolygonMode>
|
|
|
|
#include <osg/Transparency>
|
2001-09-30 02:34:26 +08:00
|
|
|
#include <osg/Depth>
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
using namespace osg;
|
|
|
|
|
|
|
|
StateSet::StateSet()
|
|
|
|
{
|
|
|
|
_renderingHint = DEFAULT_BIN;
|
|
|
|
|
|
|
|
setRendingBinToInherit();
|
|
|
|
}
|
|
|
|
|
Added support for shallow and deep copy of nodes, drawables and state, via a
copy constructor which takes an optional Cloner object, and the old
osg::Object::clone() has changed so that it now requires a Cloner as paramter.
This is passed on to the copy constructor to help control the shallow vs
deep copying. The old functionality of clone() which was clone of type has
been renamed to cloneType().
Updated all of the OSG to work with these new conventions, implemention all
the required copy constructors etc. A couple of areas will do shallow
copies by design, a couple of other still need to be updated to do either
shallow or deep.
Neither of the shallow or deep copy operations have been tested yet, only
the old functionality of the OSG has been checked so far, such running the
viewer on various demo datasets.
Also fixed a problem in osg::Optimize::RemoveRendundentNodesVisitor which
was not checking that Group didn't have have any attached StateSet's, Callbacks
or UserData. These checks have now been added, which fixes a bug which was
revealled by the new osgscribe demo, this related to removal of group acting
as state decorator.
method
2002-01-29 05:17:01 +08:00
|
|
|
StateSet::StateSet(const StateSet& rhs,const Cloner& cloner):Object(rhs,cloner)
|
2001-10-23 06:02:47 +08:00
|
|
|
{
|
Added support for shallow and deep copy of nodes, drawables and state, via a
copy constructor which takes an optional Cloner object, and the old
osg::Object::clone() has changed so that it now requires a Cloner as paramter.
This is passed on to the copy constructor to help control the shallow vs
deep copying. The old functionality of clone() which was clone of type has
been renamed to cloneType().
Updated all of the OSG to work with these new conventions, implemention all
the required copy constructors etc. A couple of areas will do shallow
copies by design, a couple of other still need to be updated to do either
shallow or deep.
Neither of the shallow or deep copy operations have been tested yet, only
the old functionality of the OSG has been checked so far, such running the
viewer on various demo datasets.
Also fixed a problem in osg::Optimize::RemoveRendundentNodesVisitor which
was not checking that Group didn't have have any attached StateSet's, Callbacks
or UserData. These checks have now been added, which fixes a bug which was
revealled by the new osgscribe demo, this related to removal of group acting
as state decorator.
method
2002-01-29 05:17:01 +08:00
|
|
|
// shallow copy right now, we should go through each attribute and
|
|
|
|
// use the cloner instead of attribute list copy.. on the TODO list. Robert. Jan 2002.
|
|
|
|
|
2001-10-23 06:02:47 +08:00
|
|
|
_modeList = rhs._modeList;
|
|
|
|
_attributeList = rhs._attributeList;
|
|
|
|
|
|
|
|
_renderingHint = rhs._renderingHint;
|
|
|
|
|
|
|
|
_binMode = rhs._binMode;
|
|
|
|
_binNum = rhs._binNum;
|
|
|
|
_binName = rhs._binName;
|
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
StateSet::~StateSet()
|
|
|
|
{
|
|
|
|
// note, all attached state attributes will be automatically
|
|
|
|
// unreferenced by ref_ptr<> and therefore there is no need to
|
|
|
|
// delete the memory manually.
|
|
|
|
}
|
|
|
|
|
2001-11-01 04:04:32 +08:00
|
|
|
int StateSet::compare(const StateSet& rhs,bool compareAttributeContents) const
|
2001-10-02 07:02:14 +08:00
|
|
|
{
|
|
|
|
|
2001-11-01 04:04:32 +08:00
|
|
|
if (compareAttributeContents)
|
2001-10-02 07:02:14 +08:00
|
|
|
{
|
2001-11-01 04:04:32 +08:00
|
|
|
// now check to see how the attributes compare.
|
|
|
|
AttributeList::const_iterator lhs_attr_itr = _attributeList.begin();
|
|
|
|
AttributeList::const_iterator rhs_attr_itr = rhs._attributeList.begin();
|
|
|
|
while (lhs_attr_itr!=_attributeList.end() && rhs_attr_itr!=rhs._attributeList.end())
|
|
|
|
{
|
|
|
|
if (lhs_attr_itr->first<rhs_attr_itr->first) return -1;
|
|
|
|
else if (rhs_attr_itr->first<lhs_attr_itr->first) return 1;
|
|
|
|
if (*(lhs_attr_itr->second.first)<*(rhs_attr_itr->second.first)) return -1;
|
|
|
|
else if (*(rhs_attr_itr->second.first)<*(lhs_attr_itr->second.first)) return 1;
|
|
|
|
if (lhs_attr_itr->second.second<rhs_attr_itr->second.second) return -1;
|
|
|
|
else if (rhs_attr_itr->second.second<lhs_attr_itr->second.second) return 1;
|
|
|
|
++lhs_attr_itr;
|
|
|
|
++rhs_attr_itr;
|
|
|
|
}
|
|
|
|
if (lhs_attr_itr==_attributeList.end())
|
|
|
|
{
|
|
|
|
if (rhs_attr_itr!=rhs._attributeList.end()) return -1;
|
|
|
|
}
|
|
|
|
else if (rhs_attr_itr == rhs._attributeList.end()) return 1;
|
2001-10-02 07:02:14 +08:00
|
|
|
}
|
2001-11-01 04:04:32 +08:00
|
|
|
else // just compare pointers.
|
2001-10-02 07:02:14 +08:00
|
|
|
{
|
2001-11-01 04:04:32 +08:00
|
|
|
// now check to see how the attributes compare.
|
|
|
|
AttributeList::const_iterator lhs_attr_itr = _attributeList.begin();
|
|
|
|
AttributeList::const_iterator rhs_attr_itr = rhs._attributeList.begin();
|
|
|
|
while (lhs_attr_itr!=_attributeList.end() && rhs_attr_itr!=rhs._attributeList.end())
|
|
|
|
{
|
|
|
|
if (lhs_attr_itr->first<rhs_attr_itr->first) return -1;
|
|
|
|
else if (rhs_attr_itr->first<lhs_attr_itr->first) return 1;
|
|
|
|
if (lhs_attr_itr->second.first<rhs_attr_itr->second.first) return -1;
|
|
|
|
else if (rhs_attr_itr->second.first<lhs_attr_itr->second.first) return 1;
|
|
|
|
if (lhs_attr_itr->second.second<rhs_attr_itr->second.second) return -1;
|
|
|
|
else if (rhs_attr_itr->second.second<lhs_attr_itr->second.second) return 1;
|
|
|
|
++lhs_attr_itr;
|
|
|
|
++rhs_attr_itr;
|
|
|
|
}
|
|
|
|
if (lhs_attr_itr==_attributeList.end())
|
|
|
|
{
|
|
|
|
if (rhs_attr_itr!=rhs._attributeList.end()) return -1;
|
|
|
|
}
|
|
|
|
else if (rhs_attr_itr == rhs._attributeList.end()) return 1;
|
2001-10-02 07:02:14 +08:00
|
|
|
}
|
2001-11-01 04:04:32 +08:00
|
|
|
|
2001-10-04 22:39:24 +08:00
|
|
|
// we've got here so attributes must be equal...
|
|
|
|
|
|
|
|
// check to see how the modes compare.
|
|
|
|
|
|
|
|
ModeList::const_iterator lhs_mode_itr = _modeList.begin();
|
|
|
|
ModeList::const_iterator rhs_mode_itr = rhs._modeList.begin();
|
|
|
|
while (lhs_mode_itr!=_modeList.end() && rhs_mode_itr!=rhs._modeList.end())
|
|
|
|
{
|
|
|
|
if (lhs_mode_itr->first<rhs_mode_itr->first) return -1;
|
|
|
|
else if (rhs_mode_itr->first<lhs_mode_itr->first) return 1;
|
|
|
|
if (lhs_mode_itr->second<rhs_mode_itr->second) return -1;
|
|
|
|
else if (rhs_mode_itr->second<lhs_mode_itr->second) return 1;
|
|
|
|
++lhs_mode_itr;
|
|
|
|
++rhs_mode_itr;
|
|
|
|
}
|
|
|
|
if (lhs_mode_itr==_modeList.end())
|
|
|
|
{
|
|
|
|
if (rhs_mode_itr!=rhs._modeList.end()) return -1;
|
|
|
|
}
|
|
|
|
else if (rhs_mode_itr == rhs._modeList.end()) return 1;
|
|
|
|
|
2001-10-02 07:02:14 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
void StateSet::setGlobalDefaults()
|
|
|
|
{
|
|
|
|
_renderingHint = DEFAULT_BIN;
|
|
|
|
|
|
|
|
setRendingBinToInherit();
|
|
|
|
|
2001-10-15 22:07:54 +08:00
|
|
|
|
|
|
|
setAttributeAndModes(new AlphaFunc,StateAttribute::OFF);
|
|
|
|
setAttributeAndModes(new Transparency,StateAttribute::OFF);
|
|
|
|
|
|
|
|
Material *material = new Material;
|
|
|
|
material->setColorMode(Material::AMBIENT_AND_DIFFUSE);
|
|
|
|
setAttributeAndModes(material,StateAttribute::ON);
|
|
|
|
/*
|
2001-09-20 05:19:47 +08:00
|
|
|
setMode(GL_LIGHTING,StateAttribute::OFF);
|
|
|
|
setMode(GL_FOG,StateAttribute::OFF);
|
|
|
|
setMode(GL_POINT_SMOOTH,StateAttribute::OFF);
|
|
|
|
|
|
|
|
setMode(GL_TEXTURE_2D,StateAttribute::OFF);
|
|
|
|
|
|
|
|
setMode(GL_TEXTURE_GEN_S,StateAttribute::OFF);
|
|
|
|
setMode(GL_TEXTURE_GEN_T,StateAttribute::OFF);
|
|
|
|
setMode(GL_TEXTURE_GEN_R,StateAttribute::OFF);
|
|
|
|
setMode(GL_TEXTURE_GEN_Q,StateAttribute::OFF);
|
|
|
|
|
|
|
|
setAttributeAndModes(new AlphaFunc,StateAttribute::OFF);
|
|
|
|
setAttributeAndModes(new CullFace,StateAttribute::ON);
|
|
|
|
setAttributeAndModes(new FrontFace,StateAttribute::ON);
|
|
|
|
|
|
|
|
Material *material = new Material;
|
|
|
|
material->setColorMode(Material::AMBIENT_AND_DIFFUSE);
|
|
|
|
setAttributeAndModes(material,StateAttribute::ON);
|
|
|
|
|
|
|
|
setAttributeAndModes(new PolygonMode,StateAttribute::OFF);
|
|
|
|
setAttributeAndModes(new Transparency,StateAttribute::OFF);
|
2001-09-30 02:34:26 +08:00
|
|
|
setAttributeAndModes(new Depth,StateAttribute::ON);
|
2001-10-15 22:07:54 +08:00
|
|
|
*/
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void StateSet::setAllToInherit()
|
|
|
|
{
|
|
|
|
_renderingHint = DEFAULT_BIN;
|
|
|
|
|
|
|
|
setRendingBinToInherit();
|
|
|
|
|
|
|
|
_modeList.clear();
|
|
|
|
_attributeList.clear();
|
|
|
|
}
|
|
|
|
|
2001-10-14 17:58:49 +08:00
|
|
|
void StateSet::merge(const StateSet& rhs)
|
|
|
|
{
|
|
|
|
// merge the modes of rhs into this,
|
|
|
|
// this overrides rhs if OVERRIDE defined in this.
|
|
|
|
for(ModeList::const_iterator rhs_mitr = rhs._modeList.begin();
|
2001-12-01 04:53:50 +08:00
|
|
|
rhs_mitr != rhs._modeList.end();
|
2001-10-14 17:58:49 +08:00
|
|
|
++rhs_mitr)
|
|
|
|
{
|
|
|
|
ModeList::iterator lhs_mitr = _modeList.find(rhs_mitr->first);
|
|
|
|
if (lhs_mitr!=_modeList.end())
|
|
|
|
{
|
|
|
|
if (!(lhs_mitr->second & StateAttribute::OVERRIDE))
|
|
|
|
{
|
|
|
|
// override isn't on in rhs, so overrite it with incomming
|
|
|
|
// value.
|
|
|
|
lhs_mitr->second = rhs_mitr->second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// entry doesn't exist so insert it.
|
|
|
|
_modeList.insert(*rhs_mitr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// merge the attributes of rhs into this,
|
|
|
|
// this overrides rhs if OVERRIDE defined in this.
|
|
|
|
for(AttributeList::const_iterator rhs_aitr = rhs._attributeList.begin();
|
2001-12-01 04:53:50 +08:00
|
|
|
rhs_aitr != rhs._attributeList.end();
|
2001-10-14 17:58:49 +08:00
|
|
|
++rhs_aitr)
|
|
|
|
{
|
|
|
|
AttributeList::iterator lhs_aitr = _attributeList.find(rhs_aitr->first);
|
|
|
|
if (lhs_aitr!=_attributeList.end())
|
|
|
|
{
|
|
|
|
if (!(lhs_aitr->second.second & StateAttribute::OVERRIDE))
|
|
|
|
{
|
|
|
|
// override isn't on in rhs, so overrite it with incomming
|
|
|
|
// value.
|
|
|
|
lhs_aitr->second = rhs_aitr->second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// entry doesn't exist so insert it.
|
|
|
|
_attributeList.insert(*rhs_aitr);
|
|
|
|
}
|
|
|
|
}
|
2001-12-01 04:53:50 +08:00
|
|
|
|
|
|
|
// need to merge rendering hints
|
|
|
|
// but will need to think how best to do this first
|
|
|
|
// RO, Nov. 2001.
|
|
|
|
|
2001-10-14 17:58:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
void StateSet::setMode(const StateAttribute::GLMode mode, const StateAttribute::GLModeValue value)
|
|
|
|
{
|
|
|
|
if ((value&StateAttribute::INHERIT)) setModeToInherit(mode);
|
|
|
|
else _modeList[mode] = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StateSet::setModeToInherit(const StateAttribute::GLMode mode)
|
|
|
|
{
|
|
|
|
ModeList::iterator itr = _modeList.find(mode);
|
|
|
|
if (itr!=_modeList.end())
|
|
|
|
{
|
|
|
|
_modeList.erase(itr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const StateAttribute::GLModeValue StateSet::getMode(const StateAttribute::GLMode mode) const
|
|
|
|
{
|
|
|
|
ModeList::const_iterator itr = _modeList.find(mode);
|
|
|
|
if (itr!=_modeList.end())
|
|
|
|
{
|
|
|
|
return itr->second;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return StateAttribute::INHERIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StateSet::setAttribute(StateAttribute *attribute, const StateAttribute::OverrideValue value)
|
|
|
|
{
|
|
|
|
if (attribute)
|
|
|
|
{
|
|
|
|
if ((value&StateAttribute::INHERIT)) setAttributeToInherit(attribute->getType());
|
|
|
|
else _attributeList[attribute->getType()] = RefAttributePair(attribute,value&StateAttribute::OVERRIDE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StateSet::setAttributeAndModes(StateAttribute *attribute, const StateAttribute::GLModeValue value)
|
|
|
|
{
|
|
|
|
if (attribute)
|
|
|
|
{
|
|
|
|
_attributeList[attribute->getType()] = RefAttributePair(attribute,value&StateAttribute::OVERRIDE);
|
|
|
|
attribute->setStateSetModes(*this,value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StateSet::setAttributeToInherit(const StateAttribute::Type type)
|
|
|
|
{
|
|
|
|
AttributeList::iterator itr = _attributeList.find(type);
|
|
|
|
if (itr!=_attributeList.end())
|
|
|
|
{
|
|
|
|
itr->second.first->setStateSetModes(*this,StateAttribute::INHERIT);
|
|
|
|
_attributeList.erase(itr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-09-29 00:56:19 +08:00
|
|
|
StateAttribute* StateSet::getAttribute(const StateAttribute::Type type)
|
|
|
|
{
|
|
|
|
AttributeList::iterator itr = _attributeList.find(type);
|
|
|
|
if (itr!=_attributeList.end())
|
|
|
|
{
|
|
|
|
return itr->second.first.get();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
const StateAttribute* StateSet::getAttribute(const StateAttribute::Type type) const
|
|
|
|
{
|
|
|
|
AttributeList::const_iterator itr = _attributeList.find(type);
|
|
|
|
if (itr!=_attributeList.end())
|
|
|
|
{
|
|
|
|
return itr->second.first.get();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const StateSet::RefAttributePair* StateSet::getAttributePair(const StateAttribute::Type type) const
|
|
|
|
{
|
|
|
|
AttributeList::const_iterator itr = _attributeList.find(type);
|
|
|
|
if (itr!=_attributeList.end())
|
|
|
|
{
|
|
|
|
return &(itr->second);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StateSet::compile(State& state) const
|
|
|
|
{
|
|
|
|
for(AttributeList::const_iterator itr = _attributeList.begin();
|
|
|
|
itr!=_attributeList.end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
itr->second.first->compile(state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StateSet::setRenderingHint(const int hint)
|
|
|
|
{
|
|
|
|
_renderingHint = hint;
|
|
|
|
// temporary hack to get new render bins working.
|
|
|
|
if (_renderingHint==TRANSPARENT_BIN)
|
|
|
|
{
|
|
|
|
_binMode = USE_RENDERBIN_DETAILS;
|
|
|
|
_binNum = 1;
|
|
|
|
_binName = "DepthSortedBin";
|
|
|
|
// _binName = "RenderBin";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StateSet::setRenderBinDetails(const int binNum,const std::string& binName,const RenderBinMode mode)
|
|
|
|
{
|
|
|
|
_binMode = mode;
|
|
|
|
_binNum = binNum;
|
|
|
|
_binName = binName;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StateSet::setRendingBinToInherit()
|
|
|
|
{
|
|
|
|
_binMode = INHERIT_RENDERBIN_DETAILS;
|
|
|
|
_binNum = 0;
|
|
|
|
_binName = "";
|
|
|
|
}
|