]> git.mxchange.org Git - simgear.git/commitdiff
Frederic Bouvier:
authorcurt <curt>
Mon, 10 May 2004 14:59:02 +0000 (14:59 +0000)
committercurt <curt>
Mon, 10 May 2004 14:59:02 +0000 (14:59 +0000)
Fix a memory leak, and brownian animation, if not motion.

I have 2 new files : personality.[ch]xx . They store the personality
data that would be deleted when the object is destroyed, instead
of staying in the animation maps. I also manage the current animation
step better and the towers are not flashing randomly now.
Makefile.am is updated.

simgear/scene/model/Makefile.am
simgear/scene/model/animation.cxx
simgear/scene/model/animation.hxx
simgear/scene/model/flash.hxx
simgear/scene/model/modellib.cxx
simgear/scene/model/personality.cxx [new file with mode: 0755]
simgear/scene/model/personality.hxx [new file with mode: 0755]

index 4ab768d6f828d1a9ca3daaf5371838b572a4743d..e9b91a7d15fbe2e57a2dbe9463ef5876db5037db 100644 (file)
@@ -10,6 +10,7 @@ include_HEADERS = \
        location.hxx \
        model.hxx \
        modellib.hxx \
+       personality.hxx \
        placement.hxx
 
 libsgmodel_a_SOURCES = \
@@ -18,6 +19,7 @@ libsgmodel_a_SOURCES = \
        location.cxx \
        model.cxx \
        modellib.cxx \
+       personality.cxx \
        placement.cxx
 
 INCLUDES = -I$(top_srcdir)
index 317df8e169903fa5c05c88d44ed13ccc9cf897d5..a068d4c1d722ac455c40c74c1a4c327cb940f1ea 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "animation.hxx"
 #include "flash.hxx"
+#include "personality.hxx"
 
 \f
 ////////////////////////////////////////////////////////////////////////
@@ -175,7 +176,7 @@ read_interpolation_table (SGPropertyNode_ptr props)
 
 // Initialize the static data member
 double SGAnimation::sim_time_sec = 0.0;
-ssgBranch *SGAnimation::current_object = 0;
+SGPersonalityBranch *SGAnimation::current_object = 0;
 
 SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
     : _branch(branch)
@@ -418,9 +419,12 @@ SGSpinAnimation::update()
 
 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
   : SGAnimation(props, new ssgSelector),
+    _use_personality( props->getBoolValue("use-personality",false) ),
     _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
-    _step( 0 ),
-    _use_personality( props->getBoolValue("use-personality",false) )
+    _last_time_sec( sim_time_sec ),
+    _total_duration_sec( 0 ),
+    _step( 0 )
+    
 {
     vector<SGPropertyNode_ptr> nodes = props->getChildren( "branch-duration-sec" );
     size_t nb = nodes.size();
@@ -437,6 +441,14 @@ SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
                                                           rNode->getDoubleValue( "max", 1.0 ) );
         }
     }
+    if ( !_use_personality ) {
+        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 );
+            _branch_duration_sec.push_back( v );
+            _total_duration_sec += v;
+        }
+    }
     ((ssgSelector *)getBranch())->selectStep(_step);
 }
 
@@ -447,35 +459,56 @@ SGTimedAnimation::~SGTimedAnimation ()
 int
 SGTimedAnimation::update()
 {
-    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;
+    if ( _use_personality ) {
+        SGPersonalityBranch *key = current_object;
+        if ( !key->getIntValue( this, INIT ) ) {
+            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 );
+                key->setDoubleValue( v, this, BRANCH_DURATION_SEC, i );
+                total += v;
+            }
+            key->setDoubleValue( sim_time_sec, this, LAST_TIME_SEC );
+            key->setDoubleValue( total, this, TOTAL_DURATION_SEC );
+            key->setIntValue( 0, this, STEP );
+            key->setIntValue( 1, this, INIT );
         }
-        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;
+        _step = key->getIntValue( this, STEP );
+        _last_time_sec = key->getDoubleValue( this, LAST_TIME_SEC );
+        _total_duration_sec = key->getDoubleValue( this, TOTAL_DURATION_SEC );
+        while ( ( sim_time_sec - _last_time_sec ) >= _total_duration_sec ) {
+            _last_time_sec += _total_duration_sec;
+        }
+        double duration = _duration_sec;
+        if ( _step < (int)_branch_duration_specs.size() ) {
+            duration = key->getDoubleValue( this, BRANCH_DURATION_SEC, _step );
+        }
+        if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
+            _last_time_sec += duration;
+            _step += 1;
+            if ( _step >= getBranch()->getNumKids() )
+                _step = 0;
+        }
         ((ssgSelector *)getBranch())->selectStep( _step );
+        key->setDoubleValue( _last_time_sec, this, LAST_TIME_SEC );
+        key->setIntValue( _step, this, STEP );
+    } else {
+        while ( ( sim_time_sec - _last_time_sec ) >= _total_duration_sec ) {
+            _last_time_sec += _total_duration_sec;
+        }
+        double duration = _duration_sec;
+        if ( _step < (int)_branch_duration_sec.size() ) {
+            duration = _branch_duration_sec[ _step ];
+        }
+        if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
+            _last_time_sec += duration;
+            _step += 1;
+            if ( _step >= getBranch()->getNumKids() )
+                _step = 0;
+            ((ssgSelector *)getBranch())->selectStep( _step );
+        }
     }
     return 1;
 }
