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 :

<animation>
 <type>flash</type>
 <object-name>HaloObject</object-name>
 <center>
  <x-m>0</x-m>
  <y-m>0</y-m>
  <z-m>0</z-m>
 </center>
 <axis>
  <x>0</x>
  <y>0</y>
  <z>1</z>
 </axis>
 <power>1</power>
 <factor>1</factor>
 <offset>0</offset>
 <min>0</min>
 <max>1</max>
 <two-sides>false</two-sides>
</animation>
This commit is contained in:
ehofman
2004-05-07 16:42:59 +00:00
parent e09164e5b3
commit ffada9257d
6 changed files with 287 additions and 28 deletions

View File

@@ -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 \

View File

@@ -16,7 +16,7 @@
#include <simgear/props/props.hxx>
#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

View File

@@ -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

147
simgear/scene/model/flash.cxx Executable file
View File

@@ -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"; }

29
simgear/scene/model/flash.hxx Executable file
View File

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

View File

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