+////////////////////////////////////////////////////////////////////////
+// Implementation of SGTexTranslateAnimation
+////////////////////////////////////////////////////////////////////////
+
+SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
+ SGPropertyNode_ptr props )
+ : SGAnimation(props, new ssgTexTrans),
+ _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
+ _offset(props->getDoubleValue("offset", 0.0)),
+ _factor(props->getDoubleValue("factor", 1.0)),
+ _step(props->getDoubleValue("step",0.0)),
+ _scroll(props->getDoubleValue("scroll",0.0)),
+ _table(read_interpolation_table(props)),
+ _has_min(props->hasValue("min")),
+ _min(props->getDoubleValue("min")),
+ _has_max(props->hasValue("max")),
+ _max(props->getDoubleValue("max")),
+ _position(props->getDoubleValue("starting-position", 0))
+{
+ _axis[0] = props->getFloatValue("axis/x", 0);
+ _axis[1] = props->getFloatValue("axis/y", 0);
+ _axis[2] = props->getFloatValue("axis/z", 0);
+ sgNormalizeVec3(_axis);
+}
+
+SGTexTranslateAnimation::~SGTexTranslateAnimation ()
+{
+ delete _table;
+}
+
+int
+SGTexTranslateAnimation::update()
+{
+ 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));
+ }
+ set_translation(_matrix, _position, _axis);
+ ((ssgTexTrans *)_branch)->setTransform(_matrix);
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+// Implementation of SGTexMultipleAnimation
+////////////////////////////////////////////////////////////////////////
+
+SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
+ SGPropertyNode_ptr props )
+ : SGAnimation(props, new ssgTexTrans),
+ _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
+{
+ unsigned int i;
+ // Load animations
+ vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
+ _transform = new TexTransform [transform_nodes.size()];
+ _num_transforms = 0;
+ for (i = 0; i < transform_nodes.size(); i++) {
+ SGPropertyNode_ptr transform_props = transform_nodes[i];
+
+ if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
+
+ // transform is a translation
+ _transform[i].subtype = 0;
+
+ _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
+
+ _transform[i].offset = transform_props->getDoubleValue("offset", 0.0);
+ _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
+ _transform[i].step = transform_props->getDoubleValue("step",0.0);
+ _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0);
+ _transform[i].table = read_interpolation_table(transform_props);
+ _transform[i].has_min = transform_props->hasValue("min");
+ _transform[i].min = transform_props->getDoubleValue("min");
+ _transform[i].has_max = transform_props->hasValue("max");
+ _transform[i].max = transform_props->getDoubleValue("max");
+ _transform[i].position = transform_props->getDoubleValue("starting-position", 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);
+ _num_transforms++;
+ } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
+
+ // transform is a rotation
+ _transform[i].subtype = 1;
+
+ _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
+ _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0);
+ _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
+ _transform[i].table = read_interpolation_table(transform_props);
+ _transform[i].has_min = transform_props->hasValue("min-deg");
+ _transform[i].min = transform_props->getDoubleValue("min-deg");
+ _transform[i].has_max = transform_props->hasValue("max-deg");
+ _transform[i].max = transform_props->getDoubleValue("max-deg");
+ _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0);
+
+ _transform[i].center[0] = transform_props->getFloatValue("center/x", 0);
+ _transform[i].center[1] = transform_props->getFloatValue("center/y", 0);
+ _transform[i].center[2] = transform_props->getFloatValue("center/z", 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);
+ _num_transforms++;
+ }
+ }
+}
+
+SGTexMultipleAnimation::~SGTexMultipleAnimation ()
+{
+ // delete _table;
+ delete _transform;
+}
+
+int
+SGTexMultipleAnimation::update()
+{
+ int i;
+ sgMat4 tmatrix;
+ sgMakeIdentMat4(tmatrix);
+ for (i = 0; i < _num_transforms; i++) {
+
+ if(_transform[i].subtype == 0) {
+
+ // subtype 0 is translation
+ if (_transform[i].table == 0) {
+ _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor;
+ if (_transform[i].has_min && _transform[i].position < _transform[i].min)
+ _transform[i].position = _transform[i].min;
+ if (_transform[i].has_max && _transform[i].position > _transform[i].max)
+ _transform[i].position = _transform[i].max;
+ } 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);
+
+ } else if (_transform[i].subtype == 1) {
+
+ // subtype 1 is rotation
+
+ if (_transform[i].table == 0) {
+ _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset;
+ if (_transform[i].has_min && _transform[i].position < _transform[i].min)
+ _transform[i].position = _transform[i].min;
+ if (_transform[i].has_max && _transform[i].position > _transform[i].max)
+ _transform[i].position = _transform[i].max;
+ } 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);
+ }
+ }
+ ((ssgTexTrans *)_branch)->setTransform(tmatrix);
+ return 1;
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of SGAlphaTestAnimation
+////////////////////////////////////////////////////////////////////////
+
+SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props)
+ : SGAnimation(props, new ssgBranch)
+{
+ _alpha_clamp = props->getFloatValue("alpha-factor", 0.0);
+}
+
+SGAlphaTestAnimation::~SGAlphaTestAnimation ()
+{
+}
+
+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 );
+ }
+ }
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of SGFlashAnimation
+////////////////////////////////////////////////////////////////////////
+SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props)
+ : SGAnimation( props, new SGCustomTransform )
+{
+ _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 );
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// 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 );
+}
+