X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmodel%2Fanimation.cxx;h=8a1c73e2281ef3bb5701cdc727f25969bf626b84;hb=b199f733f7a71218a20c3408af570aa1edf92642;hp=928d90f112b1f14d90f01f0d724eb00e67319e21;hpb=d3db963dceaa1b27bb5541cc385df5dedb3c726c;p=simgear.git diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index 928d90f1..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" //////////////////////////////////////////////////////////////////////// @@ -97,20 +99,22 @@ set_scale (sgMat4 &matrix, double x, double y, double z) static void change_alpha( ssgBase *_branch, float _blend ) { - unsigned int i; + int i; for (i = 0; i < ((ssgBranch *)_branch)->getNumKids(); i++) change_alpha( ((ssgBranch *)_branch)->getKid(i), _blend ); - if ( strcmp("ssgLeaf", _branch->getTypeName()) && - strcmp("ssgVtxTable", _branch->getTypeName()) && - strcmp("ssgVTable", _branch->getTypeName()) ) + if ( !_branch->isAKindOf(ssgTypeLeaf()) + && !_branch->isAKindOf(ssgTypeVtxTable()) + && !_branch->isAKindOf(ssgTypeVTable()) ) 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() { } @@ -214,19 +230,72 @@ SGNullAnimation::~SGNullAnimation () // Implementation of SGRangeAnimation //////////////////////////////////////////////////////////////////////// -SGRangeAnimation::SGRangeAnimation (SGPropertyNode_ptr props) - : SGAnimation(props, new ssgRangeSelector) +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), + _condition(0) { - float ranges[] = { props->getFloatValue("min-m", 0), - props->getFloatValue("max-m", 5000) }; + SGPropertyNode_ptr node = props->getChild("condition"); + if (node != 0) + _condition = sgReadCondition(prop_root, node); + + float ranges[2]; + + 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() * _min_factor; + } else { + _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() * _max_factor; + } else { + _max = props->getFloatValue("max-m", 0); + ranges[1] = _max * _max_factor; + } ((ssgRangeSelector *)_branch)->setRanges(ranges, 2); - } SGRangeAnimation::~SGRangeAnimation () { } +int +SGRangeAnimation::update() +{ + float ranges[2]; + if ( _condition == 0 || _condition->test() ) { + if (_min_prop != 0) { + ranges[0] = _min_prop->getFloatValue() * _min_factor; + } else { + ranges[0] = _min * _min_factor; + } + if (_max_prop != 0) { + ranges[1] = _max_prop->getFloatValue() * _max_factor; + } else { + ranges[1] = _max * _max_factor; + } + } else { + ranges[0] = 0.f; + ranges[1] = 1000000000.f; + } + ((ssgRangeSelector *)_branch)->setRanges(ranges, 2); + return 1; +} + //////////////////////////////////////////////////////////////////////// @@ -263,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; } @@ -285,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; @@ -322,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; } @@ -346,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 () @@ -357,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; } @@ -385,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; @@ -423,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; } @@ -448,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)) { } @@ -464,7 +644,7 @@ SGBlendAnimation::~SGBlendAnimation () delete _table; } -void +int SGBlendAnimation::update() { double _blend; @@ -484,6 +664,7 @@ SGBlendAnimation::update() _prev_value = _blend; change_alpha( _branch, _blend ); } + return 1; } @@ -503,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); @@ -516,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; } @@ -569,7 +758,7 @@ SGScaleAnimation::~SGScaleAnimation () delete _table; } -void +int SGScaleAnimation::update() { if (_table == 0) { @@ -604,6 +793,7 @@ SGScaleAnimation::update() set_scale(_matrix, _x_scale, _y_scale, _z_scale ); ((ssgTransform *)_branch)->setTransform(_matrix); + return 1; } @@ -638,7 +828,7 @@ SGTexRotateAnimation::~SGTexRotateAnimation () delete _table; } -void +int SGTexRotateAnimation::update() { if (_table == 0) { @@ -652,6 +842,7 @@ SGTexRotateAnimation::update() } set_rotation(_matrix, _position_deg, _center, _axis); ((ssgTexTrans *)_branch)->setTransform(_matrix); + return 1; } @@ -685,7 +876,7 @@ SGTexTranslateAnimation::~SGTexTranslateAnimation () delete _table; } -void +int SGTexTranslateAnimation::update() { if (_table == 0) { @@ -699,6 +890,7 @@ SGTexTranslateAnimation::update() } set_translation(_matrix, _position, _axis); ((ssgTexTrans *)_branch)->setTransform(_matrix); + return 1; } @@ -775,7 +967,7 @@ SGTexMultipleAnimation::~SGTexMultipleAnimation () delete _transform; } -void +int SGTexMultipleAnimation::update() { int i; @@ -816,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