]> git.mxchange.org Git - simgear.git/commitdiff
Frederic Bouvier:
authorcurt <curt>
Mon, 10 May 2004 14:35:58 +0000 (14:35 +0000)
committercurt <curt>
Mon, 10 May 2004 14:35:58 +0000 (14:35 +0000)
modellib.cxx :
  Add a branch between the model and its transformation to add
 a unique identifier for the model. I called it "personality
 branch" and it maintains a "current_object" in SGAnimation.
 Animations specifically written to support it ( currently only
 the timed animation ) can add a degree of variety among the
 occurrences of the same model that would look otherwise cloned.

flash.[ch]xx :
  Better compute the view vector. The flash is now syncronized with
 its axis even at the edge of the screen.

animation.[ch]xx :
  Lots of changes :
 - add a condition to 'rotate', 'spin', 'translate' and 'range'.
  When a condition is specified *and* it evaluates to false, the
  animation becomes a no-op. Possible usage : no rotation during
  daylight, LOD range variable along the day, ...

 - use different durations for each branch in the timed animation.
  Enable the use of multiple <branch-duration-sec>, one for each
  <object-name> specified. Usage : strobes with flash light.

 - allow randomization of the <branch-duration-sec>, by using
  <random><min>_min_value_</min><max>_max_value_</max></random>.
  The value computed once is between _min_value_ and _max_value_.

 - implement model personality in timed animation. If
  <use-personality type="bool">true</use-personality> is specified,
  a different set of duration is created for every model in the
  scenegraph using this animation. Best if used with randomization.
  When using strobes where the population of the same object is
  dense, it avoids the "cheasy" clone effect.

simgear/scene/model/animation.cxx
simgear/scene/model/animation.hxx
simgear/scene/model/flash.cxx
simgear/scene/model/flash.hxx
simgear/scene/model/modellib.cxx

index 6ced085855e3ac2b8e603a84640803792d6300e2..317df8e169903fa5c05c88d44ed13ccc9cf897d5 100644 (file)
@@ -14,6 +14,7 @@
 #include <simgear/math/interpolater.hxx>
 #include <simgear/props/condition.hxx>
 #include <simgear/props/props.hxx>
+#include <simgear/math/sg_random.h>
 
 #include "animation.hxx"
 #include "flash.hxx"
@@ -174,6 +175,7 @@ read_interpolation_table (SGPropertyNode_ptr props)
 
 // Initialize the static data member
 double SGAnimation::sim_time_sec = 0.0;
+ssgBranch *SGAnimation::current_object = 0;
 
 SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
     : _branch(branch)
@@ -225,12 +227,16 @@ SGNullAnimation::~SGNullAnimation ()
 SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
                                     SGPropertyNode_ptr props)
   : SGAnimation(props, new ssgRangeSelector),
