From 4758447370f0ac241ebf9428193664e649351349 Mon Sep 17 00:00:00 2001 From: Frederic Bouvier Date: Sat, 14 Apr 2012 09:57:20 +0200 Subject: [PATCH] Add a parameter in the light animation contains a element, and optionally , , , , and --- simgear/scene/model/SGLightAnimation.cxx | 110 +++++++++++++++++++---- simgear/scene/model/animation.hxx | 3 + 2 files changed, 94 insertions(+), 19 deletions(-) diff --git a/simgear/scene/model/SGLightAnimation.cxx b/simgear/scene/model/SGLightAnimation.cxx index 108cd6d1..930d2db2 100644 --- a/simgear/scene/model/SGLightAnimation.cxx +++ b/simgear/scene/model/SGLightAnimation.cxx @@ -27,8 +27,12 @@ #include #include #include -#include +#include +#include #include +#include +#include +#include typedef std::map > EffectMap; static EffectMap lightEffectMap; @@ -39,6 +43,58 @@ static EffectMap lightEffectMap; getConfig()->getDoubleValue(n "/b"), \ getConfig()->getDoubleValue(n "/a") ) +class SGLightAnimation::UpdateCallback : public osg::NodeCallback { +public: + UpdateCallback(string k, const SGExpressiond* v, SGVec4d a, SGVec4d d, SGVec4d s) : + _key(k), + _ambient(a), + _diffuse(d), + _specular(s), + _animationValue(v) + { + _prev_values[k] = -1; + } + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + double dim = _animationValue->getValue(); + if (dim != _prev_values[_key]) { + _prev_values[_key] = dim; + + EffectMap::iterator iter = lightEffectMap.find(_key); + if (iter != lightEffectMap.end()) { + simgear::Effect* effect = iter->second; + SGPropertyNode* params = effect->parametersProp; + params->getNode("ambient")->setValue(_ambient * dim); + params->getNode("diffuse")->setValue(_diffuse * dim); + params->getNode("specular")->setValue(_specular * dim); + BOOST_FOREACH(osg::ref_ptr& technique, effect->techniques) + { + BOOST_FOREACH(osg::ref_ptr& pass, technique->passes) + { + osg::Uniform* amb = pass->getUniform("Ambient"); + amb->set(toOsg(_ambient) * dim); + osg::Uniform* dif = pass->getUniform("Diffuse"); + dif->set(toOsg(_diffuse) * dim); + osg::Uniform* spe = pass->getUniform("Specular"); + spe->set(toOsg(_specular) * dim); + } + } + } + } + traverse(node, nv); + } +public: + string _key; + SGVec4d _ambient; + SGVec4d _diffuse; + SGVec4d _specular; + SGSharedPtr _animationValue; + + typedef std::map PrevValueMap; + static PrevValueMap _prev_values; +}; +SGLightAnimation::UpdateCallback::PrevValueMap SGLightAnimation::UpdateCallback::_prev_values; + SGLightAnimation::SGLightAnimation(const SGPropertyNode* configNode, SGPropertyNode* modelRoot, const string &path, int i) : @@ -58,12 +114,20 @@ SGLightAnimation::SGLightAnimation(const SGPropertyNode* configNode, _near = getConfig()->getDoubleValue("near-m"); _far = getConfig()->getDoubleValue("far-m"); _key = path + ";" + boost::lexical_cast( i ); + + SGConstPropertyNode_ptr dim_factor = configNode->getChild("dim-factor"); + if (dim_factor.valid()) { + _animationValue = read_value(dim_factor, modelRoot, "", 0, 1); + } } osg::Group* SGLightAnimation::createAnimationGroup(osg::Group& parent) { osg::Group* grp = new osg::Group; + grp->setName("light animation node"); + if (_animationValue.valid()) + grp->setUpdateCallback(new UpdateCallback(_key, _animationValue, _ambient, _diffuse, _specular)); parent.addChild(grp); grp->setNodeMask( simgear::MODELLIGHT_BIT ); return grp; @@ -81,18 +145,22 @@ SGLightAnimation::install(osg::Node& node) if (iter == lightEffectMap.end()) { SGPropertyNode_ptr effectProp = new SGPropertyNode; makeChild(effectProp, "inherits-from")->setStringValue("Effects/light-spot"); + double dim = 1.0; + if (_animationValue.valid()) + dim = _animationValue->getValue(); + SGPropertyNode* params = makeChild(effectProp, "parameters"); - params->getNode("light-spot/position",true)->setValue(SGVec4d(_position.x(),_position.y(),_position.z(),1.0)); - params->getNode("light-spot/direction",true)->setValue(SGVec4d(_direction.x(),_direction.y(),_direction.z(),0.0)); - params->getNode("light-spot/ambient",true)->setValue(_ambient); - params->getNode("light-spot/diffuse",true)->setValue(_diffuse); - params->getNode("light-spot/specular",true)->setValue(_specular); - params->getNode("light-spot/attenuation",true)->setValue(_attenuation); - params->getNode("light-spot/exponent",true)->setValue(_exponent); - params->getNode("light-spot/cutoff",true)->setValue(_cutoff); - params->getNode("light-spot/cosCutoff",true)->setValue( cos(_cutoff*SG_DEGREES_TO_RADIANS) ); - params->getNode("light-spot/near",true)->setValue(_near); - params->getNode("light-spot/far",true)->setValue(_far); + params->getNode("position",true)->setValue(SGVec4d(_position.x(),_position.y(),_position.z(),1.0)); + params->getNode("direction",true)->setValue(SGVec4d(_direction.x(),_direction.y(),_direction.z(),0.0)); + params->getNode("ambient",true)->setValue(_ambient * dim); + params->getNode("diffuse",true)->setValue(_diffuse * dim); + params->getNode("specular",true)->setValue(_specular * dim); + params->getNode("attenuation",true)->setValue(_attenuation); + params->getNode("exponent",true)->setValue(_exponent); + params->getNode("cutoff",true)->setValue(_cutoff); + params->getNode("cosCutoff",true)->setValue( cos(_cutoff*SG_DEGREES_TO_RADIANS) ); + params->getNode("near",true)->setValue(_near); + params->getNode("far",true)->setValue(_far); effect = simgear::makeEffect(effectProp, true); lightEffectMap.insert(EffectMap::value_type(_key, effect)); @@ -120,14 +188,18 @@ SGLightAnimation::install(osg::Node& node) if (iter == lightEffectMap.end()) { SGPropertyNode_ptr effectProp = new SGPropertyNode; makeChild(effectProp, "inherits-from")->setStringValue("Effects/light-point"); + double dim = 1.0; + if (_animationValue.valid()) + dim = _animationValue->getValue(); + SGPropertyNode* params = makeChild(effectProp, "parameters"); - params->getNode("light-spot/position",true)->setValue(SGVec4d(_position.x(),_position.y(),_position.z(),1.0)); - params->getNode("light-spot/ambient",true)->setValue(_ambient); - params->getNode("light-spot/diffuse",true)->setValue(_diffuse); - params->getNode("light-spot/specular",true)->setValue(_specular); - params->getNode("light-spot/attenuation",true)->setValue(_attenuation); - params->getNode("light-spot/near",true)->setValue(_near); - params->getNode("light-spot/far",true)->setValue(_far); + params->getNode("position",true)->setValue(SGVec4d(_position.x(),_position.y(),_position.z(),1.0)); + params->getNode("ambient",true)->setValue(_ambient * dim); + params->getNode("diffuse",true)->setValue(_diffuse * dim); + params->getNode("specular",true)->setValue(_specular * dim); + params->getNode("attenuation",true)->setValue(_attenuation); + params->getNode("near",true)->setValue(_near); + params->getNode("far",true)->setValue(_far); effect = simgear::makeEffect(effectProp, true); lightEffectMap.insert(EffectMap::value_type(_key, effect)); diff --git a/simgear/scene/model/animation.hxx b/simgear/scene/model/animation.hxx index 31696192..57641d30 100644 --- a/simgear/scene/model/animation.hxx +++ b/simgear/scene/model/animation.hxx @@ -369,6 +369,9 @@ private: double _near; double _far; string _key; + class UpdateCallback; + friend class UpdateCallback; + SGSharedPtr _animationValue; }; #endif // _SG_ANIMATION_HXX -- 2.39.5