]> git.mxchange.org Git - simgear.git/commitdiff
Jim Wilson:
authorehofman <ehofman>
Sat, 29 Jan 2005 10:31:25 +0000 (10:31 +0000)
committerehofman <ehofman>
Sat, 29 Jan 2005 10:31:25 +0000 (10:31 +0000)
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:

 <animation>
  <type>material-emission</type>
  <object-name>Face</object-name>
  <property>/controls/lighting/instruments-norm</property>
  <emiss-red>1.0</emiss-red>
  <emiss-green>0.8</emiss-green>
  <emiss-blue>0.5</emiss-blue>
 </animation>

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
simgear/scene/model/animation.hxx
simgear/scene/model/model.cxx

index abef683d05f0be4027b8304e478b6598f0e3c1b1..917e2b362b1761490dfd0a37223789182b14df87 100644 (file)
@@ -1111,6 +1111,97 @@ void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp)
 
 
 \f
+////////////////////////////////////////////////////////////////////////
+// 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; i<nb; i++) {
+      ssgEntity *e = b->getKid(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; i<nb; i++) {
+    ssgEntity *e = b->getKid(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
 ////////////////////////////////////////////////////////////////////////
index e1451d3935907f5eea79b0e620ca6d1a08e9c62c..abcae2e1021eee4be4534baad19b065d657a5822 100644 (file)
@@ -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
index 9091c3b5a1ca3896f772ed8a259d2cf0b7e8d1f2..3bbe52f8a8fad7d2561029fde908f13ccfe5cf60 100644 (file)
@@ -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)) {