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 :

 <animation>
  <type>dist-scale</type>
  <object-name>RedLight.2</object-name>
  <interpolation>
   <entry><ind>0</ind><dep>0.1</dep></entry>
   <entry><ind>500</ind><dep>0.3</dep></entry>
   <entry><ind>16000</ind><dep>3</dep></entry>
  </interpolation>
 </animation>

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.
This commit is contained in:
curt
2004-05-11 22:21:24 +00:00
parent 331a4e4406
commit bda112297f
9 changed files with 273 additions and 227 deletions

View File

@@ -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; i<nb; i++) {
ssgEntity *e = b->getKid(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);

View File

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

View File

@@ -17,7 +17,7 @@
#include <simgear/math/sg_random.h>
#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<SGPropertyNode_ptr> 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 );
_axis[0] = props->getFloatValue("axis/x", 0);
_axis[1] = props->getFloatValue("axis/y", 0);
_axis[2] = props->getFloatValue("axis/z", 1);
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 );
_center[0] = props->getFloatValue("center/x-m", 0);
_center[1] = props->getFloatValue("center/y-m", 0);
_center[2] = props->getFloatValue("center/z-m", 0);
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 );
_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);
float v_min = props->getFloatValue("min", 0.0);
float v_max = props->getFloatValue("max", 1.0);
((SGFlash *)_branch)->setClampValues( v_min, v_max );
_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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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