X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmodel%2Fanimation.cxx;h=8a1c73e2281ef3bb5701cdc727f25969bf626b84;hb=b199f733f7a71218a20c3408af570aa1edf92642;hp=f9ebc188e81c690ef0325f7490d4f62eb59063cf;hpb=17e247852231f83d9c5c5d02f789e789ea40763b;p=simgear.git diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index f9ebc188..8a1c73e2 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -5,6 +5,7 @@ #include // for strcmp() +#include #include #include @@ -13,9 +14,11 @@ #include #include #include +#include #include "animation.hxx" - +#include "custtrans.hxx" +#include "personality.hxx" //////////////////////////////////////////////////////////////////////// @@ -78,6 +81,73 @@ set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis) sgMakeTransMat4(matrix, xyz); } +/** + * Set up the transform matrix for a scale operation. + */ +static void +set_scale (sgMat4 &matrix, double x, double y, double z) +{ + sgMakeIdentMat4( matrix ); + matrix[0][0] = x; + matrix[1][1] = y; + matrix[2][2] = z; +} + +/** + * Recursively process all kids to change the alpha values + */ +static void +change_alpha( ssgBase *_branch, float _blend ) +{ + int i; + + for (i = 0; i < ((ssgBranch *)_branch)->getNumKids(); i++) + change_alpha( ((ssgBranch *)_branch)->getKid(i), _blend ); + + 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; + } +} + +/** + * Modify property value by step and scroll settings in texture translations + */ +static double +apply_mods(double property, double step, double scroll) +{ + + double modprop; + if(step > 0) { + double scrollval = 0.0; + if(scroll > 0) { + // calculate scroll amount (for odometer like movement) + double remainder = step - fmod(fabs(property), step); + if (remainder < scroll) { + scrollval = (scroll - remainder) / scroll * step; + } + } + // apply stepping of input value + if(property > 0) + modprop = ((floor(property/step) * step) + scrollval); + else + modprop = ((ceil(property/step) * step) + scrollval); + } else { + modprop = property; + } + return modprop; + +} /** * Read an interpolation table from properties. @@ -106,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 () @@ -122,8 +198,14 @@ SGAnimation::init () { } -void +int SGAnimation::update() +{ + return 1; +} + +void +SGAnimation::restore() { } @@ -148,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; +} + //////////////////////////////////////////////////////////////////////// @@ -197,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; } @@ -219,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; @@ -256,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; } @@ -280,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 () @@ -291,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; } @@ -319,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; @@ -357,20 +600,71 @@ SGRotateAnimation::~SGRotateAnimation () delete _table; } -void +int SGRotateAnimation::update() { + 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); + } + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +// Implementation of SGBlendAnimation +//////////////////////////////////////////////////////////////////////// + +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)), + _has_min(props->hasValue("min")), + _min(props->getDoubleValue("min", 0.0)), + _has_max(props->hasValue("max")), + _max(props->getDoubleValue("max", 1.0)) +{ +} + +SGBlendAnimation::~SGBlendAnimation () +{ + delete _table; +} + +int +SGBlendAnimation::update() +{ + double _blend; + 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; + _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset); + + if (_has_min && (_blend < _min)) + _blend = _min; + if (_has_max && (_blend > _max)) + _blend = _max; } else { - _position_deg = _table->interpolate(_prop->getDoubleValue()); + _blend = _table->interpolate(_prop->getDoubleValue()); } - set_rotation(_matrix, _position_deg, _center, _axis); - ((ssgTransform *)_branch)->setTransform(_matrix); + + if (_blend != _prev_value) { + _prev_value = _blend; + change_alpha( _branch, _blend ); + } + return 1; } @@ -390,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); @@ -403,20 +702,98 @@ SGTranslateAnimation::~SGTranslateAnimation () delete _table; } -void +int SGTranslateAnimation::update() { + 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); + } + return 1; +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of SGScaleAnimation +//////////////////////////////////////////////////////////////////////// + +SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root, + SGPropertyNode_ptr props ) + : SGAnimation(props, new ssgTransform), + _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)), + _x_factor(props->getDoubleValue("x-factor", 1.0)), + _y_factor(props->getDoubleValue("y-factor", 1.0)), + _z_factor(props->getDoubleValue("z-factor", 1.0)), + _x_offset(props->getDoubleValue("x-offset", 1.0)), + _y_offset(props->getDoubleValue("y-offset", 1.0)), + _z_offset(props->getDoubleValue("z-offset", 1.0)), + _table(read_interpolation_table(props)), + _has_min_x(props->hasValue("x-min")), + _has_min_y(props->hasValue("y-min")), + _has_min_z(props->hasValue("z-min")), + _min_x(props->getDoubleValue("x-min")), + _min_y(props->getDoubleValue("y-min")), + _min_z(props->getDoubleValue("z-min")), + _has_max_x(props->hasValue("x-max")), + _has_max_y(props->hasValue("y-max")), + _has_max_z(props->hasValue("z-max")), + _max_x(props->getDoubleValue("x-max")), + _max_y(props->getDoubleValue("y-max")), + _max_z(props->getDoubleValue("z-max")) +{ +} + +SGScaleAnimation::~SGScaleAnimation () +{ + delete _table; +} + +int +SGScaleAnimation::update() +{ + if (_table == 0) { + _x_scale = _prop->getDoubleValue() * _x_factor + _x_offset; + if (_has_min_x && _x_scale < _min_x) + _x_scale = _min_x; + if (_has_max_x && _x_scale > _max_x) + _x_scale = _max_x; + } else { + _x_scale = _table->interpolate(_prop->getDoubleValue()); + } + + if (_table == 0) { + _y_scale = _prop->getDoubleValue() * _y_factor + _y_offset; + if (_has_min_y && _y_scale < _min_y) + _y_scale = _min_y; + if (_has_max_y && _y_scale > _max_y) + _y_scale = _max_y; + } else { + _y_scale = _table->interpolate(_prop->getDoubleValue()); + } + 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; + _z_scale = _prop->getDoubleValue() * _z_factor + _z_offset; + if (_has_min_z && _z_scale < _min_z) + _z_scale = _min_z; + if (_has_max_z && _z_scale > _max_z) + _z_scale = _max_z; } else { - _position_m = _table->interpolate(_prop->getDoubleValue()); + _z_scale = _table->interpolate(_prop->getDoubleValue()); } - set_translation(_matrix, _position_m, _axis); + + set_scale(_matrix, _x_scale, _y_scale, _z_scale ); ((ssgTransform *)_branch)->setTransform(_matrix); + return 1; } @@ -437,9 +814,9 @@ SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root, _max_deg(props->getDoubleValue("max-deg")), _position_deg(props->getDoubleValue("starting-position-deg", 0)) { - _center[0] = props->getFloatValue("center/x-m", 0); - _center[1] = props->getFloatValue("center/y-m", 0); - _center[2] = props->getFloatValue("center/z-m", 0); + _center[0] = props->getFloatValue("center/x", 0); + _center[1] = props->getFloatValue("center/y", 0); + _center[2] = props->getFloatValue("center/z", 0); _axis[0] = props->getFloatValue("axis/x", 0); _axis[1] = props->getFloatValue("axis/y", 0); _axis[2] = props->getFloatValue("axis/z", 0); @@ -451,7 +828,7 @@ SGTexRotateAnimation::~SGTexRotateAnimation () delete _table; } -void +int SGTexRotateAnimation::update() { if (_table == 0) { @@ -465,6 +842,7 @@ SGTexRotateAnimation::update() } set_rotation(_matrix, _position_deg, _center, _axis); ((ssgTexTrans *)_branch)->setTransform(_matrix); + return 1; } @@ -476,14 +854,16 @@ SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root, SGPropertyNode_ptr props ) : SGAnimation(props, new ssgTexTrans), _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)), - _offset_m(props->getDoubleValue("offset-m", 0.0)), + _offset(props->getDoubleValue("offset", 0.0)), _factor(props->getDoubleValue("factor", 1.0)), + _step(props->getDoubleValue("step",0.0)), + _scroll(props->getDoubleValue("scroll",0.0)), _table(read_interpolation_table(props)), - _has_min(props->hasValue("min-m")), - _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)) + _has_min(props->hasValue("min")), + _min(props->getDoubleValue("min")), + _has_max(props->hasValue("max")), + _max(props->getDoubleValue("max")), + _position(props->getDoubleValue("starting-position", 0)) { _axis[0] = props->getFloatValue("axis/x", 0); _axis[1] = props->getFloatValue("axis/y", 0); @@ -496,21 +876,306 @@ SGTexTranslateAnimation::~SGTexTranslateAnimation () delete _table; } -void +int SGTexTranslateAnimation::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; + _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor; + if (_has_min && _position < _min) + _position = _min; + if (_has_max && _position > _max) + _position = _max; } else { - _position_m = _table->interpolate(_prop->getDoubleValue()); + _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll)); } - set_translation(_matrix, _position_m, _axis); + set_translation(_matrix, _position, _axis); ((ssgTexTrans *)_branch)->setTransform(_matrix); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +// Implementation of SGTexMultipleAnimation +//////////////////////////////////////////////////////////////////////// + +SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root, + SGPropertyNode_ptr props ) + : SGAnimation(props, new ssgTexTrans), + _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)) +{ + unsigned int i; + // Load animations + vector transform_nodes = props->getChildren("transform"); + _transform = new TexTransform [transform_nodes.size()]; + _num_transforms = 0; + for (i = 0; i < transform_nodes.size(); i++) { + SGPropertyNode_ptr transform_props = transform_nodes[i]; + + if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) { + + // transform is a translation + _transform[i].subtype = 0; + + _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true); + + _transform[i].offset = transform_props->getDoubleValue("offset", 0.0); + _transform[i].factor = transform_props->getDoubleValue("factor", 1.0); + _transform[i].step = transform_props->getDoubleValue("step",0.0); + _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0); + _transform[i].table = read_interpolation_table(transform_props); + _transform[i].has_min = transform_props->hasValue("min"); + _transform[i].min = transform_props->getDoubleValue("min"); + _transform[i].has_max = transform_props->hasValue("max"); + _transform[i].max = transform_props->getDoubleValue("max"); + _transform[i].position = transform_props->getDoubleValue("starting-position", 0); + + _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0); + _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0); + _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0); + sgNormalizeVec3(_transform[i].axis); + _num_transforms++; + } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) { + + // transform is a rotation + _transform[i].subtype = 1; + + _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true); + _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0); + _transform[i].factor = transform_props->getDoubleValue("factor", 1.0); + _transform[i].table = read_interpolation_table(transform_props); + _transform[i].has_min = transform_props->hasValue("min-deg"); + _transform[i].min = transform_props->getDoubleValue("min-deg"); + _transform[i].has_max = transform_props->hasValue("max-deg"); + _transform[i].max = transform_props->getDoubleValue("max-deg"); + _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0); + + _transform[i].center[0] = transform_props->getFloatValue("center/x", 0); + _transform[i].center[1] = transform_props->getFloatValue("center/y", 0); + _transform[i].center[2] = transform_props->getFloatValue("center/z", 0); + _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0); + _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0); + _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0); + sgNormalizeVec3(_transform[i].axis); + _num_transforms++; + } + } +} + +SGTexMultipleAnimation::~SGTexMultipleAnimation () +{ + // delete _table; + delete _transform; } +int +SGTexMultipleAnimation::update() +{ + int i; + sgMat4 tmatrix; + sgMakeIdentMat4(tmatrix); + for (i = 0; i < _num_transforms; i++) { + + if(_transform[i].subtype == 0) { + + // subtype 0 is translation + if (_transform[i].table == 0) { + _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor; + if (_transform[i].has_min && _transform[i].position < _transform[i].min) + _transform[i].position = _transform[i].min; + if (_transform[i].has_max && _transform[i].position > _transform[i].max) + _transform[i].position = _transform[i].max; + } else { + _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll)); + } + set_translation(_transform[i].matrix, _transform[i].position, _transform[i].axis); + sgPreMultMat4(tmatrix, _transform[i].matrix); + + } else if (_transform[i].subtype == 1) { + + // subtype 1 is rotation + + if (_transform[i].table == 0) { + _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset; + if (_transform[i].has_min && _transform[i].position < _transform[i].min) + _transform[i].position = _transform[i].min; + if (_transform[i].has_max && _transform[i].position > _transform[i].max) + _transform[i].position = _transform[i].max; + } else { + _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue()); + } + set_rotation(_transform[i].matrix, _transform[i].position, _transform[i].center, _transform[i].axis); + sgPreMultMat4(tmatrix, _transform[i].matrix); + } + } + ((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