From bda112297f2d81bd752b758bbb42485ccbf6a89e Mon Sep 17 00:00:00 2001 From: curt Date: Tue, 11 May 2004 22:21:24 +0000 Subject: [PATCH] Frederic Bouvier: I was not very happy with the size of the halo, so I created a new animation to control it. Now we can control the scale value with the distance from the viewer to the object. The towers are now beginning to look good. They might need some tuning though. If you want to play, locate in radio-*.xml this code : dist-scale RedLight.2 00.1 5000.3 160003 You get the idea ? ind is the distance, dep is the resulting scale value. The medium tower appears brighter than the tall one, because the lights are closer to each other. Maybe they need a smaller scale factor at distance. Feel free to modify these values if you find a better setup. About the code : I renamed flash to custtrans because the ssg branch is now less specialized. It needs a callback to compute the so called 'custom transformation'. It can be used for the SGFlashAnimation and the new SGDistScaleAnimation. So please cvs remove flash.[ch]xx and add custtrans.[ch]xx. I also undo some of the code I send you yesterday that was totally useless. It is replaced by something simpler and that works. There is also a patch to matmodel.cxx. This is not related and was something I forgot. Its purpose is to set the alpha test on material billboard models that are likely to be trees to lessen a transparency weird effect with clouds. --- simgear/scene/material/matmodel.cxx | 24 ++++ simgear/scene/model/Makefile.am | 4 +- simgear/scene/model/animation.cxx | 166 +++++++++++++++++++++------- simgear/scene/model/animation.hxx | 29 +++++ simgear/scene/model/custtrans.cxx | 61 ++++++++++ simgear/scene/model/custtrans.hxx | 32 ++++++ simgear/scene/model/flash.cxx | 151 ------------------------- simgear/scene/model/flash.hxx | 37 ------- simgear/scene/model/model.cxx | 2 + 9 files changed, 276 insertions(+), 230 deletions(-) create mode 100755 simgear/scene/model/custtrans.cxx create mode 100755 simgear/scene/model/custtrans.hxx delete mode 100755 simgear/scene/model/flash.cxx delete mode 100755 simgear/scene/model/flash.hxx diff --git a/simgear/scene/material/matmodel.cxx b/simgear/scene/material/matmodel.cxx index db47a66b..abe20af4 100644 --- a/simgear/scene/material/matmodel.cxx +++ b/simgear/scene/material/matmodel.cxx @@ -126,6 +126,22 @@ SGMatModel::get_model_count( SGModelLib *modellib, return _models.size(); } +static void +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 ); + } + } +} + inline void SGMatModel::load_models ( SGModelLib *modellib, const string &fg_root, @@ -147,6 +163,14 @@ SGMatModel::load_models ( SGModelLib *modellib, lod->ref(); lod->setRanges(ranges, 2); if (_heading_type == HEADING_BILLBOARD) { + // if the model is a billboard, it is likely : + // 1. a branch with only leaves, + // 2. a tree or a non rectangular shape faked by transparency + // We add alpha clamp then + if ( entity->isAKindOf(ssgTypeBranch()) ) { + ssgBranch *b = (ssgBranch *)entity; + setAlphaClampToBranch( b, 0.01f ); + } ssgCutout * cutout = new ssgCutout(false); cutout->addKid(entity); lod->addKid(cutout); diff --git a/simgear/scene/model/Makefile.am b/simgear/scene/model/Makefile.am index e9b91a7d..d376bdb2 100644 --- a/simgear/scene/model/Makefile.am +++ b/simgear/scene/model/Makefile.am @@ -6,7 +6,7 @@ noinst_HEADERS = include_HEADERS = \ animation.hxx \ - flash.hxx \ + custtrans.hxx \ location.hxx \ model.hxx \ modellib.hxx \ @@ -15,7 +15,7 @@ include_HEADERS = \ libsgmodel_a_SOURCES = \ animation.cxx \ - flash.cxx \ + custtrans.cxx \ location.cxx \ model.cxx \ modellib.cxx \ diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index 298f0691..68cd908f 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -17,7 +17,7 @@ #include #include "animation.hxx" -#include "flash.hxx" +#include "custtrans.hxx" #include "personality.hxx" @@ -420,26 +420,12 @@ 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( sim_time_sec ), _total_duration_sec( 0 ), _step( 0 ) { - SGPropertyNode_ptr dNode = props->getChild( "duration-sec" ); - if ( dNode == 0 ) { - _duration_sec = 1.0; - } else { - SGPropertyNode_ptr rNode = dNode->getChild("random"); - if ( rNode == 0 ) { - _duration_sec = dNode->getDoubleValue(); - } else { - double dmin = rNode->getDoubleValue( "min", 0.0 ), - dmax = rNode->getDoubleValue( "max", 1.0 ); - _duration_sec = dmin + sg_random() * ( dmax - dmin ); - } - } - - _last_time_sec = sim_time_sec - _duration_sec; - vector nodes = props->getChildren( "branch-duration-sec" ); size_t nb = nodes.size(); for ( size_t i = 0; i < nb; i++ ) { @@ -477,13 +463,17 @@ SGTimedAnimation::update() 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; } - key->setDoubleValue( sim_time_sec, this, LAST_TIME_SEC ); + 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 ); @@ -1040,33 +1030,129 @@ void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp) // Implementation of SGFlashAnimation //////////////////////////////////////////////////////////////////////// SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props) - : SGAnimation( props, new SGFlash ) + : SGAnimation( props, new SGCustomTransform ) { - 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 ); + _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 diff --git a/simgear/scene/model/animation.hxx b/simgear/scene/model/animation.hxx index 98193fce..95807afb 100644 --- a/simgear/scene/model/animation.hxx +++ b/simgear/scene/model/animation.hxx @@ -433,6 +433,35 @@ class SGFlashAnimation : public SGAnimation public: SGFlashAnimation(SGPropertyNode_ptr props); virtual ~SGFlashAnimation (); + + static void flashCallback( sgMat4 r, sgFrustum *f, sgMat4 m, void *d ); + void flashCallback( sgMat4 r, sgFrustum *f, sgMat4 m ); + +private: + sgVec3 _axis, _center; + float _power, _factor, _offset, _min_v, _max_v; + bool _two_sides; +}; + + +/** + * An animation that compute a scale according to + * the distance from a point and the viewer + */ +class SGDistScaleAnimation : public SGAnimation +{ +public: + SGDistScaleAnimation(SGPropertyNode_ptr props); + virtual ~SGDistScaleAnimation (); + + static void distScaleCallback( sgMat4 r, sgFrustum *f, sgMat4 m, void *d ); + void distScaleCallback( sgMat4 r, sgFrustum *f, sgMat4 m ); + +private: + sgVec3 _center; + float _factor, _offset, _min_v, _max_v; + bool _has_min, _has_max; + SGInterpTable * _table; }; diff --git a/simgear/scene/model/custtrans.cxx b/simgear/scene/model/custtrans.cxx new file mode 100755 index 00000000..bde8be13 --- /dev/null +++ b/simgear/scene/model/custtrans.cxx @@ -0,0 +1,61 @@ +/* + $Id$ +*/ + +#include "plib/ssg.h" +#include "custtrans.hxx" +void _ssgPushMatrix ( sgMat4 m ); +void _ssgPopMatrix (); +void _ssgReadInt ( FILE *fd, int *var ); +void _ssgWriteInt ( FILE *fd, const int var ); +extern sgMat4 _ssgOpenGLAxisSwapMatrix; + +void SGCustomTransform::copy_from( SGCustomTransform *src, int clone_flags ) +{ + ssgBranch::copy_from( src, clone_flags ); + _callback = src->_callback; + _data = (void *)src->_callback; +} + +ssgBase *SGCustomTransform::clone( int clone_flags ) +{ + SGCustomTransform *b = new SGCustomTransform; + b -> copy_from( this, clone_flags ); + return b; +} + + +SGCustomTransform::SGCustomTransform() + : _callback(0),_data(0) +{ + type = ssgTypeBranch(); +} + +SGCustomTransform::~SGCustomTransform() +{ +} + +void SGCustomTransform::cull( sgFrustum *f, sgMat4 m, int test_needed ) +{ + if ( ! preTravTests( &test_needed, SSGTRAV_CULL ) ) + return; + + if ( _callback ) { + sgMat4 tmp; + _callback( tmp, f, m, _data ); + + _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 ); +} + + +const char *SGCustomTransform::getTypeName (void) { return "SGCustomTransform"; } diff --git a/simgear/scene/model/custtrans.hxx b/simgear/scene/model/custtrans.hxx new file mode 100755 index 00000000..2b0da4a5 --- /dev/null +++ b/simgear/scene/model/custtrans.hxx @@ -0,0 +1,32 @@ +/** + * $Id$ + */ + +#ifndef _SG_CUSTOM_TRANSFORM_HXX +#define _SG_CUSTOM_TRANSFORM_HXX 1 + +class SGCustomTransform : public ssgBranch +{ +public: + typedef void (*TransCallback)( sgMat4 r, sgFrustum *f, sgMat4 m, void *d ); + virtual ssgBase *clone( int clone_flags = 0 ); + SGCustomTransform(); + virtual ~SGCustomTransform(void); + + void setTransCallback( TransCallback c, void *d ) { + _callback = c; + _data = d; + } + + virtual const char *getTypeName(void); + virtual void cull( sgFrustum *f, sgMat4 m, int test_needed ); + +protected: + virtual void copy_from( SGCustomTransform *src, int clone_flags ); + +private: + TransCallback _callback; + void *_data; +}; + +#endif // _SG_CUSTOM_TRANSFORM_HXX diff --git a/simgear/scene/model/flash.cxx b/simgear/scene/model/flash.cxx deleted file mode 100755 index 67a2ec52..00000000 --- a/simgear/scene/model/flash.cxx +++ /dev/null @@ -1,151 +0,0 @@ -/* - $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 ); - - 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 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 deleted file mode 100755 index 47d4fe33..00000000 --- a/simgear/scene/model/flash.hxx +++ /dev/null @@ -1,37 +0,0 @@ -/** - * $Id$ - */ - -#ifndef _SG_FLASH_HXX -#define _SG_FLASH_HXX 1 - -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; -}; - -#endif // _SG_FLASH_HXX diff --git a/simgear/scene/model/model.cxx b/simgear/scene/model/model.cxx index 3e6d508b..3d7cf5f3 100644 --- a/simgear/scene/model/model.cxx +++ b/simgear/scene/model/model.cxx @@ -156,6 +156,8 @@ sgMakeAnimation( ssgBranch * model, animation = new SGAlphaTestAnimation(node); } else if (!strcmp("flash", type)) { animation = new SGFlashAnimation(node); + } else if (!strcmp("dist-scale", type)) { + animation = new SGDistScaleAnimation(node); } else { animation = new SGNullAnimation(node); SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type); -- 2.39.5