]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/model/animation.cxx
Modified Files:
[simgear.git] / simgear / scene / model / animation.cxx
index e7aa26b3a101255e8da0088a7274d5f45b2cd616..47bee355cd18f3214edbe2a5feb3e98c5ea6ab69 100644 (file)
@@ -3,22 +3,32 @@
 //
 // 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
 ////////////////////////////////////////////////////////////////////////
@@ -29,8 +39,8 @@
  * Set up the transform matrix for a spin or rotation.
  */
 static void
-set_rotation (sgMat4 &matrix, double position_deg,
-              sgVec3 &center, sgVec3 &axis)
+set_rotation (osg::Matrix &matrix, double position_deg,
+              const osg::Vec3 &center, const osg::Vec3 &axis)
 {
  float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ;
  
@@ -44,80 +54,55 @@ set_rotation (sgMat4 &matrix, double position_deg,
  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;
 }
 
 /**
@@ -174,18 +159,15 @@ read_interpolation_table (SGPropertyNode_ptr props)
 // 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());
     }
 }
 
@@ -198,25 +180,24 @@ SGAnimation::init ()
 {
 }
 
-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)
 {
 }
 
@@ -232,7 +213,7 @@ SGNullAnimation::~SGNullAnimation ()
 
 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)
 {
@@ -266,15 +247,15 @@ SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
        _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() ) {
@@ -292,8 +273,8 @@ SGRangeAnimation::update()
     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);
 }
 
 
@@ -303,8 +284,18 @@ SGRangeAnimation::update()
 ////////////////////////////////////////////////////////////////////////
 
 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 ()
@@ -319,7 +310,7 @@ 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");
@@ -332,28 +323,29 @@ SGSelectAnimation::~SGSelectAnimation ()
   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)
 {
@@ -389,37 +381,12 @@ SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
        _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_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();
     }
 }
 
@@ -427,55 +394,25 @@ SGSpinAnimation::~SGSpinAnimation ()
 {
 }
 
-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);
 }
 
 
@@ -485,10 +422,10 @@ SGSpinAnimation::update()
 ////////////////////////////////////////////////////////////////////////
 
 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 )
     
@@ -518,9 +455,9 @@ void
 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 {
@@ -529,77 +466,33 @@ SGTimedAnimation::init()
             _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);
 }
 
 
@@ -610,7 +503,7 @@ SGTimedAnimation::update()
 
 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)),
@@ -629,14 +522,18 @@ SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
     _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;
@@ -644,17 +541,14 @@ SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
         _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 ()
@@ -662,8 +556,8 @@ SGRotateAnimation::~SGRotateAnimation ()
   delete _table;
 }
 
-int
-SGRotateAnimation::update()
+void
+SGRotateAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
 {
   if (_condition == 0 || _condition->test()) {
     if (_table == 0) {
@@ -675,10 +569,11 @@ SGRotateAnimation::update()
     } 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
@@ -688,17 +583,29 @@ SGRotateAnimation::update()
 
 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 ()
@@ -706,8 +613,8 @@ SGBlendAnimation::~SGBlendAnimation ()
     delete _table;
 }
 
-int
-SGBlendAnimation::update()
+void
+SGBlendAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
 {
   double _blend;
 
@@ -724,9 +631,9 @@ SGBlendAnimation::update()
 
   if (_blend != _prev_value) {
     _prev_value = _blend;
-    change_alpha( _branch, _blend );
+    _colorMatrix->getMatrix()(3, 3) = _blend;
   }
-  return 1;
+  traverse(node, nv);
 }
 
 
@@ -737,10 +644,11 @@ SGBlendAnimation::update()
 
 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")),
@@ -756,7 +664,12 @@ SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
   _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 ()
@@ -764,12 +677,13 @@ 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)
@@ -777,10 +691,12 @@ SGTranslateAnimation::update()
     } 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);
 }
 
 
@@ -791,14 +707,15 @@ SGTranslateAnimation::update()
 
 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")),
@@ -813,6 +730,14 @@ SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
     _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 ()
@@ -820,8 +745,8 @@ 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;
@@ -853,9 +778,10 @@ SGScaleAnimation::update()
     _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);
 }
 
 
@@ -865,7 +791,7 @@ SGScaleAnimation::update()
 
 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)),
@@ -874,15 +800,24 @@ SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
       _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 ()
@@ -890,21 +825,24 @@ 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);
 }
 
 
@@ -914,7 +852,7 @@ SGTexRotateAnimation::update()
 
 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)),
@@ -925,12 +863,21 @@ SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
     _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 ()
@@ -938,21 +885,24 @@ 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);
 }
 
 
@@ -962,7 +912,7 @@ SGTexTranslateAnimation::update()
 
 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;
@@ -994,7 +944,7 @@ SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
       _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))) {
 
@@ -1017,10 +967,13 @@ SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
       _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 ()
@@ -1028,12 +981,12 @@ 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) {
@@ -1048,8 +1001,9 @@ SGTexMultipleAnimation::update()
       } 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) {
 
@@ -1064,12 +1018,14 @@ SGTexMultipleAnimation::update()
      } 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);
 }
 
 
@@ -1079,7 +1035,7 @@ SGTexMultipleAnimation::update()
 ////////////////////////////////////////////////////////////////////////
 
 SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props)
-  : SGAnimation(props, new ssgBranch)
+  : SGAnimation(props, new osg::Group)
 {
   _alpha_clamp = props->getFloatValue("alpha-factor", 0.0);
 }
@@ -1090,93 +1046,450 @@ 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 );
-    }
-  }
+  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()
+{
 }
 
 
@@ -1184,59 +1497,143 @@ void SGFlashAnimation::flashCallback( sgMat4 r, sgFrustum *f, sgMat4 m )
 ////////////////////////////////////////////////////////////////////////
 // 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