From 4c78e887e1d08599c8ecefa983acd8d4b79c742d Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 10 Jul 2003 09:49:29 +0000 Subject: [PATCH] Jim Wilson: This update adds the ability to do multiple texture transforms (Steve B. thinks supporting them at the plib level would be inefficient, which is probably true). Removed units (e.g. "_m") from texture translation property and variable names since the texture translation values are dimensionless. Added the ability to specify a scroll factor for stepped texture animation that needs to scroll smoothly when approaching the step interval (e.g. odometer movement). --- simgear/scene/model/animation.cxx | 177 +++++++++++++++++++++++++++--- simgear/scene/model/animation.hxx | 48 +++++++- simgear/scene/model/model.cxx | 2 + 3 files changed, 205 insertions(+), 22 deletions(-) diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index 1c9c5b02..0ca95a2d 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -438,9 +438,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); @@ -477,15 +477,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); @@ -503,24 +504,164 @@ SGTexTranslateAnimation::update() { if (_table == 0) { if(_step > 0) { + double scrollval = 0.0; + if(_scroll > 0) { + // calculate scroll amount (for odometer like movement) + double remainder = _step - fmod(fabs(_prop->getDoubleValue()), _step); + if (remainder < _scroll) { + scrollval = (_scroll - remainder) / _scroll * _step; + } + } // apply stepping of input value if(_prop->getDoubleValue() > 0) - _position_m = ((floor(_prop->getDoubleValue()/_step) * _step) + _offset_m) * _factor; + _position = ((floor(_prop->getDoubleValue()/_step) * _step) + _offset + scrollval) * _factor; else - _position_m = ((ceil(_prop->getDoubleValue()/_step) * _step) + _offset_m) * _factor; + _position = ((ceil(_prop->getDoubleValue()/_step) * _step) + _offset + scrollval) * _factor; } else { - _position_m = (_prop->getDoubleValue() + _offset_m) * _factor; + _position = (_prop->getDoubleValue() + _offset) * _factor; } - if (_has_min && _position_m < _min_m) - _position_m = _min_m; - if (_has_max && _position_m > _max_m) - _position_m = _max_m; + if (_has_min && _position < _min) + _position = _min; + if (_has_max && _position > _max) + _position = _max; } else { - _position_m = _table->interpolate(_prop->getDoubleValue()); + _position = _table->interpolate(_prop->getDoubleValue()); } - set_translation(_matrix, _position_m, _axis); + set_translation(_matrix, _position, _axis); ((ssgTexTrans *)_branch)->setTransform(_matrix); } +//////////////////////////////////////////////////////////////////////// +// 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)) +{ + 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; +} + +void +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) { + if(_transform[i].step > 0) { + double scrollval = 0.0; + if(_transform[i].scroll > 0) { + // calculate scroll amount (for odometer like movement) + double remainder = _transform[i].step - fmod(fabs(_transform[i].prop->getDoubleValue()), _transform[i].step); + if (remainder < _transform[i].scroll) { + scrollval = (_transform[i].scroll - remainder) / _transform[i].scroll * _transform[i].step; + } + } + // apply stepping of input value + if(_transform[i].prop->getDoubleValue() > 0) + _transform[i].position = ((floor(_transform[i].prop->getDoubleValue()/_transform[i].step) * _transform[i].step) + _transform[i].offset) * _transform[i].factor; + else + _transform[i].position = ((ceil(_transform[i].prop->getDoubleValue()/_transform[i].step) * _transform[i].step) + _transform[i].offset) * _transform[i].factor; + } else { + _transform[i].position = (_transform[i].prop->getDoubleValue() + _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(_transform[i].prop->getDoubleValue()); + } + 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); +} + // end of animation.cxx diff --git a/simgear/scene/model/animation.hxx b/simgear/scene/model/animation.hxx index c80edc15..9259401b 100644 --- a/simgear/scene/model/animation.hxx +++ b/simgear/scene/model/animation.hxx @@ -260,17 +260,57 @@ public: virtual void update(); private: SGPropertyNode_ptr _prop; - double _offset_m; + double _offset; double _factor; double _step; + double _scroll; SGInterpTable * _table; bool _has_min; - double _min_m; + double _min; bool _has_max; - double _max_m; - double _position_m; + double _max; + double _position; sgMat4 _matrix; sgVec3 _axis; }; + + +/** + * Classes for handling multiple types of Texture translations on one object + */ + +class SGTexMultipleAnimation : public SGAnimation +{ +public: + SGTexMultipleAnimation( SGPropertyNode *prop_root, + SGPropertyNode_ptr props ); + virtual ~SGTexMultipleAnimation (); + virtual void update(); +private: + class TexTransform + { + public: + SGPropertyNode_ptr prop; + int subtype; // 0=translation, 1=rotation + double offset; + double factor; + double step; + double scroll; + SGInterpTable * table; + bool has_min; + double min; + bool has_max; + double max; + double position; + sgMat4 matrix; + sgVec3 center; + sgVec3 axis; + }; + SGPropertyNode_ptr _prop; + TexTransform* _transform; + int _num_transforms; +}; + + #endif // _SG_ANIMATION_HXX diff --git a/simgear/scene/model/model.cxx b/simgear/scene/model/model.cxx index 1ece4c5b..528ad116 100644 --- a/simgear/scene/model/model.cxx +++ b/simgear/scene/model/model.cxx @@ -125,6 +125,8 @@ sgMakeAnimation( ssgBranch * model, animation = new SGTexRotateAnimation(prop_root, node); } else if (!strcmp("textranslate", type)) { animation = new SGTexTranslateAnimation(prop_root, node); + } else if (!strcmp("texmultiple", type)) { + animation = new SGTexMultipleAnimation(prop_root, node); } else { animation = new SGNullAnimation(node); SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type); -- 2.39.5