index cac476867a240491d422e4b929eba972fbc4dde7..98193fce26cc3a0327c683d3f386e00e84d23243 100644 (file)
@@ -27,6 +27,7 @@ SG_USING_STD(map);
 // Don't pull in the headers, since we don't need them here.
 class SGInterpTable;
 class SGCondition;
+class SGPersonalityBranch;
 
 
 // Has anyone done anything *really* stupid, like making min and max macros?
@@ -84,7 +85,7 @@ public:
    * Current personality branch : enable animation to behave differently
    * for similar objects
    */
-  static ssgBranch *current_object;
+  static SGPersonalityBranch *current_object;
 
 protected:
 
@@ -188,9 +189,11 @@ public:
     virtual ~SGTimedAnimation ();
     virtual int update();
 private:
+    bool _use_personality;
+    enum PersonalityVar { INIT, LAST_TIME_SEC, TOTAL_DURATION_SEC, BRANCH_DURATION_SEC, STEP };
     double _duration_sec;
-    map<ssgBranch *,double> _last_time_sec;
-    map<ssgBranch *,double> _total_duration_sec;
+    double _last_time_sec;
+    double _total_duration_sec;
     int _step;
     struct DurationSpec {
         DurationSpec( double m = 0.0 ) : _min(m), _max(m) {}
@@ -198,9 +201,7 @@ private:
         double _min, _max;
     };
     vector<DurationSpec> _branch_duration_specs;
-    bool _use_personality;
-    typedef map<ssgBranch *,vector<double> > PersonalityMap;
-    PersonalityMap _branch_duration_sec;
+    vector<double> _branch_duration_sec;
 };
 
 
index 3ca3b6fe54bd30d677db2bb2f80ad8f1e514d9e6..47d4fe33f8245818169930622950f22edc3e59cc 100755 (executable)
@@ -2,6 +2,9 @@
  * $Id$
  */
 
+#ifndef _SG_FLASH_HXX
+#define _SG_FLASH_HXX 1
+
 class SGFlash : public ssgBranch
 {
 public:
@@ -30,3 +33,5 @@ private:
     float _power, _factor, _offset, _min_v, _max_v;
     bool _two_sides;
 };
+
+#endif // _SG_FLASH_HXX
index 8733f4481b1171f896bd86f1c8789cbe985ad583..49073d63908baf5de7fac98d267e2b0155653f05 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "model.hxx"
 #include "animation.hxx"
+#include "personality.hxx"
 
 #include "modellib.hxx"
 
@@ -61,15 +62,11 @@ 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;
+    SGAnimation::current_object = (SGPersonalityBranch *)entity;
     return 1;
 }
 
diff --git a/simgear/scene/model/personality.cxx b/simgear/scene/model/personality.cxx
new file mode 100755 (executable)
index 0000000..622137e
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * $Id$
+ */
+
+#include <simgear/compiler.h>
+
+#include "personality.hxx"
+
+void SGPersonalityBranch::setDoubleValue( double value, SGAnimation *anim, int var_id, int var_num )
+{
+    _doubleValues[ Key( anim, var_id, var_num ) ] = value;
+}
+
+void SGPersonalityBranch::setIntValue( int value, SGAnimation *anim, int var_id, int var_num )
+{
+    _intValues[ Key( anim, var_id, var_num ) ] = value;
+}
+
+double SGPersonalityBranch::getDoubleValue( SGAnimation *anim, int var_id, int var_num ) const
+{
+    map<Key,double>::const_iterator it = _doubleValues.find( Key( anim, var_id, var_num ) );
+    if ( it != _doubleValues.end() ) {
+        return it->second;
+    } else {
+        return 0;
+    }
+}
+
+int SGPersonalityBranch::getIntValue( SGAnimation *anim, int var_id, int var_num ) const
+{
+    map<Key,int>::const_iterator it = _intValues.find( Key( anim, var_id, var_num ) );
+    if ( it != _intValues.end() ) {
+        return it->second;
+    } else {
+        return 0;
+    }
+}
diff --git a/simgear/scene/model/personality.hxx b/simgear/scene/model/personality.hxx
new file mode 100755 (executable)
index 0000000..468d1e9
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * $Id$
+ */
+
+#ifndef _SG_PERSONALITY_HXX
+#define _SG_PERSONALITY_HXX 1
+
+#include <map>
+
+SG_USING_STD(map);
+
+#include <plib/ssg.h>
+
+class SGAnimation;
+
+class SGPersonalityBranch : public ssgBranch {
+public:
+    void setDoubleValue( double value, SGAnimation *anim, int var_id, int var_num = 0 );
+    void setIntValue( int value, SGAnimation *anim, int var_id, int var_num = 0 );
+    double getDoubleValue( SGAnimation *anim, int var_id, int var_num = 0 ) const;
+    int getIntValue( SGAnimation *anim, int var_id, int var_num = 0 ) const;
+
+    SGPersonalityBranch *_old_current;
+
+private:
+    struct Key {
+        Key( SGAnimation *a, int i, int n = 0 ) : anim(a), var_id(i), var_num(n) {}
+        SGAnimation *anim;
+        int var_id;
+        int var_num;
+        bool operator<( const Key &r ) const {
+                return anim < r.anim || 
+                    ( anim == r.anim && ( var_id < r.var_id ||
+                                        ( var_id == r.var_id && var_num < r.var_num ) ) );
+        }
+    };
+    map<Key,double> _doubleValues;
+    map<Key,int> _intValues;
+};
+
+#endif // _SG_PERSONALITY_HXX