osg::Vec4 ambientDiffuse;
};
+class MaterialPropertyAdapter
+{
+public:
+ MaterialPropertyAdapter(const SGPropertyNode* configNode,
+ SGPropertyNode* modelRoot) :
+ _ambient(configNode->getChild("ambient"), modelRoot),
+ _diffuse(configNode->getChild("diffuse"), modelRoot),
+ _specular(configNode->getChild("specular"), modelRoot),
+ _emission(configNode->getChild("emission"), modelRoot),
+ _shininess("shininess", "shininess-prop",
+ configNode/*->getChild("shininess")*/, modelRoot),
+ _transparency("alpha", "alpha-prop",
+ configNode->getChild("transparency"), modelRoot)
+ {
+ _shininess.max = 128;
+ _isAnimated = (_ambient.live() || _diffuse.live() || _specular.live()
+ || _emission.live() || _shininess.live()
+ || _transparency.live());
+ }
+ bool isAnimated() { return _isAnimated; }
+ // This takes a StateSet argument because the rendering bin will
+ // be changed if there is transparency.
+ void setMaterialValues(osg::StateSet* stateSet)
+ {
+ osg::StateAttribute* stateAttribute
+ = stateSet->getAttribute(osg::StateAttribute::MATERIAL);
+ osg::Material* material = dynamic_cast<osg::Material*>(stateAttribute);
+ if (material) {
+ if (_ambient.live() || _ambient.dirty())
+ material->setAmbient(osg::Material::FRONT_AND_BACK,
+ _ambient.rgbaVec4());
+ if (_diffuse.live() || _diffuse.dirty())
+ material->setDiffuse(osg::Material::FRONT_AND_BACK,
+ _diffuse.rgbaVec4());
+ if (_specular.live() || _specular.dirty())
+ material->setSpecular(osg::Material::FRONT_AND_BACK,
+ _specular.rgbaVec4());
+ if (_emission.live() || _emission.dirty())
+ material->setEmission(osg::Material::FRONT_AND_BACK,
+ _emission.rgbaVec4());
+ if (_shininess.live() || _shininess.dirty())
+ material->setShininess(osg::Material::FRONT_AND_BACK,
+ _shininess.getValue());
+ if (_transparency.live() || _transparency.dirty()) {
+ float alpha = _transparency.getValue();
+ material->setAlpha(osg::Material::FRONT_AND_BACK, alpha);
+ if (alpha < 1.0f) {
+ stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+ stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
+ } else {
+ stateSet->setRenderingHint(osg::StateSet::DEFAULT_BIN);
+ }
+ }
+ }
+ }
+ ColorSpec _ambient;
+ ColorSpec _diffuse;
+ ColorSpec _specular;
+ ColorSpec _emission;
+ PropSpec _shininess;
+ PropSpec _transparency;
+ bool _isAnimated;
+
+};
+
class UpdateCallback : public osg::NodeCallback {
public:
UpdateCallback(const osgDB::FilePathList& texturePathList,
const SGCondition* condition,
const SGPropertyNode* configNode, SGPropertyNode* modelRoot) :
_condition(condition),
- _ambient(configNode->getChild("ambient"), modelRoot),
- _diffuse(configNode->getChild("diffuse"), modelRoot),
- _specular(configNode->getChild("specular"), modelRoot),
- _emission(configNode->getChild("emission"), modelRoot),
- _shininess("shininess", "shininess-prop",
- configNode->getChild("shininess"), modelRoot),
- _transparency("alpha", "alpha-prop",
- configNode->getChild("transparency"), modelRoot),
- _texturePathList(texturePathList)
+ _materialProps(configNode, modelRoot),
+ _texturePathList(texturePathList),
+ _prevState(false)
{
const SGPropertyNode* node;
osg::StateSet* stateSet = node->getOrCreateStateSet();
osg::StateAttribute* stateAttribute;
stateAttribute = stateSet->getAttribute(osg::StateAttribute::ALPHAFUNC);
- osg::AlphaFunc* alphaFunc = dynamic_cast<osg::AlphaFunc*>(stateAttribute);
+ osg::AlphaFunc* alphaFunc
+ = dynamic_cast<osg::AlphaFunc*>(stateAttribute);
assert(alphaFunc);
alphaFunc->setReferenceValue(_thresholdProp->getFloatValue());
}
- osg::StateAttribute* stateAttribute
- = stateSet->getAttribute(osg::StateAttribute::MATERIAL);
- osg::Material* material = dynamic_cast<osg::Material*>(stateAttribute);
- if (material) {
- if (_ambient.live())
- material->setAmbient(osg::Material::FRONT_AND_BACK,
- _ambient.rgbaVec4());
- if (_diffuse.live())
- material->setDiffuse(osg::Material::FRONT_AND_BACK,
- _diffuse.rgbaVec4());
- if (_specular.live())
- material->setSpecular(osg::Material::FRONT_AND_BACK,
- _specular.rgbaVec4());
- if (_emission.live())
- material->setEmission(osg::Material::FRONT_AND_BACK,
- _emission.rgbaVec4());
- if (_shininess.live())
- material->setShininess(osg::Material::FRONT_AND_BACK,
- _shininess.getValue());
- if (_transparency.live()) {
- float alpha = _transparency.getValue();
- material->setAlpha(osg::Material::FRONT_AND_BACK, alpha);
- if (alpha < 1.0f) {
- stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
- stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
- } else {
- stateSet->setRenderingHint(osg::StateSet::DEFAULT_BIN);
- }
- }
- }
+ if (_materialProps.isAnimated() || !_prevState)
+ _materialProps.setMaterialValues(stateSet);
+ _prevState = true;
+ } else {
+ _prevState = false;
}
traverse(node, nv);
}
SGSharedPtr<const SGPropertyNode> _textureProp;
SGSharedPtr<const SGPropertyNode> _thresholdProp;
std::string _textureName;
- ColorSpec _ambient;
- ColorSpec _diffuse;
- ColorSpec _specular;
- ColorSpec _emission;
- PropSpec _shininess;
- PropSpec _transparency;
+ MaterialPropertyAdapter _materialProps;
osgDB::FilePathList _texturePathList;
+ bool _prevState;
};
} // namespace
SGMaterialAnimation::SGMaterialAnimation(const SGPropertyNode* configNode,
- SGPropertyNode* modelRoot) :
- SGAnimation(configNode, modelRoot)
+ SGPropertyNode* modelRoot,
+ const osgDB::ReaderWriter::Options*
+ options) :
+ SGAnimation(configNode, modelRoot),
+ texturePathList(options->getDatabasePathList())
{
if (configNode->hasChild("global"))
SG_LOG(SG_IO, SG_ALERT, "Use of <global> in material animation is "
SGPropertyNode* inputRoot = getModelRoot();
const SGPropertyNode* node = getConfig()->getChild("property-base");
if (node)
- inputRoot = getModelRoot()->getRootNode()->getNode(node->getStringValue(),
- true);
-
- osgDB::FilePathList texturePathList = osgDB::getDataFilePathList();
-
- if (getConfig()->hasChild("texture-prop"))
- osg::StateSet* stateSet = group->getOrCreateStateSet();
+ inputRoot = getModelRoot()->getNode(node->getStringValue(), true);
+ osg::StateSet* stateSet = group->getOrCreateStateSet();
if (getConfig()->hasChild("texture")) {
std::string textureName = getConfig()->getStringValue("texture");
std::string textureFile;
textureFile = osgDB::findFileInPath(textureName, texturePathList);
if (!textureFile.empty()) {
- osg::StateSet* stateSet = group->getOrCreateStateSet();
osg::Texture2D* texture2D = SGLoadTexture2D(textureFile);
if (texture2D) {
stateSet->setTextureAttribute(0, texture2D,
}
if (getConfig()->hasChild("threshold-prop") ||
getConfig()->hasChild("threshold")) {
- osg::StateSet* stateSet = group->getOrCreateStateSet();
osg::AlphaFunc* alphaFunc = new osg::AlphaFunc;
alphaFunc->setFunction(osg::AlphaFunc::GREATER);
float threshold = getConfig()->getFloatValue("threshold", 0);
suppliedColors |= SHININESS;
if (getConfig()->hasChild("transparency"))
suppliedColors |= TRANSPARENCY;
-
+ osg::Material* mat = 0;
if (suppliedColors != 0) {
- osg::StateSet* stateSet = group->getOrCreateStateSet();
- osg::Material* mat;
-
- if (defaultMaterial.valid()) {
- mat = defaultMaterial.get();
+ if (defaultMaterial.valid()) {
+ mat = defaultMaterial.get();
+ } else {
+ mat = new osg::Material;
+ mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
+ }
+ mat->setDataVariance(osg::Object::DYNAMIC);
+ unsigned defaultColorModeMask = 0;
+ mat->setUpdateCallback(0); // Just to make sure.
+ switch (mat->getColorMode()) {
+ case osg::Material::OFF:
+ defaultColorModeMask = 0;
+ break;
+ case osg::Material::AMBIENT:
+ defaultColorModeMask = AMBIENT;
+ break;
+ case osg::Material::DIFFUSE:
+ defaultColorModeMask = DIFFUSE;
+ break;
+ case osg::Material::AMBIENT_AND_DIFFUSE:
+ defaultColorModeMask = AMBIENT | DIFFUSE;
+ break;
+ case osg::Material::SPECULAR:
+ defaultColorModeMask = SPECULAR;
+ break;
+ case osg::Material::EMISSION:
+ defaultColorModeMask = EMISSION;
+ break;
+ }
+ // Copy the color found by traversing geometry into the material
+ // in case we need to specify it (e.g., transparency) and it is
+ // not specified by the animation.
+ if (defaultAmbientDiffuse.x() >= 0) {
+ if (defaultColorModeMask & AMBIENT)
+ mat->setAmbient(osg::Material::FRONT_AND_BACK, defaultAmbientDiffuse);
+ if (defaultColorModeMask & DIFFUSE)
+ mat->setDiffuse(osg::Material::FRONT_AND_BACK, defaultAmbientDiffuse);
+ }
+ // Compute which colors in the animation override colors set via
+ // colorMode / glColor, and set the colorMode for the animation's
+ // material accordingly.
+ if (suppliedColors & TRANSPARENCY) {
+ // All colors will be affected by the material. Hope all the
+ // defaults are fine, if needed.
+ mat->setColorMode(osg::Material::OFF);
+ } else if ((suppliedColors & defaultColorModeMask) != 0) {
+ // First deal with the complicated AMBIENT/DIFFUSE case.
+ if ((defaultColorModeMask & AMBIENT_DIFFUSE) != 0) {
+ // glColor can supply colors not specified by the animation.
+ unsigned matColorModeMask = ((~suppliedColors & defaultColorModeMask)
+ & AMBIENT_DIFFUSE);
+ if ((matColorModeMask & DIFFUSE) != 0)
+ mat->setColorMode(osg::Material::DIFFUSE);
+ else if ((matColorModeMask & AMBIENT) != 0)
+ mat->setColorMode(osg::Material::AMBIENT);
+ else
+ mat->setColorMode(osg::Material::OFF);
} else {
- mat = new osg::Material;
- mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
- }
- mat->setDataVariance(osg::Object::DYNAMIC);
- unsigned defaultColorModeMask = 0;
- mat->setUpdateCallback(0); // Just to make sure.
- switch (mat->getColorMode()) {
- case osg::Material::OFF:
- defaultColorModeMask = 0;
- break;
- case osg::Material::AMBIENT:
- defaultColorModeMask = AMBIENT;
- break;
- case osg::Material::DIFFUSE:
- defaultColorModeMask = DIFFUSE;
- break;
- case osg::Material::AMBIENT_AND_DIFFUSE:
- defaultColorModeMask = AMBIENT | DIFFUSE;
- break;
- case osg::Material::SPECULAR:
- defaultColorModeMask = SPECULAR;
- break;
- case osg::Material::EMISSION:
- defaultColorModeMask = EMISSION;
- break;
- }
- // Copy the color found by traversing geometry into the material
- // in case we need to specify it (e.g., transparency) and it is
- // not specified by the animation.
- if (defaultAmbientDiffuse.x() >= 0) {
- if (defaultColorModeMask & AMBIENT)
- mat->setAmbient(osg::Material::FRONT_AND_BACK, defaultAmbientDiffuse);
- if (defaultColorModeMask & DIFFUSE)
- mat->setDiffuse(osg::Material::FRONT_AND_BACK, defaultAmbientDiffuse);
- }
- // Compute which colors in the animation override colors set via
- // colorMode / glColor, and set the colorMode for the animation's
- // material accordingly.
- if (suppliedColors & TRANSPARENCY) {
- // All colors will be affected by the material. Hope all the
- // defaults are fine, if needed.
- mat->setColorMode(osg::Material::OFF);
- } else if ((suppliedColors & defaultColorModeMask) != 0) {
- // First deal with the complicated AMBIENT/DIFFUSE case.
- if ((defaultColorModeMask & AMBIENT_DIFFUSE) != 0) {
- // glColor can supply colors not specified by the animation.
- unsigned matColorModeMask = ((~suppliedColors & defaultColorModeMask)
- & AMBIENT_DIFFUSE);
- if ((matColorModeMask & DIFFUSE) != 0)
- mat->setColorMode(osg::Material::DIFFUSE);
- else if ((matColorModeMask & AMBIENT) != 0)
- mat->setColorMode(osg::Material::AMBIENT);
- else
- mat->setColorMode(osg::Material::OFF);
- } else {
- // The animation overrides the glColor color.
- mat->setColorMode(osg::Material::OFF);
- }
- } else {
- // No overlap between the animation and color mode, so leave
- // the color mode alone.
+ // The animation overrides the glColor color.
+ mat->setColorMode(osg::Material::OFF);
}
- stateSet->setAttribute(mat,(osg::StateAttribute::ON
- | osg::StateAttribute::OVERRIDE));
+ } else {
+ // No overlap between the animation and color mode, so leave
+ // the color mode alone.
+ }
+ stateSet->setAttribute(mat,(osg::StateAttribute::ON
+ | osg::StateAttribute::OVERRIDE));
+ }
+ bool matAnimated = false;
+ if (mat) {
+ MaterialPropertyAdapter adapter(getConfig(), inputRoot);
+ adapter.setMaterialValues(stateSet);
+ matAnimated = adapter.isAnimated();
+ }
+ if (matAnimated || getConfig()->hasChild("texture-prop")
+ || getConfig()->hasChild("threshold-prop") || getCondition()) {
+ stateSet->setDataVariance(osg::Object::DYNAMIC);
+ group->setUpdateCallback(new UpdateCallback(texturePathList,
+ getCondition(),
+ getConfig(), inputRoot));
+ } else {
+ stateSet->setDataVariance(osg::Object::STATIC);
}
- group->setUpdateCallback(new UpdateCallback(texturePathList,
- getCondition(),
- getConfig(), inputRoot));
parent.addChild(group);
return group;
}