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); }