From 7795eb82395a17a719b7cce79f480efb18109bff Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 29 Jan 2005 10:31:25 +0000 Subject: [PATCH] Jim Wilson: This patch adds support to the model animation system for modifying emissive states on the fly so that it is possible to make "lights" appear to dimm. This is an example of a configuration entry which should explain how it is used: material-emission Face /controls/lighting/instruments-norm 1.0 0.8 0.5 Note the color entries are the emissive colors when the "property" value is 1.0. They are useful for tinting the light. The "property" itself must be float or double and is clamped to values between 0 ~ 1.0 inclusively. The "property" value is multiplied against the colors to get the actual material properties. Thus property value 0.0 = darkest, and 1.0 = brightest. --- simgear/scene/model/animation.cxx | 91 +++++++++++++++++++++++++++++++ simgear/scene/model/animation.hxx | 23 ++++++++ simgear/scene/model/model.cxx | 2 + 3 files changed, 116 insertions(+) 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)) {