Duplicate light effect when animation is requested. Make dimmed lights work in multiplayer

This commit is contained in:
Frederic Bouvier
2012-06-24 23:06:12 +02:00
parent a781eea10e
commit f0b7a27fd4
+44 -72
View File
@@ -46,32 +46,29 @@ static EffectMap lightEffectMap;
class SGLightAnimation::UpdateCallback : public osg::NodeCallback { class SGLightAnimation::UpdateCallback : public osg::NodeCallback {
public: public:
UpdateCallback(string k, const SGExpressiond* v, SGVec4d a, SGVec4d d, SGVec4d s) : UpdateCallback(const SGExpressiond* v, SGVec4d a, SGVec4d d, SGVec4d s) :
_key(k),
_ambient(a), _ambient(a),
_diffuse(d), _diffuse(d),
_specular(s), _specular(s),
_animationValue(v) _animationValue(v)
{ {
_prev_values[k] = -1; _prev_value = -1;
} }
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{ {
double dim = _animationValue->getValue(); double dim = _animationValue->getValue();
if (dim != _prev_values[_key]) { if (dim != _prev_value) {
_prev_values[_key] = dim; _prev_value = dim;
simgear::EffectGeode* geode = dynamic_cast<simgear::EffectGeode*>( node );
if (geode != 0) {
osg::ref_ptr<simgear::Effect> effect = geode->getEffect();
osg::ref_ptr<simgear::Effect> effect;
EffectMap::iterator iter = lightEffectMap.find(_key);
if (iter != lightEffectMap.end() && iter->second.lock(effect)) {
SGPropertyNode* params = effect->parametersProp; SGPropertyNode* params = effect->parametersProp;
params->getNode("ambient")->setValue(_ambient * dim); params->getNode("ambient")->setValue(_ambient * dim);
params->getNode("diffuse")->setValue(_diffuse * dim); params->getNode("diffuse")->setValue(_diffuse * dim);
params->getNode("specular")->setValue(_specular * dim); params->getNode("specular")->setValue(_specular * dim);
BOOST_FOREACH(osg::ref_ptr<simgear::Technique>& technique, effect->techniques) BOOST_FOREACH(osg::ref_ptr<simgear::Technique>& technique, effect->techniques) {
{ BOOST_FOREACH(osg::ref_ptr<simgear::Pass>& pass, technique->passes) {
BOOST_FOREACH(osg::ref_ptr<simgear::Pass>& pass, technique->passes)
{
osg::Uniform* amb = pass->getUniform("Ambient"); osg::Uniform* amb = pass->getUniform("Ambient");
if (amb) if (amb)
amb->set(osg::Vec4f(_ambient.x() * dim, _ambient.y() * dim, _ambient.z() * dim, _ambient.w() * dim)); amb->set(osg::Vec4f(_ambient.x() * dim, _ambient.y() * dim, _ambient.z() * dim, _ambient.w() * dim));
@@ -88,16 +85,12 @@ public:
traverse(node, nv); traverse(node, nv);
} }
public: public:
string _key;
SGVec4d _ambient; SGVec4d _ambient;
SGVec4d _diffuse; SGVec4d _diffuse;
SGVec4d _specular; SGVec4d _specular;
SGSharedPtr<SGExpressiond const> _animationValue; SGSharedPtr<SGExpressiond const> _animationValue;
double _prev_value;
typedef std::map<string, double> PrevValueMap;
static PrevValueMap _prev_values;
}; };
SGLightAnimation::UpdateCallback::PrevValueMap SGLightAnimation::UpdateCallback::_prev_values;
SGLightAnimation::SGLightAnimation(const SGPropertyNode* configNode, SGLightAnimation::SGLightAnimation(const SGPropertyNode* configNode,
SGPropertyNode* modelRoot, SGPropertyNode* modelRoot,
@@ -130,8 +123,6 @@ SGLightAnimation::createAnimationGroup(osg::Group& parent)
{ {
osg::Group* grp = new osg::Group; osg::Group* grp = new osg::Group;
grp->setName("light animation node"); grp->setName("light animation node");
if (_animationValue.valid())
grp->setUpdateCallback(new UpdateCallback(_key, _animationValue, _ambient, _diffuse, _specular));
parent.addChild(grp); parent.addChild(grp);
grp->setNodeMask( simgear::MODELLIGHT_BIT ); grp->setNodeMask( simgear::MODELLIGHT_BIT );
return grp; return grp;
@@ -142,12 +133,17 @@ SGLightAnimation::install(osg::Node& node)
{ {
SGAnimation::install(node); SGAnimation::install(node);
if (_light_type == "spot") { bool cacheEffect = false;
osg::ref_ptr<simgear::Effect> effect;
EffectMap::iterator iter = lightEffectMap.end();
if (!_animationValue.valid()) { // Effects with animated properties should be singletons
iter = lightEffectMap.find(_key);
cacheEffect = true;
}
osg::ref_ptr<simgear::Effect> effect; if (iter == lightEffectMap.end() || !iter->second.lock(effect)) {
EffectMap::iterator iter = lightEffectMap.find(_key); SGPropertyNode_ptr effectProp = new SGPropertyNode;
if (iter == lightEffectMap.end() || !iter->second.lock(effect)) { if (_light_type == "spot") {
SGPropertyNode_ptr effectProp = new SGPropertyNode;
makeChild(effectProp, "name")->setStringValue(_key); makeChild(effectProp, "name")->setStringValue(_key);
makeChild(effectProp, "inherits-from")->setStringValue("Effects/light-spot"); makeChild(effectProp, "inherits-from")->setStringValue("Effects/light-spot");
double dim = 1.0; double dim = 1.0;
@@ -166,37 +162,8 @@ SGLightAnimation::install(osg::Node& node)
params->getNode("cosCutoff",true)->setValue( cos(_cutoff*SG_DEGREES_TO_RADIANS) ); params->getNode("cosCutoff",true)->setValue( cos(_cutoff*SG_DEGREES_TO_RADIANS) );
params->getNode("near",true)->setValue(_near); params->getNode("near",true)->setValue(_near);
params->getNode("far",true)->setValue(_far); params->getNode("far",true)->setValue(_far);
effect = simgear::makeEffect(effectProp, true);
if (iter==lightEffectMap.end())
lightEffectMap.insert(EffectMap::value_type(_key, effect));
else
iter->second = effect;
} else {
effect = iter->second.get();
} }
else if (_light_type == "point") {
node.setNodeMask( simgear::MODELLIGHT_BIT );
simgear::EffectGeode* geode = dynamic_cast<simgear::EffectGeode*>(&node);
if (geode == 0) {
osg::Group* grp = node.asGroup();
if (grp != 0) {
for (size_t i=0; i<grp->getNumChildren(); ++i) {
geode = dynamic_cast<simgear::EffectGeode*>(grp->getChild(i));
if (geode) {
geode->setNodeMask( simgear::MODELLIGHT_BIT );
geode->setEffect(effect);
}
}
}
}
}
else if (_light_type == "point") {
osg::ref_ptr<simgear::Effect> effect;
EffectMap::iterator iter = lightEffectMap.find(_key);
if (iter == lightEffectMap.end() || !iter->second.lock(effect)) {
SGPropertyNode_ptr effectProp = new SGPropertyNode;
makeChild(effectProp, "name")->setStringValue(_key); makeChild(effectProp, "name")->setStringValue(_key);
makeChild(effectProp, "inherits-from")->setStringValue("Effects/light-point"); makeChild(effectProp, "inherits-from")->setStringValue("Effects/light-point");
double dim = 1.0; double dim = 1.0;
@@ -211,29 +178,34 @@ SGLightAnimation::install(osg::Node& node)
params->getNode("attenuation",true)->setValue(_attenuation); params->getNode("attenuation",true)->setValue(_attenuation);
params->getNode("near",true)->setValue(_near); params->getNode("near",true)->setValue(_near);
params->getNode("far",true)->setValue(_far); params->getNode("far",true)->setValue(_far);
effect = simgear::makeEffect(effectProp, true);
if (iter==lightEffectMap.end())
lightEffectMap.insert(EffectMap::value_type(_key, effect));
else
iter->second = effect;
} else { } else {
effect = iter->second.get(); return;
} }
node.setNodeMask( simgear::MODELLIGHT_BIT ); effect = simgear::makeEffect(effectProp, true);
simgear::EffectGeode* geode = dynamic_cast<simgear::EffectGeode*>(&node); if (iter == lightEffectMap.end() && cacheEffect)
if (geode == 0) { lightEffectMap.insert(EffectMap::value_type(_key, effect));
osg::Group* grp = node.asGroup(); else if (cacheEffect)
if (grp != 0) { iter->second = effect;
for (size_t i=0; i<grp->getNumChildren(); ++i) { } else {
geode = dynamic_cast<simgear::EffectGeode*>(grp->getChild(i)); effect = iter->second.get();
if (geode) { }
geode->setNodeMask( simgear::MODELLIGHT_BIT );
geode->setEffect(effect); node.setNodeMask( simgear::MODELLIGHT_BIT );
} simgear::EffectGeode* geode = dynamic_cast<simgear::EffectGeode*>(&node);
if (geode == 0) {
osg::Group* grp = node.asGroup();
if (grp != 0) {
for (size_t i=0; i<grp->getNumChildren(); ++i) {
geode = dynamic_cast<simgear::EffectGeode*>(grp->getChild(i));
if (geode) {
geode->setNodeMask( simgear::MODELLIGHT_BIT );
geode->setEffect(effect);
} }
} }
} }
} }
if (geode != 0 && _animationValue.valid())
geode->setUpdateCallback(new UpdateCallback(_animationValue, _ambient, _diffuse, _specular));
} }