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:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
37
simgear/scene/model/personality.cxx
Executable file
37
simgear/scene/model/personality.cxx
Executable 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;
|
||||
}
|
||||
}
|
||||
41
simgear/scene/model/personality.hxx
Executable file
41
simgear/scene/model/personality.hxx
Executable 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
|
||||
Reference in New Issue
Block a user