From ffada9257d18a888ea846338882ac6b9ec014e28 Mon Sep 17 00:00:00 2001 From: ehofman Date: Fri, 7 May 2004 16:42:59 +0000 Subject: [PATCH] Frederic Bouvier: this patch introduce a new kind of animation and ssg branch. I called them flash animation, because they help me to enhance the look of the rotating beacon and possible future lighthouse. It computes the cosine of the angle between an arbitrary axis, transformed by the current modelview matrix, and the view direction. No trig involved, just a dot/scalar product. The computed value can be modified by three parameters, power, factor and offset, according to the formulae : value = factor * pow( cosine, power ) + offset. It is clamped between a minimum and a maximum. This value is then used as the scale factor of a matrix transformation applied to the children of the SGFlash branch. The xml syntax, with default values, is : flash HaloObject
0 0 0
0 0 1 1 1 0 0 1 false
--- simgear/scene/model/Makefile.am | 2 + simgear/scene/model/animation.cxx | 78 +++++++++++++--- simgear/scene/model/animation.hxx | 43 ++++++--- simgear/scene/model/flash.cxx | 147 ++++++++++++++++++++++++++++++ simgear/scene/model/flash.hxx | 29 ++++++ simgear/scene/model/model.cxx | 16 +++- 6 files changed, 287 insertions(+), 28 deletions(-) create mode 100755 simgear/scene/model/flash.cxx create mode 100755 simgear/scene/model/flash.hxx diff --git a/simgear/scene/model/Makefile.am b/simgear/scene/model/Makefile.am index 3734733b..4ab768d6 100644 --- a/simgear/scene/model/Makefile.am +++ b/simgear/scene/model/Makefile.am @@ -6,6 +6,7 @@ noinst_HEADERS = include_HEADERS = \ animation.hxx \ + flash.hxx \ location.hxx \ model.hxx \ modellib.hxx \ @@ -13,6 +14,7 @@ include_HEADERS = \ libsgmodel_a_SOURCES = \ animation.cxx \ + flash.cxx \ location.cxx \ model.cxx \ modellib.cxx \ diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index ac305760..6ced0858 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -16,7 +16,7 @@ #include #include "animation.hxx" - +#include "flash.hxx" //////////////////////////////////////////////////////////////////////// @@ -190,8 +190,14 @@ SGAnimation::init () { } -void +int SGAnimation::update() +{ + return 1; +} + +void +SGAnimation::restore() { } @@ -255,7 +261,7 @@ SGRangeAnimation::~SGRangeAnimation () { } -void +int SGRangeAnimation::update() { float ranges[2]; @@ -275,6 +281,7 @@ SGRangeAnimation::update() if (upd) { ((ssgRangeSelector *)_branch)->setRanges(ranges, 2); } + return 1; } @@ -313,13 +320,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; } @@ -372,7 +380,7 @@ SGSpinAnimation::~SGSpinAnimation () { } -void +int SGSpinAnimation::update() { double dt = sim_time_sec - _last_time_sec; @@ -386,6 +394,7 @@ SGSpinAnimation::update() _position_deg -= 360.0; set_rotation(_matrix, _position_deg, _center, _axis); ((ssgTransform *)_branch)->setTransform(_matrix); + return 1; } @@ -406,7 +415,7 @@ SGTimedAnimation::~SGTimedAnimation () { } -void +int SGTimedAnimation::update() { if ((sim_time_sec - _last_time_sec) >= _duration_sec) { @@ -416,6 +425,7 @@ SGTimedAnimation::update() _step = 0; ((ssgSelector *)getBranch())->selectStep(_step); } + return 1; } @@ -473,7 +483,7 @@ SGRotateAnimation::~SGRotateAnimation () delete _table; } -void +int SGRotateAnimation::update() { if (_table == 0) { @@ -487,6 +497,7 @@ SGRotateAnimation::update() } set_rotation(_matrix, _position_deg, _center, _axis); ((ssgTransform *)_branch)->setTransform(_matrix); + return 1; } @@ -514,7 +525,7 @@ SGBlendAnimation::~SGBlendAnimation () delete _table; } -void +int SGBlendAnimation::update() { double _blend; @@ -534,6 +545,7 @@ SGBlendAnimation::update() _prev_value = _blend; change_alpha( _branch, _blend ); } + return 1; } @@ -566,7 +578,7 @@ SGTranslateAnimation::~SGTranslateAnimation () delete _table; } -void +int SGTranslateAnimation::update() { if (_table == 0) { @@ -580,6 +592,7 @@ SGTranslateAnimation::update() } set_translation(_matrix, _position_m, _axis); ((ssgTransform *)_branch)->setTransform(_matrix); + return 1; } @@ -619,7 +632,7 @@ SGScaleAnimation::~SGScaleAnimation () delete _table; } -void +int SGScaleAnimation::update() { if (_table == 0) { @@ -654,6 +667,7 @@ SGScaleAnimation::update() set_scale(_matrix, _x_scale, _y_scale, _z_scale ); ((ssgTransform *)_branch)->setTransform(_matrix); + return 1; } @@ -688,7 +702,7 @@ SGTexRotateAnimation::~SGTexRotateAnimation () delete _table; } -void +int SGTexRotateAnimation::update() { if (_table == 0) { @@ -702,6 +716,7 @@ SGTexRotateAnimation::update() } set_rotation(_matrix, _position_deg, _center, _axis); ((ssgTexTrans *)_branch)->setTransform(_matrix); + return 1; } @@ -735,7 +750,7 @@ SGTexTranslateAnimation::~SGTexTranslateAnimation () delete _table; } -void +int SGTexTranslateAnimation::update() { if (_table == 0) { @@ -749,6 +764,7 @@ SGTexTranslateAnimation::update() } set_translation(_matrix, _position, _axis); ((ssgTexTrans *)_branch)->setTransform(_matrix); + return 1; } @@ -825,7 +841,7 @@ SGTexMultipleAnimation::~SGTexMultipleAnimation () delete _transform; } -void +int SGTexMultipleAnimation::update() { int i; @@ -866,6 +882,7 @@ SGTexMultipleAnimation::update() } } ((ssgTexTrans *)_branch)->setTransform(tmatrix); + return 1; } @@ -904,4 +921,39 @@ void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp) } } + + +//////////////////////////////////////////////////////////////////////// +// Implementation of SGFlashAnimation +//////////////////////////////////////////////////////////////////////// +SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props) + : SGAnimation( props, new SGFlash ) +{ + 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 ); + + 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 ); + + 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 ); + + float v_min = props->getFloatValue("min", 0.0); + float v_max = props->getFloatValue("max", 1.0); + ((SGFlash *)_branch)->setClampValues( v_min, v_max ); +} + +SGFlashAnimation::~SGFlashAnimation() +{ +} + // end of animation.cxx diff --git a/simgear/scene/model/animation.hxx b/simgear/scene/model/animation.hxx index c0c7fc39..76259c98 100644 --- a/simgear/scene/model/animation.hxx +++ b/simgear/scene/model/animation.hxx @@ -65,7 +65,12 @@ public: /** * Update the animation. */ - virtual void update(); + virtual int update(); + + /** + * Restore the state after the animation. + */ + virtual void restore(); /** * Set the value of sim_time_sec. This needs to be called every @@ -102,7 +107,7 @@ public: SGRangeAnimation (SGPropertyNode *prop_root, SGPropertyNode_ptr props); virtual ~SGRangeAnimation (); - virtual void update(); + virtual int update(); private: SGPropertyNode_ptr _min_prop; SGPropertyNode_ptr _max_prop; @@ -133,7 +138,7 @@ public: SGSelectAnimation( SGPropertyNode *prop_root, SGPropertyNode_ptr props ); virtual ~SGSelectAnimation (); - virtual void update(); + virtual int update(); private: SGCondition * _condition; }; @@ -151,7 +156,7 @@ public: SGPropertyNode_ptr props, double sim_time_sec ); virtual ~SGSpinAnimation (); - virtual void update(); + virtual int update(); private: SGPropertyNode_ptr _prop; double _factor; @@ -171,7 +176,7 @@ class SGTimedAnimation : public SGAnimation public: SGTimedAnimation (SGPropertyNode_ptr props); virtual ~SGTimedAnimation (); - virtual void update(); + virtual int update(); private: double _duration_sec; double _last_time_sec; @@ -189,7 +194,7 @@ class SGRotateAnimation : public SGAnimation public: SGRotateAnimation( SGPropertyNode *prop_root, SGPropertyNode_ptr props ); virtual ~SGRotateAnimation (); - virtual void update(); + virtual int update(); private: SGPropertyNode_ptr _prop; double _offset_deg; @@ -215,7 +220,7 @@ public: SGTranslateAnimation( SGPropertyNode *prop_root, SGPropertyNode_ptr props ); virtual ~SGTranslateAnimation (); - virtual void update(); + virtual int update(); private: SGPropertyNode_ptr _prop; double _offset_m; @@ -239,7 +244,7 @@ public: SGBlendAnimation( SGPropertyNode *prop_root, SGPropertyNode_ptr props ); virtual ~SGBlendAnimation (); - virtual void update(); + virtual int update(); private: SGPropertyNode_ptr _prop; SGInterpTable * _table; @@ -261,7 +266,7 @@ public: SGScaleAnimation( SGPropertyNode *prop_root, SGPropertyNode_ptr props ); virtual ~SGScaleAnimation (); - virtual void update(); + virtual int update(); private: SGPropertyNode_ptr _prop; double _x_factor; @@ -299,7 +304,7 @@ class SGTexRotateAnimation : public SGAnimation public: SGTexRotateAnimation( SGPropertyNode *prop_root, SGPropertyNode_ptr props ); virtual ~SGTexRotateAnimation (); - virtual void update(); + virtual int update(); private: SGPropertyNode_ptr _prop; double _offset_deg; @@ -325,7 +330,7 @@ public: SGTexTranslateAnimation( SGPropertyNode *prop_root, SGPropertyNode_ptr props ); virtual ~SGTexTranslateAnimation (); - virtual void update(); + virtual int update(); private: SGPropertyNode_ptr _prop; double _offset; @@ -354,7 +359,7 @@ public: SGTexMultipleAnimation( SGPropertyNode *prop_root, SGPropertyNode_ptr props ); virtual ~SGTexMultipleAnimation (); - virtual void update(); + virtual int update(); private: class TexTransform { @@ -382,7 +387,7 @@ private: /** - * An animation to enable the alpha test + * An "animation" to enable the alpha test */ class SGAlphaTestAnimation : public SGAnimation { @@ -396,4 +401,16 @@ private: }; +/** + * An "animation" that compute a scale according to + * the angle between an axis and the view direction + */ +class SGFlashAnimation : public SGAnimation +{ +public: + SGFlashAnimation(SGPropertyNode_ptr props); + virtual ~SGFlashAnimation (); +}; + + #endif // _SG_ANIMATION_HXX diff --git a/simgear/scene/model/flash.cxx b/simgear/scene/model/flash.cxx new file mode 100755 index 00000000..9e75421d --- /dev/null +++ b/simgear/scene/model/flash.cxx @@ -0,0 +1,147 @@ +/* + $Id$ +*/ + +#include "plib/ssg.h" +#include "flash.hxx" +void _ssgPushMatrix ( sgMat4 m ); +void _ssgPopMatrix (); +void _ssgReadInt ( FILE *fd, int *var ); +void _ssgWriteInt ( FILE *fd, const int var ); +extern sgMat4 _ssgOpenGLAxisSwapMatrix; + +void SGFlash::copy_from( SGFlash *src, int clone_flags ) +{ + ssgBranch::copy_from( src, clone_flags ); + sgCopyVec3( _center, src->_center ); + sgCopyVec3( _axis, src->_axis ); + _power = src->_power; + _factor = src->_factor; + _offset = src->_offset; + _min_v = src->_min_v; + _max_v = src->_max_v; + _two_sides = src->_two_sides; +} + +ssgBase *SGFlash::clone( int clone_flags ) +{ + SGFlash *b = new SGFlash; + b -> copy_from( this, clone_flags ); + return b; +} + + +SGFlash::SGFlash() +{ + type = ssgTypeBranch(); +} + +SGFlash::~SGFlash() +{ +} + +void SGFlash::setAxis( sgVec3 axis ) +{ + sgCopyVec3( _axis, axis ); + sgNormalizeVec3( _axis ); +} + +void SGFlash::setCenter( sgVec3 center ) +{ + sgCopyVec3( _center, center ); +} + +void SGFlash::setParameters( float power, float factor, float offset, bool two_sides ) +{ + _power = power; + _factor = factor; + _offset = offset; + _two_sides = two_sides; +} + +void SGFlash::setClampValues( float min_v, float max_v ) +{ + _min_v = min_v; + _max_v = max_v; +} + +void SGFlash::cull( sgFrustum *f, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests( &test_needed, SSGTRAV_CULL ) ) + return; + + sgVec3 transformed_axis; + sgXformVec3( transformed_axis, _axis, m ); + sgNormalizeVec3( transformed_axis ); + + float cos_angle = transformed_axis[ 2 ]; // z component, through the screen + 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 tmp, 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( tmp, m ); + sgPreMultMat4( tmp, transform ); + + _ssgPushMatrix( tmp ); + glPushMatrix(); + glLoadMatrixf( (float *) tmp ); + + for ( ssgEntity *e = getKid ( 0 ); e != NULL; e = getNextKid() ) + e -> cull( f, tmp, test_needed ); + + glPopMatrix(); + _ssgPopMatrix(); + + postTravTests( SSGTRAV_CULL ); +} + + +void SGFlash::hot( sgVec3 s, sgMat4 m, int test_needed ) +{ + ssgBranch::hot( s, m, test_needed ); +} + +void SGFlash::los( sgVec3 s, sgMat4 m, int test_needed ) +{ + ssgBranch::los( s, m, test_needed ); +} + + +void SGFlash::isect( sgSphere *s, sgMat4 m, int test_needed ) +{ + ssgBranch::isect( s, m, test_needed ); +} + + + +int SGFlash::load( FILE *fd ) +{ +// _ssgReadInt( fd, & point_rotate ); + + return ssgBranch::load(fd); +} + +int SGFlash::save( FILE *fd ) +{ +// _ssgWriteInt( fd, point_rotate ); + + return ssgBranch::save(fd); +} + +const char *SGFlash::getTypeName (void) { return "SGFlash"; } diff --git a/simgear/scene/model/flash.hxx b/simgear/scene/model/flash.hxx new file mode 100755 index 00000000..f94fef03 --- /dev/null +++ b/simgear/scene/model/flash.hxx @@ -0,0 +1,29 @@ + +class SGFlash : public ssgBranch +{ +public: + virtual ssgBase *clone( int clone_flags = 0 ); + SGFlash(); + virtual ~SGFlash(void); + + void setAxis( sgVec3 axis ); + void setCenter( sgVec3 center ); + void setParameters( float power, float factor, float offset, bool two_sides ); + void setClampValues( float min_v, float max_v ); + + virtual const char *getTypeName(void); + virtual int load( FILE *fd ); + virtual int save( FILE *fd ); + virtual void cull( sgFrustum *f, sgMat4 m, int test_needed ); + virtual void isect( sgSphere *s, sgMat4 m, int test_needed ); + virtual void hot( sgVec3 s, sgMat4 m, int test_needed ); + virtual void los( sgVec3 s, sgMat4 m, int test_needed ); + +protected: + virtual void copy_from( SGFlash *src, int clone_flags ); + +private: + sgVec3 _axis, _center; + float _power, _factor, _offset, _min_v, _max_v; + bool _two_sides; +}; diff --git a/simgear/scene/model/model.cxx b/simgear/scene/model/model.cxx index be5d9f48..3e6d508b 100644 --- a/simgear/scene/model/model.cxx +++ b/simgear/scene/model/model.cxx @@ -52,8 +52,17 @@ model_filter_callback (ssgEntity * entity, int mask) static int animation_callback (ssgEntity * entity, int mask) { - ((SGAnimation *)entity->getUserData())->update(); - return true; + return ((SGAnimation *)entity->getUserData())->update(); +} + +/** + * Callback to restore the state after an animation. + */ +static int +restore_callback (ssgEntity * entity, int mask) +{ + ((SGAnimation *)entity->getUserData())->restore(); + return 1; } @@ -145,6 +154,8 @@ sgMakeAnimation( ssgBranch * model, animation = new SGBlendAnimation(prop_root, node); } else if (!strcmp("alpha-test", type)) { animation = new SGAlphaTestAnimation(node); + } else if (!strcmp("flash", type)) { + animation = new SGFlashAnimation(node); } else { animation = new SGNullAnimation(node); SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type); @@ -188,6 +199,7 @@ sgMakeAnimation( ssgBranch * model, animation->init(); branch->setUserData(animation); branch->setTravCallback(SSG_CALLBACK_PRETRAV, animation_callback); + branch->setTravCallback(SSG_CALLBACK_POSTTRAV, restore_callback); } -- 2.39.5