From: curt Date: Mon, 10 May 2004 14:35:58 +0000 (+0000) Subject: Frederic Bouvier: X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=11a74f7a31ab53abafd2d709ea6896044f4a2947;p=simgear.git Frederic Bouvier: 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 , one for each specified. Usage : strobes with flash light. - allow randomization of the , by using _min_value__max_value_. The value computed once is between _min_value_ and _max_value_. - implement model personality in timed animation. If true 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. --- diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index 6ced0858..317df8e1 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -14,6 +14,7 @@ #include #include #include +#include #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 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 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; } diff --git a/simgear/scene/model/animation.hxx b/simgear/scene/model/animation.hxx index 76259c98..cac47686 100644 --- a/simgear/scene/model/animation.hxx +++ b/simgear/scene/model/animation.hxx @@ -12,8 +12,10 @@ #endif #include +#include SG_USING_STD(vector); +SG_USING_STD(map); #include #include @@ -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 _last_time_sec; + map _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 _branch_duration_specs; + bool _use_personality; + typedef map > 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; }; /** diff --git a/simgear/scene/model/flash.cxx b/simgear/scene/model/flash.cxx index 9e75421d..67a2ec52 100755 --- a/simgear/scene/model/flash.cxx +++ b/simgear/scene/model/flash.cxx @@ -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; diff --git a/simgear/scene/model/flash.hxx b/simgear/scene/model/flash.hxx index f94fef03..3ca3b6fe 100755 --- a/simgear/scene/model/flash.hxx +++ b/simgear/scene/model/flash.hxx @@ -1,3 +1,6 @@ +/** + * $Id$ + */ class SGFlash : public ssgBranch { diff --git a/simgear/scene/model/modellib.cxx b/simgear/scene/model/modellib.cxx index 3d3edd1b..8733f448 100644 --- a/simgear/scene/model/modellib.cxx +++ b/simgear/scene/model/modellib.cxx @@ -4,6 +4,7 @@ #include #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::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; }