X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmodel%2Fanimation.cxx;h=8a1c73e2281ef3bb5701cdc727f25969bf626b84;hb=b199f733f7a71218a20c3408af570aa1edf92642;hp=6ced085855e3ac2b8e603a84640803792d6300e2;hpb=ffada9257d18a888ea846338882ac6b9ec014e28;p=simgear.git diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index 6ced0858..8a1c73e2 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -14,9 +14,11 @@ #include #include #include +#include #include "animation.hxx" -#include "flash.hxx" +#include "custtrans.hxx" +#include "personality.hxx" //////////////////////////////////////////////////////////////////////// @@ -174,11 +176,17 @@ read_interpolation_table (SGPropertyNode_ptr props) // Initialize the static data member double SGAnimation::sim_time_sec = 0.0; +SGPersonalityBranch *SGAnimation::current_object = 0; SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch) : _branch(branch) { _branch->setName(props->getStringValue("name", 0)); + if ( props->getBoolValue( "enable-hot", true ) ) { + _branch->setTraversalMaskBits( SSGTRAV_HOT ); + } else { + _branch->clrTraversalMaskBits( SSGTRAV_HOT ); + } } SGAnimation::~SGAnimation () @@ -225,12 +233,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 +276,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 +355,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 +400,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; } @@ -405,27 +424,120 @@ 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)), - _last_time_sec(0), - _step(-1) + _last_time_sec( sim_time_sec ), + _total_duration_sec( 0 ), + _step( 0 ) + { + 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 ) ); + } + } } SGTimedAnimation::~SGTimedAnimation () { } +void +SGTimedAnimation::init() +{ + if ( !_use_personality ) { + for ( size_t i = 0; i < getBranch()->getNumKids(); i++ ) { + double v; + if ( i < _branch_duration_specs.size() ) { + DurationSpec &sp = _branch_duration_specs[ i ]; + v = sp._min + sg_random() * ( sp._max - sp._min ); + } else { + v = _duration_sec; + } + _branch_duration_sec.push_back( v ); + _total_duration_sec += v; + } + // Sanity check : total duration shouldn't equal zero + if ( _total_duration_sec < 0.01 ) { + _total_duration_sec = 0.01; + } + } + ((ssgSelector *)getBranch())->selectStep(_step); +} + int SGTimedAnimation::update() { - if ((sim_time_sec - _last_time_sec) >= _duration_sec) { - _last_time_sec = sim_time_sec; - _step++; - if (_step >= getBranch()->getNumKids()) - _step = 0; - ((ssgSelector *)getBranch())->selectStep(_step); + if ( _use_personality ) { + SGPersonalityBranch *key = current_object; + if ( !key->getIntValue( this, INIT ) ) { + double total = 0; + double offset = 1.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 ); + if ( i == 0 ) + offset = v; + total += v; + } + // Sanity check : total duration shouldn't equal zero + if ( total < 0.01 ) { + total = 0.01; + } + offset *= sg_random(); + key->setDoubleValue( sim_time_sec - offset, this, LAST_TIME_SEC ); + key->setDoubleValue( total, this, TOTAL_DURATION_SEC ); + key->setIntValue( 0, this, STEP ); + key->setIntValue( 1, this, INIT ); + } + + _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; + return 1; } @@ -445,8 +557,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 +603,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 +684,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 +705,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; } @@ -927,33 +1053,129 @@ void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp) // Implementation of SGFlashAnimation //////////////////////////////////////////////////////////////////////// SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props) - : SGAnimation( props, new SGFlash ) + : SGAnimation( props, new SGCustomTransform ) { - sgVec3 axis; - axis[0] = props->getFloatValue("axis/x", 0); - axis[1] = props->getFloatValue("axis/y", 0); - axis[2] = props->getFloatValue("axis/z", 1); - ((SGFlash *)_branch)->setAxis( axis ); + _axis[0] = props->getFloatValue("axis/x", 0); + _axis[1] = props->getFloatValue("axis/y", 0); + _axis[2] = props->getFloatValue("axis/z", 1); - sgVec3 center; - center[0] = props->getFloatValue("center/x-m", 0); - center[1] = props->getFloatValue("center/y-m", 0); - center[2] = props->getFloatValue("center/z-m", 0); - ((SGFlash *)_branch)->setCenter( center ); + _center[0] = props->getFloatValue("center/x-m", 0); + _center[1] = props->getFloatValue("center/y-m", 0); + _center[2] = props->getFloatValue("center/z-m", 0); - float offset = props->getFloatValue("offset", 0.0); - float factor = props->getFloatValue("factor", 1.0); - float power = props->getFloatValue("power", 1.0); - bool two_sides = props->getBoolValue("two-sides", false); - ((SGFlash *)_branch)->setParameters( power, factor, offset, two_sides ); + _offset = props->getFloatValue("offset", 0.0); + _factor = props->getFloatValue("factor", 1.0); + _power = props->getFloatValue("power", 1.0); + _two_sides = props->getBoolValue("two-sides", false); - float v_min = props->getFloatValue("min", 0.0); - float v_max = props->getFloatValue("max", 1.0); - ((SGFlash *)_branch)->setClampValues( v_min, v_max ); + _min_v = props->getFloatValue("min", 0.0); + _max_v = props->getFloatValue("max", 1.0); + + ((SGCustomTransform *)_branch)->setTransCallback( &SGFlashAnimation::flashCallback, this ); } SGFlashAnimation::~SGFlashAnimation() { } +void SGFlashAnimation::flashCallback( sgMat4 r, sgFrustum *f, sgMat4 m, void *d ) +{ + ((SGFlashAnimation *)d)->flashCallback( r, f, m ); +} + +void SGFlashAnimation::flashCallback( sgMat4 r, sgFrustum *f, sgMat4 m ) +{ + sgVec3 transformed_axis; + sgXformVec3( transformed_axis, _axis, m ); + sgNormalizeVec3( transformed_axis ); + + 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; + else if ( cos_angle > 0 ) + scale_factor = _factor * (float)pow( cos_angle, _power ) + _offset; + + if ( scale_factor < _min_v ) + scale_factor = _min_v; + if ( scale_factor > _max_v ) + scale_factor = _max_v; + + sgMat4 transform; + sgMakeIdentMat4( transform ); + transform[0][0] = scale_factor; + transform[1][1] = scale_factor; + transform[2][2] = scale_factor; + transform[3][0] = _center[0] * ( 1 - scale_factor ); + transform[3][1] = _center[1] * ( 1 - scale_factor ); + transform[3][2] = _center[2] * ( 1 - scale_factor ); + + sgCopyMat4( r, m ); + sgPreMultMat4( r, transform ); +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of SGDistScaleAnimation +//////////////////////////////////////////////////////////////////////// +SGDistScaleAnimation::SGDistScaleAnimation(SGPropertyNode_ptr props) + : SGAnimation( props, new SGCustomTransform ), + _factor(props->getFloatValue("factor", 1.0)), + _offset(props->getFloatValue("offset", 0.0)), + _min_v(props->getFloatValue("min", 0.0)), + _max_v(props->getFloatValue("max", 1.0)), + _has_min(props->hasValue("min")), + _has_max(props->hasValue("max")), + _table(read_interpolation_table(props)) +{ + _center[0] = props->getFloatValue("center/x-m", 0); + _center[1] = props->getFloatValue("center/y-m", 0); + _center[2] = props->getFloatValue("center/z-m", 0); + + ((SGCustomTransform *)_branch)->setTransCallback( &SGDistScaleAnimation::distScaleCallback, this ); +} + +SGDistScaleAnimation::~SGDistScaleAnimation() +{ +} + +void SGDistScaleAnimation::distScaleCallback( sgMat4 r, sgFrustum *f, sgMat4 m, void *d ) +{ + ((SGDistScaleAnimation *)d)->distScaleCallback( r, f, m ); +} + +void SGDistScaleAnimation::distScaleCallback( sgMat4 r, sgFrustum *f, sgMat4 m ) +{ + sgVec3 view; + sgFullXformPnt3( view, _center, m ); + + float scale_factor = sgLengthVec3( view ); + if (_table == 0) { + scale_factor = _factor * scale_factor + _offset; + if ( _has_min && scale_factor < _min_v ) + scale_factor = _min_v; + if ( _has_max && scale_factor > _max_v ) + scale_factor = _max_v; + } else { + scale_factor = _table->interpolate( scale_factor ); + } + + sgMat4 transform; + sgMakeIdentMat4( transform ); + transform[0][0] = scale_factor; + transform[1][1] = scale_factor; + transform[2][2] = scale_factor; + transform[3][0] = _center[0] * ( 1 - scale_factor ); + transform[3][1] = _center[1] * ( 1 - scale_factor ); + transform[3][2] = _center[2] * ( 1 - scale_factor ); + + sgCopyMat4( r, m ); + sgPreMultMat4( r, transform ); +} + // end of animation.cxx