//
// This file is in the Public Domain, and comes with no warranty.
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
#include <string.h> // for strcmp()
#include <math.h>
-#include <plib/sg.h>
-#include <plib/ssg.h>
-#include <plib/ul.h>
+#include <osg/AlphaFunc>
+#include <osg/AutoTransform>
+#include <osg/ColorMatrix>
+#include <osg/Drawable>
+#include <osg/Geode>
+#include <osg/LOD>
+#include <osg/MatrixTransform>
+#include <osg/StateSet>
+#include <osg/Switch>
+#include <osg/TexMat>
#include <simgear/math/interpolater.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx>
#include <simgear/math/sg_random.h>
+#include <simgear/scene/util/SGNodeMasks.hxx>
#include "animation.hxx"
-#include "custtrans.hxx"
-#include "personality.hxx"
+#include "model.hxx"
\f
////////////////////////////////////////////////////////////////////////
* Set up the transform matrix for a spin or rotation.
*/
static void
-set_rotation (sgMat4 &matrix, double position_deg,
- sgVec3 ¢er, sgVec3 &axis)
+set_rotation (osg::Matrix &matrix, double position_deg,
+ const osg::Vec3 ¢er, const osg::Vec3 &axis)
{
float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ;
float y = axis[1];
float z = axis[2];
- matrix[0][0] = t * x * x + c ;
- matrix[0][1] = t * y * x - s * z ;
- matrix[0][2] = t * z * x + s * y ;
- matrix[0][3] = SG_ZERO;
+ matrix(0, 0) = t * x * x + c ;
+ matrix(0, 1) = t * y * x - s * z ;
+ matrix(0, 2) = t * z * x + s * y ;
+ matrix(0, 3) = SG_ZERO;
- matrix[1][0] = t * x * y + s * z ;
- matrix[1][1] = t * y * y + c ;
- matrix[1][2] = t * z * y - s * x ;
- matrix[1][3] = SG_ZERO;
+ matrix(1, 0) = t * x * y + s * z ;
+ matrix(1, 1) = t * y * y + c ;
+ matrix(1, 2) = t * z * y - s * x ;
+ matrix(1, 3) = SG_ZERO;
- matrix[2][0] = t * x * z - s * y ;
- matrix[2][1] = t * y * z + s * x ;
- matrix[2][2] = t * z * z + c ;
- matrix[2][3] = SG_ZERO;
+ matrix(2, 0) = t * x * z - s * y ;
+ matrix(2, 1) = t * y * z + s * x ;
+ matrix(2, 2) = t * z * z + c ;
+ matrix(2, 3) = SG_ZERO;
// hint to the compiler to put these into FP registers
x = center[0];
y = center[1];
z = center[2];
- matrix[3][0] = x - x*matrix[0][0] - y*matrix[1][0] - z*matrix[2][0];
- matrix[3][1] = y - x*matrix[0][1] - y*matrix[1][1] - z*matrix[2][1];
- matrix[3][2] = z - x*matrix[0][2] - y*matrix[1][2] - z*matrix[2][2];
- matrix[3][3] = SG_ONE;
+ matrix(3, 0) = x - x*matrix(0, 0) - y*matrix(1, 0) - z*matrix(2, 0);
+ matrix(3, 1) = y - x*matrix(0, 1) - y*matrix(1, 1) - z*matrix(2, 1);
+ matrix(3, 2) = z - x*matrix(0, 2) - y*matrix(1, 2) - z*matrix(2, 2);
+ matrix(3, 3) = SG_ONE;
}
/**
* Set up the transform matrix for a translation.
*/
static void
-set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis)
+set_translation (osg::Matrix &matrix, double position_m, const osg::Vec3 &axis)
{
- sgVec3 xyz;
- sgScaleVec3(xyz, axis, position_m);
- sgMakeTransMat4(matrix, xyz);
+ osg::Vec3 xyz = axis * position_m;
+ matrix.makeIdentity();
+ matrix(3, 0) = xyz[0];
+ matrix(3, 1) = xyz[1];
+ matrix(3, 2) = xyz[2];
}
/**
* Set up the transform matrix for a scale operation.
*/
static void
-set_scale (sgMat4 &matrix, double x, double y, double z)
+set_scale (osg::Matrix &matrix, double x, double y, double z)
{
- sgMakeIdentMat4( matrix );
- matrix[0][0] = x;
- matrix[1][1] = y;
- matrix[2][2] = z;
-}
-
-/**
- * Recursively process all kids to change the alpha values
- */
-static void
-change_alpha( ssgBase *_branch, float _blend )
-{
- int i;
-
- for (i = 0; i < ((ssgBranch *)_branch)->getNumKids(); i++)
- change_alpha( ((ssgBranch *)_branch)->getKid(i), _blend );
-
- if ( !_branch->isAKindOf(ssgTypeLeaf())
- && !_branch->isAKindOf(ssgTypeVtxTable())
- && !_branch->isAKindOf(ssgTypeVTable()) )
- return;
-
- int num_colors = ((ssgLeaf *)_branch)->getNumColours();
-// unsigned int select_ = (_blend == 1.0) ? false : true;
-
- for (i = 0; i < num_colors; i++)
- {
-// ((ssgSelector *)_branch)->select( select_ );
- float *color = ((ssgLeaf *)_branch)->getColour(i);
- color[3] = _blend;
- }
+ matrix.makeIdentity();
+ matrix(0, 0) = x;
+ matrix(1, 1) = y;
+ matrix(2, 2) = z;
}
/**
// Implementation of SGAnimation
////////////////////////////////////////////////////////////////////////
-// Initialize the static data member
-double SGAnimation::sim_time_sec = 0.0;
-SGPersonalityBranch *SGAnimation::current_object = 0;
-
-SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
- : _branch(branch)
+SGAnimation::SGAnimation (SGPropertyNode_ptr props, osg::Group * branch)
+ : _branch(branch),
+ animation_type(0)
{
- _branch->setName(props->getStringValue("name", 0));
+ _branch->setName(props->getStringValue("name", "Animation"));
if ( props->getBoolValue( "enable-hot", true ) ) {
- _branch->setTraversalMaskBits( SSGTRAV_HOT );
+ _branch->setNodeMask(SG_NODEMASK_TERRAIN_BIT|_branch->getNodeMask());
} else {
- _branch->clrTraversalMaskBits( SSGTRAV_HOT );
+ _branch->setNodeMask(~SG_NODEMASK_TERRAIN_BIT&_branch->getNodeMask());
}
}
{
}
-int
-SGAnimation::update()
+void
+SGAnimation::restore()
{
- return 1;
}
void
-SGAnimation::restore()
+SGAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
+ traverse(node, nv);
}
-
\f
////////////////////////////////////////////////////////////////////////
// Implementation of SGNullAnimation
////////////////////////////////////////////////////////////////////////
SGNullAnimation::SGNullAnimation (SGPropertyNode_ptr props)
- : SGAnimation(props, new ssgBranch)
+ : SGAnimation(props, new osg::Group)
{
}
SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
SGPropertyNode_ptr props)
- : SGAnimation(props, new ssgRangeSelector),
+ : SGAnimation(props, new osg::LOD),
_min(0.0), _max(0.0), _min_factor(1.0), _max_factor(1.0),
_condition(0)
{
_max = props->getFloatValue("max-m", 0);
ranges[1] = _max * _max_factor;
}
- ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
+ static_cast<osg::LOD*>(_branch)->setRange(0, ranges[0], ranges[1]);
}
SGRangeAnimation::~SGRangeAnimation ()
{
}
-int
-SGRangeAnimation::update()
+void
+SGRangeAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
float ranges[2];
if ( _condition == 0 || _condition->test() ) {
ranges[0] = 0.f;
ranges[1] = 1000000000.f;
}
- ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
- return 1;
+ static_cast<osg::LOD*>(_branch)->setRange(0, ranges[0], ranges[1]);
+ traverse(node, nv);
}
////////////////////////////////////////////////////////////////////////
SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
- : SGAnimation(props, new ssgCutout(props->getBoolValue("spherical", true)))
+ : SGAnimation(props, new osg::AutoTransform)
{
+//OSGFIXME: verify
+ bool spherical = props->getBoolValue("spherical", true);
+ osg::AutoTransform* autoTrans = static_cast<osg::AutoTransform*>(_branch);
+ if (spherical) {
+ autoTrans->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_SCREEN);
+ } else {
+ autoTrans->setAutoRotateMode(osg::AutoTransform::NO_ROTATION);
+ autoTrans->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
+ }
+ autoTrans->setAutoScaleToScreen(false);
}
SGBillboardAnimation::~SGBillboardAnimation ()
SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
SGPropertyNode_ptr props )
- : SGAnimation(props, new ssgSelector),
+ : SGAnimation(props, new osg::Switch),
_condition(0)
{
SGPropertyNode_ptr node = props->getChild("condition");
delete _condition;
}
-int
-SGSelectAnimation::update()
-{
- if (_condition != 0 && _condition->test())
- ((ssgSelector *)_branch)->select(0xffff);
+void
+SGSelectAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+ if (_condition != 0 && _condition->test())
+ static_cast<osg::Switch*>(_branch)->setAllChildrenOn();
else
- ((ssgSelector *)_branch)->select(0x0000);
- return 1;
+ static_cast<osg::Switch*>(_branch)->setAllChildrenOff();
+ traverse(node, nv);
}
-
\f
////////////////////////////////////////////////////////////////////////
// Implementation of SGSpinAnimation
////////////////////////////////////////////////////////////////////////
SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
- SGPropertyNode_ptr props,
- double sim_time_sec )
- : SGAnimation(props, new ssgTransform),
+ SGPropertyNode_ptr props,
+ double sim_time_sec )
+ : SGAnimation(props, new osg::MatrixTransform),
_use_personality( props->getBoolValue("use-personality",false) ),
_prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
+ _factor( props, "factor", 1.0 ),
+ _position_deg( props, "starting-position-deg", 0.0 ),
_last_time_sec( sim_time_sec ),
_condition(0)
{
_center[1] = props->getFloatValue("center/y-m", 0);
_center[2] = props->getFloatValue("center/z-m", 0);
}
- sgNormalizeVec3(_axis);
-
- //_factor(props->getDoubleValue("factor", 1.0)),
- _factor = 1.0;
- _factor_min = 1.0;
- _factor_max = 1.0;
- SGPropertyNode_ptr factor_n = props->getNode( "factor" );
- if ( factor_n != 0 ) {
- SGPropertyNode_ptr rand_n = factor_n->getNode( "random" );
- if ( rand_n != 0 ) {
- _factor_min = rand_n->getDoubleValue( "min", 0.0 );
- _factor_max = rand_n->getDoubleValue( "max", 1.0 );
- _factor = _factor_min + sg_random() * ( _factor_max - _factor_min );
- } else {
- _factor = _factor_min = _factor_max = props->getDoubleValue("factor", 1.0);
- }
- }
- //_position_deg(props->getDoubleValue("starting-position-deg", 0)),
- _position_deg = 0.0;
- _position_deg_min = 0.0;
- _position_deg_max = 0.0;
- SGPropertyNode_ptr position_deg_n = props->getNode( "starting-position-deg" );
- if ( position_deg_n != 0 ) {
- SGPropertyNode_ptr rand_n = position_deg_n->getNode( "random" );
- if ( rand_n != 0 ) {
- _position_deg_min = rand_n->getDoubleValue( "min", 0.0 );
- _position_deg_max = rand_n->getDoubleValue( "max", 1.0 );
- _position_deg = _position_deg_min + sg_random() * ( _position_deg_max - _position_deg_min );
- } else {
- _position_deg = _position_deg_min = _position_deg_max =
- props->getDoubleValue("starting-position-deg", 1.0);
- }
+
+ _axis.normalize();
+
+ if ( _use_personality ) {
+ _factor.shuffle();
+ _position_deg.shuffle();
}
}
{
}
-int
-SGSpinAnimation::update()
+void
+SGSpinAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
+ double sim_time_sec = nv->getFrameStamp()->getReferenceTime();
if ( _condition == 0 || _condition->test() ) {
double dt;
float velocity_rpms;
- if ( _use_personality ) {
- SGPersonalityBranch *key = current_object;
- if ( !key->getIntValue( this, INIT_SPIN ) ) {
- double v = _factor_min + sg_random() * ( _factor_max - _factor_min );
- key->setDoubleValue( v, this, FACTOR_SPIN );
-
- key->setDoubleValue( sim_time_sec, this, LAST_TIME_SEC_SPIN );
- key->setIntValue( 1, this, INIT_SPIN );
-
- v = _position_deg_min + sg_random() * ( _position_deg_max - _position_deg_min );
- key->setDoubleValue( v, this, POSITION_DEG_SPIN );
- }
-
- _factor = key->getDoubleValue( this, FACTOR_SPIN );
- _position_deg = key->getDoubleValue( this, POSITION_DEG_SPIN );
- _last_time_sec = key->getDoubleValue( this, LAST_TIME_SEC_SPIN );
- dt = sim_time_sec - _last_time_sec;
- _last_time_sec = sim_time_sec;
- key->setDoubleValue( _last_time_sec, this, LAST_TIME_SEC_SPIN );
-
- velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
- _position_deg += (dt * velocity_rpms * 360);
- while (_position_deg < 0)
- _position_deg += 360.0;
- while (_position_deg >= 360.0)
- _position_deg -= 360.0;
- key->setDoubleValue( _position_deg, this, POSITION_DEG_SPIN );
- } else {
- dt = sim_time_sec - _last_time_sec;
- _last_time_sec = sim_time_sec;
-
- velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
- _position_deg += (dt * velocity_rpms * 360);
- while (_position_deg < 0)
- _position_deg += 360.0;
- while (_position_deg >= 360.0)
- _position_deg -= 360.0;
- }
+ dt = sim_time_sec - _last_time_sec;
+ _last_time_sec = sim_time_sec;
+
+ velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
+ _position_deg += (dt * velocity_rpms * 360);
+ _position_deg -= 360*floor(_position_deg/360);
+ osg::Matrix _matrix;
set_rotation(_matrix, _position_deg, _center, _axis);
- ((ssgTransform *)_branch)->setTransform(_matrix);
+ static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
}
- return 1;
+ traverse(node, nv);
}
////////////////////////////////////////////////////////////////////////
SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
- : SGAnimation(props, new ssgSelector),
+ : SGAnimation(props, new osg::Switch),
_use_personality( props->getBoolValue("use-personality",false) ),
_duration_sec(props->getDoubleValue("duration-sec", 1.0)),
- _last_time_sec( sim_time_sec ),
+ _last_time_sec( 0 ),
_total_duration_sec( 0 ),
_step( 0 )
SGTimedAnimation::init()
{
if ( !_use_personality ) {
- for ( int i = 0; i < getBranch()->getNumKids(); i++ ) {
+ for ( unsigned i = 0; i < getBranch()->getNumChildren(); i++ ) {
double v;
- if ( i < (int)_branch_duration_specs.size() ) {
+ if ( i < _branch_duration_specs.size() ) {
DurationSpec &sp = _branch_duration_specs[ i ];
v = sp._min + sg_random() * ( sp._max - sp._min );
} else {
_branch_duration_sec.push_back( v );
_total_duration_sec += v;
}
- // Sanity check : total duration shouldn't equal zero
- if ( _total_duration_sec < 0.01 ) {
- _total_duration_sec = 0.01;
- }
}
- ((ssgSelector *)getBranch())->selectStep(_step);
+ // Sanity check : total duration shouldn't equal zero
+ if (_duration_sec < 0.01)
+ _duration_sec = 0.01;
+ if ( _total_duration_sec < 0.01 )
+ _total_duration_sec = 0.01;
+
+ static_cast<osg::Switch*>(getBranch())->setSingleChildOn(_step);
}
-int
-SGTimedAnimation::update()
+void
+SGTimedAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
- if ( _use_personality ) {
- SGPersonalityBranch *key = current_object;
- if ( !key->getIntValue( this, INIT_TIMED ) ) {
- 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_TIMED, i );
- if ( i == 0 )
- offset = v;
- total += v;
- }
- // Sanity check : total duration shouldn't equal zero
- if ( total < 0.01 ) {
- total = 0.01;
- }
- offset *= sg_random();
- key->setDoubleValue( sim_time_sec - offset, this, LAST_TIME_SEC_TIMED );
- key->setDoubleValue( total, this, TOTAL_DURATION_SEC_TIMED );
- key->setIntValue( 0, this, STEP_TIMED );
- key->setIntValue( 1, this, INIT_TIMED );
- }
-
- _step = key->getIntValue( this, STEP_TIMED );
- _last_time_sec = key->getDoubleValue( this, LAST_TIME_SEC_TIMED );
- _total_duration_sec = key->getDoubleValue( this, TOTAL_DURATION_SEC_TIMED );
- while ( ( sim_time_sec - _last_time_sec ) >= _total_duration_sec ) {
- _last_time_sec += _total_duration_sec;
- }
- double duration = _duration_sec;
- if ( _step < (int)_branch_duration_specs.size() ) {
- duration = key->getDoubleValue( this, BRANCH_DURATION_SEC_TIMED, _step );
- }
- if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
- _last_time_sec += duration;
- _step += 1;
- if ( _step >= getBranch()->getNumKids() )
- _step = 0;
- }
- ((ssgSelector *)getBranch())->selectStep( _step );
- key->setDoubleValue( _last_time_sec, this, LAST_TIME_SEC_TIMED );
- key->setIntValue( _step, this, STEP_TIMED );
- } else {
- while ( ( sim_time_sec - _last_time_sec ) >= _total_duration_sec ) {
- _last_time_sec += _total_duration_sec;
- }
- double duration = _duration_sec;
- if ( _step < (int)_branch_duration_sec.size() ) {
- duration = _branch_duration_sec[ _step ];
- }
- if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
- _last_time_sec += duration;
- _step += 1;
- if ( _step >= getBranch()->getNumKids() )
- _step = 0;
- ((ssgSelector *)getBranch())->selectStep( _step );
- }
+ double sim_time_sec = nv->getFrameStamp()->getReferenceTime();
+ _last_time_sec -= _total_duration_sec*floor((sim_time_sec - _last_time_sec)/_total_duration_sec);
+ double duration = _duration_sec;
+ if ( _step < _branch_duration_sec.size() ) {
+ duration = _branch_duration_sec[ _step ];
}
- return 1;
+ if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
+ _last_time_sec += duration;
+ _step += 1;
+ if ( _step >= getBranch()->getNumChildren() )
+ _step = 0;
+ static_cast<osg::Switch*>(getBranch())->setSingleChildOn(_step);
+ }
+ traverse(node, nv);
}
SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
SGPropertyNode_ptr props )
- : SGAnimation(props, new ssgTransform),
+ : SGAnimation(props, new osg::MatrixTransform),
_prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
_offset_deg(props->getDoubleValue("offset-deg", 0.0)),
_factor(props->getDoubleValue("factor", 1.0)),
_center[0] = 0;
_center[1] = 0;
_center[2] = 0;
- if (props->hasValue("axis/x1-m")) {
+ if (props->hasValue("axis/x") || props->hasValue("axis/y") || props->hasValue("axis/z")) {
+ _axis[0] = props->getFloatValue("axis/x", 0);
+ _axis[1] = props->getFloatValue("axis/y", 0);
+ _axis[2] = props->getFloatValue("axis/z", 0);
+ } else {
double x1,y1,z1,x2,y2,z2;
- x1 = props->getFloatValue("axis/x1-m");
- y1 = props->getFloatValue("axis/y1-m");
- z1 = props->getFloatValue("axis/z1-m");
- x2 = props->getFloatValue("axis/x2-m");
- y2 = props->getFloatValue("axis/y2-m");
- z2 = props->getFloatValue("axis/z2-m");
+ x1 = props->getFloatValue("axis/x1-m", 0);
+ y1 = props->getFloatValue("axis/y1-m", 0);
+ z1 = props->getFloatValue("axis/z1-m", 0);
+ x2 = props->getFloatValue("axis/x2-m", 0);
+ y2 = props->getFloatValue("axis/y2-m", 0);
+ z2 = props->getFloatValue("axis/z2-m", 0);
_center[0] = (x1+x2)/2;
_center[1]= (y1+y2)/2;
_center[2] = (z1+z2)/2;
_axis[0] = (x2-x1)/vector_length;
_axis[1] = (y2-y1)/vector_length;
_axis[2] = (z2-z1)/vector_length;
- } else {
- _axis[0] = props->getFloatValue("axis/x", 0);
- _axis[1] = props->getFloatValue("axis/y", 0);
- _axis[2] = props->getFloatValue("axis/z", 0);
}
- if (props->hasValue("center/x-m")) {
- _center[0] = props->getFloatValue("center/x-m", 0);
- _center[1] = props->getFloatValue("center/y-m", 0);
- _center[2] = props->getFloatValue("center/z-m", 0);
+ if (props->hasValue("center/x-m") || props->hasValue("center/y-m")
+ || props->hasValue("center/z-m")) {
+ _center[0] = props->getFloatValue("center/x-m", 0);
+ _center[1] = props->getFloatValue("center/y-m", 0);
+ _center[2] = props->getFloatValue("center/z-m", 0);
}
- sgNormalizeVec3(_axis);
+ _axis.normalize();
}
SGRotateAnimation::~SGRotateAnimation ()
delete _table;
}
-int
-SGRotateAnimation::update()
+void
+SGRotateAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
if (_condition == 0 || _condition->test()) {
if (_table == 0) {
} else {
_position_deg = _table->interpolate(_prop->getDoubleValue());
}
+ osg::Matrix _matrix;
set_rotation(_matrix, _position_deg, _center, _axis);
- ((ssgTransform *)_branch)->setTransform(_matrix);
+ static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
}
- return 1;
+ traverse(node, nv);
}
\f
SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
SGPropertyNode_ptr props )
- : SGAnimation(props, new ssgTransform),
+ : SGAnimation(props, new osg::Group),
+ _use_personality( props->getBoolValue("use-personality",false) ),
_prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
_table(read_interpolation_table(props)),
_prev_value(1.0),
- _offset(props->getDoubleValue("offset", 0.0)),
- _factor(props->getDoubleValue("factor", 1.0)),
+ _offset(props,"offset",0.0),
+ _factor(props,"factor",1.0),
_has_min(props->hasValue("min")),
_min(props->getDoubleValue("min", 0.0)),
_has_max(props->hasValue("max")),
_max(props->getDoubleValue("max", 1.0))
{
+ // OSGFIXME: does ot work like that!!!
+ // depends on a not so wide available extension
+
+ _colorMatrix = new osg::ColorMatrix;
+ osg::StateSet* stateSet = _branch->getOrCreateStateSet();
+ stateSet->setAttribute(_colorMatrix.get());
+
+ if ( _use_personality ) {
+ _factor.shuffle();
+ _offset.shuffle();
+ }
}
SGBlendAnimation::~SGBlendAnimation ()
delete _table;
}
-int
-SGBlendAnimation::update()
+void
+SGBlendAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
double _blend;
if (_blend != _prev_value) {
_prev_value = _blend;
- change_alpha( _branch, _blend );
+ _colorMatrix->getMatrix()(3, 3) = _blend;
}
- return 1;
+ traverse(node, nv);
}
SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
SGPropertyNode_ptr props )
- : SGAnimation(props, new ssgTransform),
- _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
- _offset_m(props->getDoubleValue("offset-m", 0.0)),
- _factor(props->getDoubleValue("factor", 1.0)),
+ : SGAnimation(props, new osg::MatrixTransform),
+ _use_personality( props->getBoolValue("use-personality",false) ),
+ _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
+ _offset_m( props, "offset-m", 0.0 ),
+ _factor( props, "factor", 1.0 ),
_table(read_interpolation_table(props)),
_has_min(props->hasValue("min-m")),
_min_m(props->getDoubleValue("min-m")),
_axis[0] = props->getFloatValue("axis/x", 0);
_axis[1] = props->getFloatValue("axis/y", 0);
_axis[2] = props->getFloatValue("axis/z", 0);
- sgNormalizeVec3(_axis);
+ _axis.normalize();
+
+ if ( _use_personality ) {
+ _factor.shuffle();
+ _offset_m.shuffle();
+ }
}
SGTranslateAnimation::~SGTranslateAnimation ()
delete _table;
}
-int
-SGTranslateAnimation::update()
+void
+SGTranslateAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
if (_condition == 0 || _condition->test()) {
+
if (_table == 0) {
- _position_m = (_prop->getDoubleValue() + _offset_m) * _factor;
+ _position_m = (_prop->getDoubleValue() * _factor) + _offset_m;
if (_has_min && _position_m < _min_m)
_position_m = _min_m;
if (_has_max && _position_m > _max_m)
} else {
_position_m = _table->interpolate(_prop->getDoubleValue());
}
+
+ osg::Matrix _matrix;
set_translation(_matrix, _position_m, _axis);
- ((ssgTransform *)_branch)->setTransform(_matrix);
+ static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
}
- return 1;
+ traverse(node, nv);
}
SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
SGPropertyNode_ptr props )
- : SGAnimation(props, new ssgTransform),
- _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
- _x_factor(props->getDoubleValue("x-factor", 1.0)),
- _y_factor(props->getDoubleValue("y-factor", 1.0)),
- _z_factor(props->getDoubleValue("z-factor", 1.0)),
- _x_offset(props->getDoubleValue("x-offset", 1.0)),
- _y_offset(props->getDoubleValue("y-offset", 1.0)),
- _z_offset(props->getDoubleValue("z-offset", 1.0)),
+ : SGAnimation(props, new osg::MatrixTransform),
+ _use_personality( props->getBoolValue("use-personality",false) ),
+ _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
+ _x_factor(props,"x-factor",1.0),
+ _y_factor(props,"y-factor",1.0),
+ _z_factor(props,"z-factor",1.0),
+ _x_offset(props,"x-offset",1.0),
+ _y_offset(props,"y-offset",1.0),
+ _z_offset(props,"z-offset",1.0),
_table(read_interpolation_table(props)),
_has_min_x(props->hasValue("x-min")),
_has_min_y(props->hasValue("y-min")),
_max_y(props->getDoubleValue("y-max")),
_max_z(props->getDoubleValue("z-max"))
{
+ if ( _use_personality ) {
+ _x_factor.shuffle();
+ _x_offset.shuffle();
+ _y_factor.shuffle();
+ _y_offset.shuffle();
+ _z_factor.shuffle();
+ _z_offset.shuffle();
+ }
}
SGScaleAnimation::~SGScaleAnimation ()
delete _table;
}
-int
-SGScaleAnimation::update()
+void
+SGScaleAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
if (_table == 0) {
_x_scale = _prop->getDoubleValue() * _x_factor + _x_offset;
_z_scale = _table->interpolate(_prop->getDoubleValue());
}
+ osg::Matrix _matrix;
set_scale(_matrix, _x_scale, _y_scale, _z_scale );
- ((ssgTransform *)_branch)->setTransform(_matrix);
- return 1;
+ static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
+ traverse(node, nv);
}
SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
SGPropertyNode_ptr props )
- : SGAnimation(props, new ssgTexTrans),
+ : SGAnimation(props, new osg::Group),
_prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
_offset_deg(props->getDoubleValue("offset-deg", 0.0)),
_factor(props->getDoubleValue("factor", 1.0)),
_min_deg(props->getDoubleValue("min-deg")),
_has_max(props->hasValue("max-deg")),
_max_deg(props->getDoubleValue("max-deg")),
- _position_deg(props->getDoubleValue("starting-position-deg", 0))
+ _position_deg(props->getDoubleValue("starting-position-deg", 0)),
+ _condition(0)
{
+ SGPropertyNode *node = props->getChild("condition");
+ if (node != 0)
+ _condition = sgReadCondition(prop_root, node);
+
_center[0] = props->getFloatValue("center/x", 0);
_center[1] = props->getFloatValue("center/y", 0);
_center[2] = props->getFloatValue("center/z", 0);
_axis[0] = props->getFloatValue("axis/x", 0);
_axis[1] = props->getFloatValue("axis/y", 0);
_axis[2] = props->getFloatValue("axis/z", 0);
- sgNormalizeVec3(_axis);
+ _axis.normalize();
+
+ osg::StateSet* stateSet = _branch->getOrCreateStateSet();
+ _texMat = new osg::TexMat;
+ stateSet->setTextureAttribute(0, _texMat.get());
}
SGTexRotateAnimation::~SGTexRotateAnimation ()
delete _table;
}
-int
-SGTexRotateAnimation::update()
+void
+SGTexRotateAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
- if (_table == 0) {
- _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
- if (_has_min && _position_deg < _min_deg)
- _position_deg = _min_deg;
- if (_has_max && _position_deg > _max_deg)
- _position_deg = _max_deg;
- } else {
- _position_deg = _table->interpolate(_prop->getDoubleValue());
+ if (!_condition || _condition->test()) {
+ if (_table == 0) {
+ _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
+ if (_has_min && _position_deg < _min_deg)
+ _position_deg = _min_deg;
+ if (_has_max && _position_deg > _max_deg)
+ _position_deg = _max_deg;
+ } else {
+ _position_deg = _table->interpolate(_prop->getDoubleValue());
+ }
+ osg::Matrix _matrix;
+ set_rotation(_matrix, _position_deg, _center, _axis);
+ _texMat->setMatrix(_matrix);
}
- set_rotation(_matrix, _position_deg, _center, _axis);
- ((ssgTexTrans *)_branch)->setTransform(_matrix);
- return 1;
+ traverse(node, nv);
}
SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
SGPropertyNode_ptr props )
- : SGAnimation(props, new ssgTexTrans),
+ : SGAnimation(props, new osg::Group),
_prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
_offset(props->getDoubleValue("offset", 0.0)),
_factor(props->getDoubleValue("factor", 1.0)),
_min(props->getDoubleValue("min")),
_has_max(props->hasValue("max")),
_max(props->getDoubleValue("max")),
- _position(props->getDoubleValue("starting-position", 0))
+ _position(props->getDoubleValue("starting-position", 0)),
+ _condition(0)
{
+ SGPropertyNode *node = props->getChild("condition");
+ if (node != 0)
+ _condition = sgReadCondition(prop_root, node);
+
_axis[0] = props->getFloatValue("axis/x", 0);
_axis[1] = props->getFloatValue("axis/y", 0);
_axis[2] = props->getFloatValue("axis/z", 0);
- sgNormalizeVec3(_axis);
+ _axis.normalize();
+
+ osg::StateSet* stateSet = _branch->getOrCreateStateSet();
+ _texMat = new osg::TexMat;
+ stateSet->setTextureAttribute(0, _texMat.get());
}
SGTexTranslateAnimation::~SGTexTranslateAnimation ()
delete _table;
}
-int
-SGTexTranslateAnimation::update()
+void
+SGTexTranslateAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
- if (_table == 0) {
- _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
- if (_has_min && _position < _min)
- _position = _min;
- if (_has_max && _position > _max)
- _position = _max;
- } else {
- _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
+ if (!_condition || _condition->test()) {
+ if (_table == 0) {
+ _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
+ if (_has_min && _position < _min)
+ _position = _min;
+ if (_has_max && _position > _max)
+ _position = _max;
+ } else {
+ _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
+ }
+ osg::Matrix _matrix;
+ set_translation(_matrix, _position, _axis);
+ _texMat->setMatrix(_matrix);
}
- set_translation(_matrix, _position, _axis);
- ((ssgTexTrans *)_branch)->setTransform(_matrix);
- return 1;
+ traverse(node, nv);
}
SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
SGPropertyNode_ptr props )
- : SGAnimation(props, new ssgTexTrans),
+ : SGAnimation(props, new osg::Group),
_prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
{
unsigned int i;
_transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
_transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
_transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
- sgNormalizeVec3(_transform[i].axis);
+ _transform[i].axis.normalize();
_num_transforms++;
} else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
_transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
_transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
_transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
- sgNormalizeVec3(_transform[i].axis);
+ _transform[i].axis.normalize();
_num_transforms++;
}
}
+ osg::StateSet* stateSet = _branch->getOrCreateStateSet();
+ _texMat = new osg::TexMat;
+ stateSet->setTextureAttribute(0, _texMat.get());
}
SGTexMultipleAnimation::~SGTexMultipleAnimation ()
delete [] _transform;
}
-int
-SGTexMultipleAnimation::update()
+void
+SGTexMultipleAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
int i;
- sgMat4 tmatrix;
- sgMakeIdentMat4(tmatrix);
+ osg::Matrix tmatrix;
+ tmatrix.makeIdentity();
for (i = 0; i < _num_transforms; i++) {
if(_transform[i].subtype == 0) {
} else {
_transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
}
- set_translation(_transform[i].matrix, _transform[i].position, _transform[i].axis);
- sgPreMultMat4(tmatrix, _transform[i].matrix);
+ osg::Matrix matrix;
+ set_translation(matrix, _transform[i].position, _transform[i].axis);
+ tmatrix = matrix*tmatrix;
} else if (_transform[i].subtype == 1) {
} else {
_transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
}
- set_rotation(_transform[i].matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
- sgPreMultMat4(tmatrix, _transform[i].matrix);
+
+ osg::Matrix matrix;
+ set_rotation(matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
+ tmatrix = matrix*tmatrix;
}
}
- ((ssgTexTrans *)_branch)->setTransform(tmatrix);
- return 1;
+ _texMat->setMatrix(tmatrix);
+ traverse(node, nv);
}
////////////////////////////////////////////////////////////////////////
SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props)
- : SGAnimation(props, new ssgBranch)
+ : SGAnimation(props, new osg::Group)
{
_alpha_clamp = props->getFloatValue("alpha-factor", 0.0);
}
void SGAlphaTestAnimation::init()
{
- setAlphaClampToBranch(_branch,_alpha_clamp);
-}
-
-void SGAlphaTestAnimation::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 );
- }
- }
+ osg::StateSet* stateSet = _branch->getOrCreateStateSet();
+ osg::AlphaFunc* alphaFunc = new osg::AlphaFunc;
+ alphaFunc->setFunction(osg::AlphaFunc::GREATER);
+ alphaFunc->setReferenceValue(_alpha_clamp);
+ stateSet->setAttribute(alphaFunc);
+ stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
+ stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
}
\f
////////////////////////////////////////////////////////////////////////
-// Implementation of SGFlashAnimation
+// Implementation of SGMaterialAnimation
////////////////////////////////////////////////////////////////////////
-SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props)
- : SGAnimation( props, new SGCustomTransform )
+
+SGMaterialAnimation::SGMaterialAnimation( SGPropertyNode *prop_root,
+ SGPropertyNode_ptr props, const SGPath &texture_path)
+ : SGAnimation(props, new osg::Group),
+ _last_condition(false),
+ _prop_root(prop_root),
+ _prop_base(""),
+ _texture_base(texture_path),
+ _read(0),
+ _update(0),
+ _global(props->getBoolValue("global", false))
{
- _axis[0] = props->getFloatValue("axis/x", 0);
- _axis[1] = props->getFloatValue("axis/y", 0);
- _axis[2] = props->getFloatValue("axis/z", 1);
+ SGPropertyNode_ptr n;
+ n = props->getChild("condition");
+ _condition = n ? sgReadCondition(_prop_root, n) : 0;
+ n = props->getChild("property-base");
+ if (n) {
+ _prop_base = n->getStringValue();
+ if (!_prop_base.empty() && _prop_base.end()[-1] != '/')
+ _prop_base += '/';
+ }
+
+ initColorGroup(props->getChild("diffuse"), &_diff, DIFFUSE);
+ initColorGroup(props->getChild("ambient"), &_amb, AMBIENT);
+ initColorGroup(props->getChild("emission"), &_emis, EMISSION);
+ initColorGroup(props->getChild("specular"), &_spec, SPECULAR);
+
+ _shi = props->getFloatValue("shininess", -1.0);
+ if (_shi >= 0.0)
+ _update |= SHININESS;
+
+ SGPropertyNode_ptr group = props->getChild("transparency");
+ if (group) {
+ _trans.value = group->getFloatValue("alpha", -1.0);
+ _trans.factor = group->getFloatValue("factor", 1.0);
+ _trans.offset = group->getFloatValue("offset", 0.0);
+ _trans.min = group->getFloatValue("min", 0.0);
+ if (_trans.min < 0.0)
+ _trans.min = 0.0;
+ _trans.max = group->getFloatValue("max", 1.0);
+ if (_trans.max > 1.0)
+ _trans.max = 1.0;
+ if (_trans.dirty())
+ _update |= TRANSPARENCY;
+
+ n = group->getChild("alpha-prop");
+ _trans.value_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+ n = group->getChild("factor-prop");
+ _trans.factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+ n = group->getChild("offset-prop");
+ _trans.offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+ if (_trans.live())
+ _read |= TRANSPARENCY;
+ }
+
+ _thresh = props->getFloatValue("threshold", -1.0);
+ if (_thresh >= 0.0)
+ _update |= THRESHOLD;
- _center[0] = props->getFloatValue("center/x-m", 0);
- _center[1] = props->getFloatValue("center/y-m", 0);
- _center[2] = props->getFloatValue("center/z-m", 0);
+ string _texture_str = props->getStringValue("texture", "");
+ if (!_texture_str.empty()) {
+ _texture = _texture_base;
+ _texture.append(_texture_str);
+ _texture2D = SGLoadTexture2D(_texture);
+ _update |= TEXTURE;
+ }
- _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);
+ n = props->getChild("shininess-prop");
+ _shi_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+ n = props->getChild("threshold-prop");
+ _thresh_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+ n = props->getChild("texture-prop");
+ _tex_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
- _min_v = props->getFloatValue("min", 0.0);
- _max_v = props->getFloatValue("max", 1.0);
+ _static_update = _update;
- ((SGCustomTransform *)_branch)->setTransCallback( &SGFlashAnimation::flashCallback, this );
+ _alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0);
}
-SGFlashAnimation::~SGFlashAnimation()
+void SGMaterialAnimation::initColorGroup(SGPropertyNode_ptr group, ColorSpec *col, int flag)
{
+ if (!group)
+ return;
+
+ col->red = group->getFloatValue("red", -1.0);
+ col->green = group->getFloatValue("green", -1.0);
+ col->blue = group->getFloatValue("blue", -1.0);
+ col->factor = group->getFloatValue("factor", 1.0);
+ col->offset = group->getFloatValue("offset", 0.0);
+ if (col->dirty())
+ _update |= flag;
+
+ SGPropertyNode *n;
+ n = group->getChild("red-prop");
+ col->red_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+ n = group->getChild("green-prop");
+ col->green_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+ n = group->getChild("blue-prop");
+ col->blue_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+ n = group->getChild("factor-prop");
+ col->factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+ n = group->getChild("offset-prop");
+ col->offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+ if (col->live())
+ _read |= flag;
}
-void SGFlashAnimation::flashCallback( sgMat4 r, sgFrustum *f, sgMat4 m, void *d )
+void SGMaterialAnimation::init()
{
- ((SGFlashAnimation *)d)->flashCallback( r, f, m );
+ if (!_global)
+ cloneMaterials(_branch);
+
+ // OSGFIXME
+ osg::StateSet* stateSet = _branch->getOrCreateStateSet();
+ if (_update & THRESHOLD) {
+ stateSet->setAttribute(_alphaFunc.get(), osg::StateAttribute::OVERRIDE);
+ stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
+ }
+ if (_update & TEXTURE) {
+ stateSet->setTextureAttribute(0, _texture2D.get(), osg::StateAttribute::OVERRIDE);
+ stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
+ }
}
-void SGFlashAnimation::flashCallback( sgMat4 r, sgFrustum *f, sgMat4 m )
+void
+SGMaterialAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
- sgVec3 transformed_axis;
- sgXformVec3( transformed_axis, _axis, m );
- sgNormalizeVec3( transformed_axis );
+ if (_condition) {
+ bool cond = _condition->test();
+ if (cond && !_last_condition)
+ _update |= _static_update;
+
+ _last_condition = cond;
+ if (!cond) {
+ traverse(node, nv);
+ return;
+ }
+ }
+
+ if (_read & DIFFUSE)
+ updateColorGroup(&_diff, DIFFUSE);
+ if (_read & AMBIENT)
+ updateColorGroup(&_amb, AMBIENT);
+ if (_read & EMISSION)
+ updateColorGroup(&_emis, EMISSION);
+ if (_read & SPECULAR)
+ updateColorGroup(&_spec, SPECULAR);
+
+ float f;
+ if (_shi_prop) {
+ f = _shi;
+ _shi = _shi_prop->getFloatValue();
+ if (_shi != f)
+ _update |= SHININESS;
+ }
+ if (_read & TRANSPARENCY) {
+ PropSpec tmp = _trans;
+ if (_trans.value_prop)
+ _trans.value = _trans.value_prop->getFloatValue();
+ if (_trans.factor_prop)
+ _trans.factor = _trans.factor_prop->getFloatValue();
+ if (_trans.offset_prop)
+ _trans.offset = _trans.offset_prop->getFloatValue();
+ if (_trans != tmp)
+ _update |= TRANSPARENCY;
+ }
+ if (_thresh_prop) {
+ f = _thresh;
+ _thresh = _thresh_prop->getFloatValue();
+ if (_thresh != f)
+ _update |= THRESHOLD;
+ }
+ if (_tex_prop) {
+ string t = _tex_prop->getStringValue();
+ if (!t.empty() && t != _texture_str) {
+ _texture_str = t;
+ _texture = _texture_base;
+ _texture.append(t);
+ _update |= TEXTURE;
+ }
+ }
+ if (_update) {
+ setMaterialBranch(_branch);
+ _update = 0;
+ }
+ traverse(node, nv);
+}
+
+void SGMaterialAnimation::updateColorGroup(ColorSpec *col, int flag)
+{
+ ColorSpec tmp = *col;
+ if (col->red_prop)
+ col->red = col->red_prop->getFloatValue();
+ if (col->green_prop)
+ col->green = col->green_prop->getFloatValue();
+ if (col->blue_prop)
+ col->blue = col->blue_prop->getFloatValue();
+ if (col->factor_prop)
+ col->factor = col->factor_prop->getFloatValue();
+ if (col->offset_prop)
+ col->offset = col->offset_prop->getFloatValue();
+ if (*col != tmp)
+ _update |= flag;
+}
+
+class SGMaterialAnimationCloneVisitor : public osg::NodeVisitor {
+public:
+ SGMaterialAnimationCloneVisitor() :
+ osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
+ {
+ setVisitorType(osg::NodeVisitor::NODE_VISITOR);
+ }
+ virtual void apply(osg::Node& node)
+ {
+ traverse(node);
+ osg::StateSet* stateSet = node.getStateSet();
+ if (!stateSet)
+ return;
+ if (1 < stateSet->referenceCount()) {
+ osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_STATESETS);
+ osg::Object* object = stateSet->clone(copyOp);
+ stateSet = static_cast<osg::StateSet*>(object);
+ node.setStateSet(stateSet);
+ }
+ cloneMaterial(stateSet);
+ }
+ virtual void apply(osg::Geode& node)
+ {
+ apply((osg::Node&)node);
+ traverse(node);
+ unsigned nDrawables = node.getNumDrawables();
+ for (unsigned i = 0; i < nDrawables; ++i) {
+ osg::Drawable* drawable = node.getDrawable(i);
+ osg::StateSet* stateSet = drawable->getStateSet();
+ if (!stateSet)
+ continue;
+ if (1 < stateSet->referenceCount()) {
+ osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_STATESETS);
+ osg::Object* object = stateSet->clone(copyOp);
+ stateSet = static_cast<osg::StateSet*>(object);
+ drawable->setStateSet(stateSet);
+ }
+ cloneMaterial(stateSet);
+ }
+ }
+ void cloneMaterial(osg::StateSet* stateSet)
+ {
+
+ osg::StateAttribute* stateAttr;
+ stateAttr = stateSet->getAttribute(osg::StateAttribute::MATERIAL);
+ if (!stateAttr)
+ return;
+ osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_STATEATTRIBUTES);
+ osg::Object* object = stateAttr->clone(copyOp);
+ osg::Material* material = static_cast<osg::Material*>(object);
+ materialList.push_back(material);
+ while (stateSet->getAttribute(osg::StateAttribute::MATERIAL)) {
+ stateSet->removeAttribute(osg::StateAttribute::MATERIAL);
+ }
+ stateSet->setAttribute(material);
+ }
+ std::vector<osg::Material*> materialList;
+};
+
+void SGMaterialAnimation::cloneMaterials(osg::Group *b)
+{
+ SGMaterialAnimationCloneVisitor cloneVisitor;
+ b->accept(cloneVisitor);
+ _materialList.swap(cloneVisitor.materialList);
+}
+
+void SGMaterialAnimation::setMaterialBranch(osg::Group *b)
+{
+ std::vector<osg::Material*>::iterator i;
+ for (i = _materialList.begin(); i != _materialList.end(); ++i) {
+ osg::Material* material = *i;
+ if (_update & DIFFUSE) {
+ osg::Vec4 v = _diff.rgba();
+ float alpha = material->getDiffuse(osg::Material::FRONT_AND_BACK)[3];
+ material->setColorMode(osg::Material::DIFFUSE);
+ material->setDiffuse(osg::Material::FRONT_AND_BACK,
+ osg::Vec4(v[0], v[1], v[2], alpha));
+ }
+ if (_update & AMBIENT) {
+ material->setColorMode(osg::Material::AMBIENT);
+ material->setDiffuse(osg::Material::FRONT_AND_BACK, _amb.rgba());
+ }
+ if (_update & EMISSION)
+ material->setEmission(osg::Material::FRONT_AND_BACK, _emis.rgba());
+ if (_update & SPECULAR)
+ material->setSpecular(osg::Material::FRONT_AND_BACK, _spec.rgba());
+ if (_update & SHININESS)
+ material->setShininess(osg::Material::FRONT_AND_BACK,
+ clamp(_shi, 0.0, 128.0));
+ if (_update & TRANSPARENCY) {
+ osg::Vec4 v = material->getDiffuse(osg::Material::FRONT_AND_BACK);
+ float trans = _trans.value * _trans.factor + _trans.offset;
+ trans = trans < _trans.min ? _trans.min : trans > _trans.max ? _trans.max : trans;
+ material->setDiffuse(osg::Material::FRONT_AND_BACK,
+ osg::Vec4(v[0], v[1], v[2], trans));
+ }
+ if (_update & THRESHOLD)
+ _alphaFunc->setReferenceValue(clamp(_thresh));
+ // OSGFIXME
+// if (_update & TEXTURE)
+// s->setTexture(_texture.c_str());
+// if (_update & (TEXTURE|TRANSPARENCY)) {
+// SGfloat alpha = s->getMaterial(GL_DIFFUSE)[3];
+// ssgTexture *tex = s->getTexture();
+// if ((tex && tex->hasAlpha()) || alpha < 0.999) {
+// s->setColourMaterial(GL_DIFFUSE);
+// s->enable(GL_COLOR_MATERIAL);
+// s->enable(GL_BLEND);
+// s->enable(GL_ALPHA_TEST);
+// s->setTranslucent();
+// s->disable(GL_COLOR_MATERIAL);
+// } else {
+// s->disable(GL_BLEND);
+// s->disable(GL_ALPHA_TEST);
+// s->setOpaque();
+// }
+// }
+ }
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of SGFlashAnimation
+////////////////////////////////////////////////////////////////////////
+class SGFlashAnimationTransform : public osg::Transform {
+public:
+ SGFlashAnimationTransform(SGPropertyNode* props)
+ {
+ getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
- sgVec3 view;
- sgFullXformPnt3( view, _center, m );
- sgNormalizeVec3( view );
+ _axis[0] = props->getFloatValue("axis/x", 0);
+ _axis[1] = props->getFloatValue("axis/y", 0);
+ _axis[2] = props->getFloatValue("axis/z", 1);
+ _axis.normalize();
+
+ _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);
+ }
- 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;
+ virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
+ osg::NodeVisitor* nv) const
+ {
+ double scale_factor = computeScaleFactor(nv);
+ osg::Matrix 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 );
+ if (_referenceFrame == RELATIVE_RF)
+ matrix.preMult(transform);
+ else
+ matrix = transform;
+
+ return true;
+ }
+
+ virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
+ osg::NodeVisitor* nv) const
+ {
+ double scale_factor = computeScaleFactor(nv);
+ if (fabs(scale_factor) <= std::numeric_limits<double>::min())
+ return false;
+ osg::Matrix transform;
+ double rScaleFactor = 1/scale_factor;
+ transform(0,0) = rScaleFactor;
+ transform(1,1) = rScaleFactor;
+ transform(2,2) = rScaleFactor;
+ transform(3,0) = rScaleFactor*_center[0] * ( scale_factor - 1 );
+ transform(3,1) = rScaleFactor*_center[1] * ( scale_factor - 1 );
+ transform(3,2) = rScaleFactor*_center[2] * ( scale_factor - 1 );
+ if (_referenceFrame == RELATIVE_RF)
+ matrix.postMult(transform);
+ else
+ matrix = transform;
+ return true;
+ }
- if ( scale_factor < _min_v )
+ double computeScaleFactor(osg::NodeVisitor* nv) const
+ {
+ if (!nv)
+ return 1;
+
+ osg::Vec3 localEyeToCenter = nv->getEyePoint() - _center;
+ localEyeToCenter.normalize();
+
+ double cos_angle = localEyeToCenter*_axis;
+ double scale_factor = 0;
+ if ( _two_sides && cos_angle < 0 )
+ scale_factor = _factor * pow( -cos_angle, _power ) + _offset;
+ else if ( cos_angle > 0 )
+ scale_factor = _factor * pow( cos_angle, _power ) + _offset;
+
+ if ( scale_factor < _min_v )
scale_factor = _min_v;
- if ( scale_factor > _max_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 );
+ return scale_factor;
+ }
+
+private:
+ osg::Vec3 _axis, _center;
+ double _power, _factor, _offset, _min_v, _max_v;
+ bool _two_sides;
+};
+
+SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props)
+ : SGAnimation( props, new SGFlashAnimationTransform(props) )
+{
+}
- sgCopyMat4( r, m );
- sgPreMultMat4( r, transform );
+SGFlashAnimation::~SGFlashAnimation()
+{
}
////////////////////////////////////////////////////////////////////////
// Implementation of SGDistScaleAnimation
////////////////////////////////////////////////////////////////////////
+class SGDistScaleTransform : public osg::Transform {
+public:
+ SGDistScaleTransform(SGPropertyNode* props)
+ {
+ getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
+
+ _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);
+ }
+ ~SGDistScaleTransform()
+ {
+ delete _table;
+ }
+
+ virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
+ osg::NodeVisitor* nv) const
+ {
+ osg::Matrix transform;
+ double scale_factor = computeScaleFactor(nv);
+ 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 );
+ if (_referenceFrame == RELATIVE_RF)
+ matrix.preMult(transform);
+ else
+ matrix = transform;
+ return true;
+ }
+
+ virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
+ osg::NodeVisitor* nv) const
+ {
+ double scale_factor = computeScaleFactor(nv);
+ if (fabs(scale_factor) <= std::numeric_limits<double>::min())
+ return false;
+ osg::Matrix transform;
+ double rScaleFactor = 1/scale_factor;
+ transform(0,0) = rScaleFactor;
+ transform(1,1) = rScaleFactor;
+ transform(2,2) = rScaleFactor;
+ transform(3,0) = rScaleFactor*_center[0] * ( scale_factor - 1 );
+ transform(3,1) = rScaleFactor*_center[1] * ( scale_factor - 1 );
+ transform(3,2) = rScaleFactor*_center[2] * ( scale_factor - 1 );
+ if (_referenceFrame == RELATIVE_RF)
+ matrix.postMult(transform);
+ else
+ matrix = transform;
+ return true;
+ }
+
+ double computeScaleFactor(osg::NodeVisitor* nv) const
+ {
+ if (!nv)
+ return 1;
+
+ osg::Vec3 localEyeToCenter = _center - nv->getEyePoint();
+ double scale_factor = localEyeToCenter.length();
+ 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 );
+ }
+
+ return scale_factor;
+ }
+
+
+private:
+ osg::Vec3 _center;
+ float _factor, _offset, _min_v, _max_v;
+ bool _has_min, _has_max;
+ SGInterpTable * _table;
+};
+
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))
+ : SGAnimation( props, new SGDistScaleTransform(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 )
+////////////////////////////////////////////////////////////////////////
+// Implementation of SGShadowAnimation
+////////////////////////////////////////////////////////////////////////
+
+SGShadowAnimation::SGShadowAnimation ( SGPropertyNode *prop_root,
+ SGPropertyNode_ptr props )
+ : SGAnimation(props, new osg::Group),
+ _condition(0),
+ _condition_value(true)
{
- ((SGDistScaleAnimation *)d)->distScaleCallback( r, f, m );
+ animation_type = 1;
+ SGPropertyNode_ptr node = props->getChild("condition");
+ if (node != 0) {
+ _condition = sgReadCondition(prop_root, node);
+ _condition_value = false;
+ }
}
-void SGDistScaleAnimation::distScaleCallback( sgMat4 r, sgFrustum *f, sgMat4 m )
+SGShadowAnimation::~SGShadowAnimation ()
{
- sgVec3 view;
- sgFullXformPnt3( view, _center, m );
+ delete _condition;
+}
- 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 );
- }
+void
+SGShadowAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
+{
+ if (_condition)
+ _condition_value = _condition->test();
+
+ if ( _condition_value ) {
+ _branch->setNodeMask(SG_NODEMASK_SHADOW_BIT|_branch->getNodeMask());
+ } else {
+ _branch->setNodeMask(~SG_NODEMASK_SHADOW_BIT&_branch->getNodeMask());
+ }
+ traverse(node, nv);
+}
- 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 );
+bool SGShadowAnimation::get_condition_value(void) {
+ return _condition_value;
}
// end of animation.cxx