X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmodel%2Fanimation.cxx;h=8a1c73e2281ef3bb5701cdc727f25969bf626b84;hb=b199f733f7a71218a20c3408af570aa1edf92642;hp=8d471a4ea08792e1b6697394831025bc635d43d9;hpb=c4d5d85c3eea3518bd208b2f8859c5ddd89ce58e;p=simgear.git diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index 8d471a4e..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 "custtrans.hxx" +#include "personality.hxx" //////////////////////////////////////////////////////////////////////// @@ -108,9 +110,11 @@ change_alpha( ssgBase *_branch, float _blend ) return; int num_colors = ((ssgLeaf *)_branch)->getNumColours(); +// unsigned int select_ = (_blend == 1.0) ? false : true; for (i = 0; i < num_colors; i++) { +// ((ssgSelector *)_branch)->select( select_ ); float *color = ((ssgLeaf *)_branch)->getColour(i); color[3] = _blend; } @@ -172,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 () @@ -188,8 +198,14 @@ SGAnimation::init () { } -void +int SGAnimation::update() +{ + return 1; +} + +void +SGAnimation::restore() { } @@ -217,23 +233,38 @@ SGNullAnimation::~SGNullAnimation () SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root, SGPropertyNode_ptr props) : SGAnimation(props, new ssgRangeSelector), - _min(0.0), _max(0.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-property" ); + node = props->getChild( "min-factor" ); + if (node != 0) { + _min_factor = props->getFloatValue("min-factor", 1.0); + } + node = props->getChild( "max-factor" ); + if (node != 0) { + _max_factor = props->getFloatValue("max-factor", 1.0); + } + node = props->getChild( "min-property" ); if (node != 0) { _min_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true); - ranges[0] = _min_prop->getFloatValue(); + ranges[0] = _min_prop->getFloatValue() * _min_factor; } else { - ranges[0] = _min = props->getFloatValue("min-m", 0); + _min = props->getFloatValue("min-m", 0); + ranges[0] = _min * _min_factor; } node = props->getChild( "max-property" ); if (node != 0) { _max_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true); - ranges[1] = _max_prop->getFloatValue(); + ranges[1] = _max_prop->getFloatValue() * _max_factor; } else { - ranges[1] = _max = props->getFloatValue("max-m", 0); + _max = props->getFloatValue("max-m", 0); + ranges[1] = _max * _max_factor; } ((ssgRangeSelector *)_branch)->setRanges(ranges, 2); } @@ -242,25 +273,27 @@ SGRangeAnimation::~SGRangeAnimation () { } -void +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(); - upd = true; + ranges[0] = _min_prop->getFloatValue() * _min_factor; } else { - ranges[0] = _min; + ranges[0] = _min * _min_factor; } if (_max_prop != 0) { - ranges[1] = _max_prop->getFloatValue(); - upd = true; + ranges[1] = _max_prop->getFloatValue() * _max_factor; } else { - ranges[1] = _max; + ranges[1] = _max * _max_factor; } - if (upd) - ((ssgRangeSelector *)_branch)->setRanges(ranges, 2); + } else { + ranges[0] = 0.f; + ranges[1] = 1000000000.f; + } + ((ssgRangeSelector *)_branch)->setRanges(ranges, 2); + return 1; } @@ -299,13 +332,14 @@ SGSelectAnimation::~SGSelectAnimation () delete _condition; } -void +int SGSelectAnimation::update() { if (_condition != 0 && _condition->test()) ((ssgSelector *)_branch)->select(0xffff); else ((ssgSelector *)_branch)->select(0x0000); + return 1; } @@ -321,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; @@ -358,20 +397,23 @@ SGSpinAnimation::~SGSpinAnimation () { } -void +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; } @@ -382,10 +424,28 @@ 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 () @@ -393,15 +453,91 @@ 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; } @@ -421,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; @@ -459,20 +600,23 @@ SGRotateAnimation::~SGRotateAnimation () delete _table; } -void +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; } @@ -484,14 +628,14 @@ SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root, SGPropertyNode_ptr props ) : SGAnimation(props, new ssgTransform), _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)), + _table(read_interpolation_table(props)), + _prev_value(1.0), _offset(props->getDoubleValue("offset", 0.0)), _factor(props->getDoubleValue("factor", 1.0)), - _table(read_interpolation_table(props)), _has_min(props->hasValue("min")), _min(props->getDoubleValue("min", 0.0)), _has_max(props->hasValue("max")), - _max(props->getDoubleValue("max", 1.0)), - _prev_value(1.0) + _max(props->getDoubleValue("max", 1.0)) { } @@ -500,7 +644,7 @@ SGBlendAnimation::~SGBlendAnimation () delete _table; } -void +int SGBlendAnimation::update() { double _blend; @@ -520,6 +664,7 @@ SGBlendAnimation::update() _prev_value = _blend; change_alpha( _branch, _blend ); } + return 1; } @@ -539,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); @@ -552,20 +702,23 @@ SGTranslateAnimation::~SGTranslateAnimation () delete _table; } -void +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; } @@ -605,7 +758,7 @@ SGScaleAnimation::~SGScaleAnimation () delete _table; } -void +int SGScaleAnimation::update() { if (_table == 0) { @@ -640,6 +793,7 @@ SGScaleAnimation::update() set_scale(_matrix, _x_scale, _y_scale, _z_scale ); ((ssgTransform *)_branch)->setTransform(_matrix); + return 1; } @@ -674,7 +828,7 @@ SGTexRotateAnimation::~SGTexRotateAnimation () delete _table; } -void +int SGTexRotateAnimation::update() { if (_table == 0) { @@ -688,6 +842,7 @@ SGTexRotateAnimation::update() } set_rotation(_matrix, _position_deg, _center, _axis); ((ssgTexTrans *)_branch)->setTransform(_matrix); + return 1; } @@ -721,7 +876,7 @@ SGTexTranslateAnimation::~SGTexTranslateAnimation () delete _table; } -void +int SGTexTranslateAnimation::update() { if (_table == 0) { @@ -735,6 +890,7 @@ SGTexTranslateAnimation::update() } set_translation(_matrix, _position, _axis); ((ssgTexTrans *)_branch)->setTransform(_matrix); + return 1; } @@ -811,7 +967,7 @@ SGTexMultipleAnimation::~SGTexMultipleAnimation () delete _transform; } -void +int SGTexMultipleAnimation::update() { int i; @@ -852,6 +1008,174 @@ SGTexMultipleAnimation::update() } } ((ssgTexTrans *)_branch)->setTransform(tmatrix); + return 1; +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of SGAlphaTestAnimation +//////////////////////////////////////////////////////////////////////// + +SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props) + : SGAnimation(props, new ssgBranch) +{ + _alpha_clamp = props->getFloatValue("alpha-factor", 0.0); +} + +SGAlphaTestAnimation::~SGAlphaTestAnimation () +{ +} + +void SGAlphaTestAnimation::init() +{ + setAlphaClampToBranch(_branch,_alpha_clamp); +} + +void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp) +{ + int nb = b->getNumKids(); + for (int i = 0; igetKid(i); + if (e->isAKindOf(ssgTypeLeaf())) { + ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState(); + s->enable( GL_ALPHA_TEST ); + s->setAlphaClamp( clamp ); + } else if (e->isAKindOf(ssgTypeBranch())) { + setAlphaClampToBranch( (ssgBranch*)e, clamp ); + } + } +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of SGFlashAnimation +//////////////////////////////////////////////////////////////////////// +SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props) + : SGAnimation( props, new SGCustomTransform ) +{ + _axis[0] = props->getFloatValue("axis/x", 0); + _axis[1] = props->getFloatValue("axis/y", 0); + _axis[2] = props->getFloatValue("axis/z", 1); + + _center[0] = props->getFloatValue("center/x-m", 0); + _center[1] = props->getFloatValue("center/y-m", 0); + _center[2] = props->getFloatValue("center/z-m", 0); + + _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); + + _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