diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index abef683d..917e2b36 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -1111,6 +1111,97 @@ void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp) +//////////////////////////////////////////////////////////////////////// +// Implementation of SGEmissionAnimation +//////////////////////////////////////////////////////////////////////// + +SGEmissionAnimation::SGEmissionAnimation( SGPropertyNode *prop_root, SGPropertyNode_ptr props) + : SGAnimation(props, new ssgBranch), + _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)) +{ + _color0 = props->getFloatValue("emiss-red", 0.0); + _color1 = props->getFloatValue("emiss-green", 0.0); + _color2 = props->getFloatValue("emiss-blue", 0.0); + _old_brightness = 0; + ssgSimpleState* _cached_material; + ssgSimpleState* _cloned_material; +} + +SGEmissionAnimation::~SGEmissionAnimation () +{ +} + +void SGEmissionAnimation::init() +{ + // clone material state(s) for this branch + cloneMaterials(_branch); +} + +void SGEmissionAnimation::cloneMaterials(ssgBranch *b) +{ + // clone material state(s) for this branch + int nb = b->getNumKids(); + + // Traverse the branch(es) and make clones of material settings for the leaves on + // this branch (ssgSimpleState objects). + // Try to be efficient (only make a new clone if the original is different + // than the previous). + + for (int i = 0; igetKid(i); + if (e->isAKindOf(ssgTypeLeaf())) { + ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState(); + // if this is a new material state, then make a copy of it... + if (!_cached_material || _cached_material != s) { + _cached_material = s; + _cloned_material = (ssgSimpleState*)s->clone(SSG_CLONE_STATE); + } + // set the material to the clone... + ((ssgLeaf*)e)->setState( _cloned_material ); + } else if (e->isAKindOf(ssgTypeBranch())) { + cloneMaterials( (ssgBranch*)e ); + } + } + +} + +int SGEmissionAnimation::update() +{ + float brightness = _prop->getFloatValue(); + + // clamp brightness 0 ~ 1 + if (brightness < 0.00) brightness = 0.00; + if (brightness > 1.00) brightness = 1.00; + + // no need to update states unless something changes... + if (brightness != _old_brightness) { + _old_brightness = brightness; // save it + float rd,gr,bl; + rd = _color0 * brightness; + gr = _color1 * brightness; + bl = _color2 * brightness; + setEmissionBranch(_branch, rd, gr, bl); + } + return 1; +} + +void SGEmissionAnimation::setEmissionBranch(ssgBranch *b, float color0, float color1, float color2) +{ + int nb = b->getNumKids(); + + for (int i = 0; igetKid(i); + if (e->isAKindOf(ssgTypeLeaf())) { + ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState(); + s->enable( GL_ALPHA_TEST ); + s->setMaterial( GL_EMISSION, color0, color1, color2, 0.0 ); + } else if (e->isAKindOf(ssgTypeBranch())) { + setEmissionBranch((ssgBranch*)e, color0, color1, color2); + } + } +} + + //////////////////////////////////////////////////////////////////////// // Implementation of SGFlashAnimation //////////////////////////////////////////////////////////////////////// diff --git a/simgear/scene/model/animation.hxx b/simgear/scene/model/animation.hxx index e1451d39..abcae2e1 100644 --- a/simgear/scene/model/animation.hxx +++ b/simgear/scene/model/animation.hxx @@ -433,6 +433,29 @@ private: }; +/** + * An "animation" to modify emissive values on leaf nodes + */ +class SGEmissionAnimation : public SGAnimation +{ +public: + SGEmissionAnimation(SGPropertyNode *prop_root, SGPropertyNode_ptr props); + virtual ~SGEmissionAnimation (); + virtual void init(); + virtual int update(); +private: + SGPropertyNode_ptr _prop; + ssgSimpleState* _cached_material; + ssgSimpleState* _cloned_material; + void cloneMaterials(ssgBranch *b); + void setEmissionBranch(ssgBranch *b, float color0, float color1, float color2); + float _color0; + float _color1; + float _color2; + float _old_brightness; +}; + + /** * An "animation" that compute a scale according to * the angle between an axis and the view direction diff --git a/simgear/scene/model/model.cxx b/simgear/scene/model/model.cxx index 9091c3b5..3bbe52f8 100644 --- a/simgear/scene/model/model.cxx +++ b/simgear/scene/model/model.cxx @@ -159,6 +159,8 @@ sgMakeAnimation( ssgBranch * model, ignore = true; } else if (!strcmp("alpha-test", type)) { animation = new SGAlphaTestAnimation(node); + } else if (!strcmp("material-emission", type)) { + animation = new SGEmissionAnimation(prop_root, node); } else if (!strcmp("flash", type)) { animation = new SGFlashAnimation(node); } else if (!strcmp("dist-scale", type)) {