-    _min(0.0), _max(0.0), _min_factor(1.0), _max_factor(1.0)
-
+    _min(0.0), _max(0.0), _min_factor(1.0), _max_factor(1.0),
+    _condition(0)
 {
+    SGPropertyNode_ptr node = props->getChild("condition");
+    if (node != 0)
+       _condition = sgReadCondition(prop_root, node);
+
     float ranges[2];
 
-    SGPropertyNode_ptr node = props->getChild( "min-factor" );
+    node = props->getChild( "min-factor" );
     if (node != 0) {
        _min_factor = props->getFloatValue("min-factor", 1.0);
     }
@@ -264,23 +270,23 @@ SGRangeAnimation::~SGRangeAnimation ()
 int
 SGRangeAnimation::update()
 {
-    float ranges[2];
-    bool upd = false;
+  float ranges[2];
+  if ( _condition == 0 || _condition->test() ) {
     if (_min_prop != 0) {
-       ranges[0] = _min_prop->getFloatValue() * _min_factor;
-       upd = true;
+      ranges[0] = _min_prop->getFloatValue() * _min_factor;
     } else {
-       ranges[0] = _min * _min_factor;
+      ranges[0] = _min * _min_factor;
     }
     if (_max_prop != 0) {
-       ranges[1] = _max_prop->getFloatValue() * _max_factor;
-       upd = true;
+      ranges[1] = _max_prop->getFloatValue() * _max_factor;
     } else {
-       ranges[1] = _max * _max_factor;
-    }
-    if (upd) {
-       ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
+      ranges[1] = _max * _max_factor;
     }
+  } else {
+    ranges[0] = 0.f;
+    ranges[1] = 1000000000.f;
+  }
+  ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
   return 1;
 }
 
@@ -343,8 +349,13 @@ SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
     _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
     _factor(props->getDoubleValue("factor", 1.0)),
     _position_deg(props->getDoubleValue("starting-position-deg", 0)),
-    _last_time_sec( sim_time_sec )
+    _last_time_sec( sim_time_sec ),
+    _condition(0)
 {
+    SGPropertyNode_ptr node = props->getChild("condition");
+    if (node != 0)
+        _condition = sgReadCondition(prop_root, node);
+
     _center[0] = 0;
     _center[1] = 0;
     _center[2] = 0;
@@ -383,17 +394,19 @@ SGSpinAnimation::~SGSpinAnimation ()
 int
 SGSpinAnimation::update()
 {
-  double dt = sim_time_sec - _last_time_sec;
-  _last_time_sec = sim_time_sec;
-
-  float velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
-  _position_deg += (dt * velocity_rpms * 360);
-  while (_position_deg < 0)
-    _position_deg += 360.0;
-  while (_position_deg >= 360.0)
-    _position_deg -= 360.0;
-  set_rotation(_matrix, _position_deg, _center, _axis);
-  ((ssgTransform *)_branch)->setTransform(_matrix);
+  if ( _condition == 0 || _condition->test() ) {
+    double dt = sim_time_sec - _last_time_sec;
+    _last_time_sec = sim_time_sec;
+
+    float velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
+    _position_deg += (dt * velocity_rpms * 360);
+    while (_position_deg < 0)
+        _position_deg += 360.0;
+    while (_position_deg >= 360.0)
+        _position_deg -= 360.0;
+    set_rotation(_matrix, _position_deg, _center, _axis);
+    ((ssgTransform *)_branch)->setTransform(_matrix);
+  }
   return 1;
 }
 
@@ -406,9 +419,25 @@ SGSpinAnimation::update()
 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
   : SGAnimation(props, new ssgSelector),
     _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
-    _last_time_sec(0),
-    _step(-1)
+    _step( 0 ),
+    _use_personality( props->getBoolValue("use-personality",false) )
 {
+    vector<SGPropertyNode_ptr> nodes = props->getChildren( "branch-duration-sec" );
+    size_t nb = nodes.size();
+    for ( size_t i = 0; i < nb; i++ ) {
+        size_t ind = nodes[ i ]->getIndex();
+        while ( ind >= _branch_duration_specs.size() ) {
+            _branch_duration_specs.push_back( DurationSpec( _duration_sec ) );
+        }
+        SGPropertyNode_ptr rNode = nodes[ i ]->getChild("random");
+        if ( rNode == 0 ) {
+            _branch_duration_specs[ ind ] = DurationSpec( nodes[ i ]->getDoubleValue() );
+        } else {
+            _branch_duration_specs[ ind ] = DurationSpec( rNode->getDoubleValue( "min", 0.0 ),
+                                                          rNode->getDoubleValue( "max", 1.0 ) );
+        }
+    }
+    ((ssgSelector *)getBranch())->selectStep(_step);
 }
 
 SGTimedAnimation::~SGTimedAnimation ()
@@ -418,14 +447,37 @@ SGTimedAnimation::~SGTimedAnimation ()
 int
 SGTimedAnimation::update()
 {
-    if ((sim_time_sec - _last_time_sec) >= _duration_sec) {
-        _last_time_sec = sim_time_sec;
-        _step++;
-        if (_step >= getBranch()->getNumKids())
+    ssgBranch *key = ( _use_personality ? current_object : 0 );
+    PersonalityMap::iterator it = _branch_duration_sec.find( key );
+    if ( it == _branch_duration_sec.end() ) {
+        vector<double> durations;
+        double total = 0;
+        for ( size_t i = 0; i < _branch_duration_specs.size(); i++ ) {
+            DurationSpec &sp = _branch_duration_specs[ i ];
+            double v = sp._min + sg_random() * ( sp._max - sp._min );
+            durations.push_back( v );
+            total += v;
+        }
+        it = _branch_duration_sec.insert( PersonalityMap::value_type( key, durations ) ).first;
+        _last_time_sec[ key ] = sim_time_sec;
+        _total_duration_sec[ key ] = total;
+    }
+
+    while ( ( sim_time_sec - _last_time_sec[ key ] ) >= _total_duration_sec[ key ] ) {
+        _last_time_sec[ key ] += _total_duration_sec[ key ];
+    }
+    double duration = _duration_sec;
+    if ( _step < (int)it->second.size() ) {
+        duration = it->second[ _step ];
+    }
+    if ( ( sim_time_sec - _last_time_sec[ key ] ) >= duration ) {
+        _last_time_sec[ key ] += duration;
+        _step += 1;
+        if ( _step >= getBranch()->getNumKids() )
             _step = 0;
-        ((ssgSelector *)getBranch())->selectStep(_step);
+        ((ssgSelector *)getBranch())->selectStep( _step );
     }
-  return 1;
+    return 1;
 }
 
 
@@ -445,8 +497,13 @@ SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
       _min_deg(props->getDoubleValue("min-deg")),
       _has_max(props->hasValue("max-deg")),
       _max_deg(props->getDoubleValue("max-deg")),
-      _position_deg(props->getDoubleValue("starting-position-deg", 0))
+      _position_deg(props->getDoubleValue("starting-position-deg", 0)),
+      _condition(0)
 {
+    SGPropertyNode_ptr node = props->getChild("condition");
+    if (node != 0)
+      _condition = sgReadCondition(prop_root, node);
+
     _center[0] = 0;
     _center[1] = 0;
     _center[2] = 0;
@@ -486,17 +543,19 @@ SGRotateAnimation::~SGRotateAnimation ()
 int
 SGRotateAnimation::update()
 {
-  if (_table == 0) {
-   _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
-   if (_has_min && _position_deg < _min_deg)
-     _position_deg = _min_deg;
-   if (_has_max && _position_deg > _max_deg)
-     _position_deg = _max_deg;
-  } else {
-    _position_deg = _table->interpolate(_prop->getDoubleValue());
+  if (_condition == 0 || _condition->test()) {
+    if (_table == 0) {
+      _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
+      if (_has_min && _position_deg < _min_deg)
+        _position_deg = _min_deg;
+      if (_has_max && _position_deg > _max_deg)
+        _position_deg = _max_deg;
+    } else {
+      _position_deg = _table->interpolate(_prop->getDoubleValue());
+    }
+    set_rotation(_matrix, _position_deg, _center, _axis);
+    ((ssgTransform *)_branch)->setTransform(_matrix);
   }
-  set_rotation(_matrix, _position_deg, _center, _axis);
-  ((ssgTransform *)_branch)->setTransform(_matrix);
   return 1;
 }
 
@@ -565,8 +624,13 @@ SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
     _min_m(props->getDoubleValue("min-m")),
     _has_max(props->hasValue("max-m")),
     _max_m(props->getDoubleValue("max-m")),
-    _position_m(props->getDoubleValue("starting-position-m", 0))
+    _position_m(props->getDoubleValue("starting-position-m", 0)),
+    _condition(0)
 {
+  SGPropertyNode_ptr node = props->getChild("condition");
+  if (node != 0)
+    _condition = sgReadCondition(prop_root, node);
+
   _axis[0] = props->getFloatValue("axis/x", 0);
   _axis[1] = props->getFloatValue("axis/y", 0);
   _axis[2] = props->getFloatValue("axis/z", 0);
@@ -581,17 +645,19 @@ SGTranslateAnimation::~SGTranslateAnimation ()
 int
 SGTranslateAnimation::update()
 {
-  if (_table == 0) {
-    _position_m = (_prop->getDoubleValue() + _offset_m) * _factor;
-    if (_has_min && _position_m < _min_m)
-      _position_m = _min_m;
-    if (_has_max && _position_m > _max_m)
-      _position_m = _max_m;
-  } else {
-    _position_m = _table->interpolate(_prop->getDoubleValue());
+  if (_condition == 0 || _condition->test()) {
+    if (_table == 0) {
+      _position_m = (_prop->getDoubleValue() + _offset_m) * _factor;
+      if (_has_min && _position_m < _min_m)
+        _position_m = _min_m;
+      if (_has_max && _position_m > _max_m)
+        _position_m = _max_m;
+    } else {
+      _position_m = _table->interpolate(_prop->getDoubleValue());
+    }
+    set_translation(_matrix, _position_m, _axis);
+    ((ssgTransform *)_branch)->setTransform(_matrix);
   }
-  set_translation(_matrix, _position_m, _axis);
-  ((ssgTransform *)_branch)->setTransform(_matrix);
   return 1;
 }
 
index 76259c980f3423e4ed28c05fb64ce0537a33d2ed..cac476867a240491d422e4b929eba972fbc4dde7 100644 (file)
 #endif
 
 #include <vector>
+#include <map>
 
 SG_USING_STD(vector);
+SG_USING_STD(map);
 
 #include <plib/sg.h>
 #include <plib/ssg.h>
@@ -78,6 +80,12 @@ public:
    */
   static void set_sim_time_sec( double val ) { sim_time_sec = val; }
 
+  /**
+   * Current personality branch : enable animation to behave differently
+   * for similar objects
+   */
+  static ssgBranch *current_object;
+
 protected:
 
   static double sim_time_sec;
@@ -115,6 +123,7 @@ private:
   float _max;
   float _min_factor;
   float _max_factor;
+  SGCondition * _condition;
 };
 
 
@@ -165,6 +174,7 @@ private:
   sgMat4 _matrix;
   sgVec3 _center;
   sgVec3 _axis;
+  SGCondition * _condition;
 };
 
 
@@ -179,8 +189,18 @@ public:
     virtual int update();
 private:
     double _duration_sec;
-    double _last_time_sec;
+    map<ssgBranch *,double> _last_time_sec;
+    map<ssgBranch *,double> _total_duration_sec;
     int _step;
+    struct DurationSpec {
+        DurationSpec( double m = 0.0 ) : _min(m), _max(m) {}
+        DurationSpec( double m1, double m2 ) : _min(m1), _max(m2) {}
+        double _min, _max;
+    };
+    vector<DurationSpec> _branch_duration_specs;
+    bool _use_personality;
+    typedef map<ssgBranch *,vector<double> > PersonalityMap;
+    PersonalityMap _branch_duration_sec;
 };
 
 
@@ -208,6 +228,7 @@ private:
   sgMat4 _matrix;
   sgVec3 _center;
   sgVec3 _axis;
+  SGCondition * _condition;
 };
 
 
@@ -233,6 +254,7 @@ private:
   double _position_m;
   sgMat4 _matrix;
   sgVec3 _axis;
+  SGCondition * _condition;
 };
 
 /**
index 9e75421d9667b664e8c95e5ee8be85535b24e36b..67a2ec52741041470fc23b263fba8c72e74103fb 100755 (executable)
@@ -74,7 +74,11 @@ void SGFlash::cull( sgFrustum *f, sgMat4 m, int test_needed )
   sgXformVec3( transformed_axis, _axis, m );
   sgNormalizeVec3( transformed_axis );
 
-  float cos_angle = transformed_axis[ 2 ]; // z component, through the screen
+  sgVec3 view;
+  sgFullXformPnt3( view, _center, m );
+  sgNormalizeVec3( view );
+
+  float cos_angle = -sgScalarProductVec3( transformed_axis, view );
   float scale_factor = 0.f;
   if ( _two_sides && cos_angle < 0 )
     scale_factor = _factor * (float)pow( -cos_angle, _power ) + _offset;
index f94fef03ee1c4d65d5b7c48cfa7927b2a872c04c..3ca3b6fe54bd30d677db2bb2f80ad8f1e514d9e6 100755 (executable)
@@ -1,3 +1,6 @@
+/**
+ * $Id$
+ */
 
 class SGFlash : public ssgBranch
 {
index 3d3edd1bd1f483695ec9f839d9314f6bd32c1cd9..8733f4481b1171f896bd86f1c8789cbe985ad583 100644 (file)
@@ -4,6 +4,7 @@
 #include <simgear/props/props.hxx>
 
 #include "model.hxx"
+#include "animation.hxx"
 
 #include "modellib.hxx"
 
@@ -60,6 +61,25 @@ SGModelLib::flush1()
     }
 }
 
+struct SGPersonalityBranch : public ssgBranch {
+    ssgBranch *_old_current;
+};
+
+static int
+personality_pretrav_callback(ssgEntity * entity, int mask)
+{
+    ((SGPersonalityBranch *)entity)->_old_current = SGAnimation::current_object;
+    SGAnimation::current_object = (ssgBranch *)entity;
+    return 1;
+}
+
+static int
+personality_posttrav_callback(ssgEntity * entity, int mask)
+{
+    SGAnimation::current_object = ((SGPersonalityBranch *)entity)->_old_current;
+    ((SGPersonalityBranch *)entity)->_old_current = 0;
+    return 1;
+}
 
 ssgEntity *
 SGModelLib::load_model( const string &fg_root,
@@ -67,6 +87,10 @@ SGModelLib::load_model( const string &fg_root,
                            SGPropertyNode *prop_root,
                            double sim_time_sec )
 {
+    ssgBranch *personality_branch = new SGPersonalityBranch;
+    personality_branch->setTravCallback(SSG_CALLBACK_PRETRAV, personality_pretrav_callback);
+    personality_branch->setTravCallback(SSG_CALLBACK_POSTTRAV, personality_posttrav_callback);
+
                                 // FIXME: normalize path to
                                 // avoid duplicates.
     map<string, ssgBase *>::iterator it = _table.find(path);
@@ -75,10 +99,11 @@ SGModelLib::load_model( const string &fg_root,
                                           sim_time_sec );
         model->ref();
         _table[path] = model;      // add one reference to keep it around
-        return model;
+        personality_branch->addKid( model );
     } else {
-        return (ssgEntity *)it->second;
+        personality_branch->addKid( (ssgEntity *)it->second );
     }
+    return personality_branch;
 }