Frederic Bouvier:

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.
This commit is contained in:
curt
2004-05-10 14:59:02 +00:00
parent 11a74f7a31
commit 2866d1ace9
7 changed files with 156 additions and 40 deletions

View 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)

View File

@@ -18,6 +18,7 @@
#include "animation.hxx"
#include "flash.hxx"
#include "personality.hxx"
////////////////////////////////////////////////////////////////////////
@@ -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;
}

View 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;
};

View File

@@ -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

View 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;
}

View File

@@ -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;
}
}

View File

@@ -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