]> git.mxchange.org Git - simgear.git/commitdiff
Split out animation code from fgfs-src/Model/model.[ch]xx and move it over
authorcurt <curt>
Thu, 8 May 2003 16:32:17 +0000 (16:32 +0000)
committercurt <curt>
Thu, 8 May 2003 16:32:17 +0000 (16:32 +0000)
here.

simgear/scene/model/Makefile.am
simgear/scene/model/animation.cxx [new file with mode: 0644]
simgear/scene/model/animation.hxx [new file with mode: 0644]

index 26de102c039f3d6eba4f604e4e8d48a9ff65c150..661f294caa32d75a78ee0ec418c0541d8ba529b3 100644 (file)
@@ -4,8 +4,8 @@ lib_LIBRARIES = libsgmodel.a
 
 noinst_HEADERS =
 
-include_HEADERS = location.hxx
+include_HEADERS = animation.hxx location.hxx
 
-libsgmodel_a_SOURCES = location.cxx
+libsgmodel_a_SOURCES = animation.cxx location.cxx
 
 INCLUDES = -I$(top_srcdir)
diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx
new file mode 100644 (file)
index 0000000..e20b597
--- /dev/null
@@ -0,0 +1,379 @@
+// animation.hxx - classes to manage model animation.
+// Written by David Megginson, started 2002.
+//
+// This file is in the Public Domain, and comes with no warranty.
+
+
+#include <string.h>             // for strcmp()
+
+#include <plib/sg.h>
+#include <plib/ssg.h>
+#include <plib/ul.h>
+
+#include <simgear/math/interpolater.hxx>
+#include <simgear/props/condition.hxx>
+#include <simgear/props/props.hxx>
+
+#include "animation.hxx"
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Static utility functions.
+////////////////////////////////////////////////////////////////////////
+
+/**
+ * Set up the transform matrix for a spin or rotation.
+ */
+static void
+set_rotation (sgMat4 &matrix, double position_deg,
+              sgVec3 &center, sgVec3 &axis)
+{
+ float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ;
+ float s = (float) sin ( temp_angle ) ;
+ float c = (float) cos ( temp_angle ) ;
+ float t = SG_ONE - c ;
+
+ // axis was normalized at load time 
+ // hint to the compiler to put these into FP registers
+ float x = axis[0];
+ 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[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;
+
+  // 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;
+}
+
+/**
+ * Set up the transform matrix for a translation.
+ */
+static void
+set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis)
+{
+  sgVec3 xyz;
+  sgScaleVec3(xyz, axis, position_m);
+  sgMakeTransMat4(matrix, xyz);
+}
+
+
+/**
+ * Read an interpolation table from properties.
+ */
+static SGInterpTable *
+read_interpolation_table (SGPropertyNode_ptr props)
+{
+  SGPropertyNode_ptr table_node = props->getNode("interpolation");
+  if (table_node != 0) {
+    SGInterpTable * table = new SGInterpTable();
+    vector<SGPropertyNode_ptr> entries = table_node->getChildren("entry");
+    for (unsigned int i = 0; i < entries.size(); i++)
+      table->addEntry(entries[i]->getDoubleValue("ind", 0.0),
+                      entries[i]->getDoubleValue("dep", 0.0));
+    return table;
+  } else {
+    return 0;
+  }
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of Animation
+////////////////////////////////////////////////////////////////////////
+
+// Initialize the static data member
+double Animation::sim_time_sec = 0.0;
+
+Animation::Animation (SGPropertyNode_ptr props, ssgBranch * branch)
+    : _branch(branch)
+{
+    _branch->setName(props->getStringValue("name", 0));
+}
+
+Animation::~Animation ()
+{
+}
+
+void
+Animation::init ()
+{
+}
+
+void
+Animation::update()
+{
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of NullAnimation
+////////////////////////////////////////////////////////////////////////
+
+NullAnimation::NullAnimation (SGPropertyNode_ptr props)
+  : Animation(props, new ssgBranch)
+{
+}
+
+NullAnimation::~NullAnimation ()
+{
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of RangeAnimation
+////////////////////////////////////////////////////////////////////////
+
+RangeAnimation::RangeAnimation (SGPropertyNode_ptr props)
+  : Animation(props, new ssgRangeSelector)
+{
+    float ranges[] = { props->getFloatValue("min-m", 0),
+                       props->getFloatValue("max-m", 5000) };
+    ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
+                       
+}
+
+RangeAnimation::~RangeAnimation ()
+{
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of BillboardAnimation
+////////////////////////////////////////////////////////////////////////
+
+BillboardAnimation::BillboardAnimation (SGPropertyNode_ptr props)
+    : Animation(props, new ssgCutout(props->getBoolValue("spherical", true)))
+{
+}
+
+BillboardAnimation::~BillboardAnimation ()
+{
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of SelectAnimation
+////////////////////////////////////////////////////////////////////////
+
+SelectAnimation::SelectAnimation( SGPropertyNode *prop_root,
+                                  SGPropertyNode_ptr props )
+  : Animation(props, new ssgSelector),
+    _condition(0)
+{
+  SGPropertyNode_ptr node = props->getChild("condition");
+  if (node != 0)
+    _condition = fgReadCondition(prop_root, node);
+}
+
+SelectAnimation::~SelectAnimation ()
+{
+  delete _condition;
+}
+
+void
+SelectAnimation::update()
+{
+  if (_condition != 0 && _condition->test()) 
+      ((ssgSelector *)_branch)->select(0xffff);
+  else
+      ((ssgSelector *)_branch)->select(0x0000);
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of SpinAnimation
+////////////////////////////////////////////////////////////////////////
+
+SpinAnimation::SpinAnimation( SGPropertyNode *prop_root,
+                              SGPropertyNode_ptr props,
+                              double sim_time_sec )
+  : Animation(props, new ssgTransform),
+    _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
+    _factor(props->getDoubleValue("factor", 1.0)),
+    _position_deg(props->getDoubleValue("starting-position-deg", 0)),
+    _last_time_sec( sim_time_sec )
+{
+    _center[0] = props->getFloatValue("center/x-m", 0);
+    _center[1] = props->getFloatValue("center/y-m", 0);
+    _center[2] = props->getFloatValue("center/z-m", 0);
+    _axis[0] = props->getFloatValue("axis/x", 0);
+    _axis[1] = props->getFloatValue("axis/y", 0);
+    _axis[2] = props->getFloatValue("axis/z", 0);
+    sgNormalizeVec3(_axis);
+}
+
+SpinAnimation::~SpinAnimation ()
+{
+}
+
+void
+SpinAnimation::update()
+{
+  double dt = sim_time_sec - _last_time_sec;
+  _last_time_sec = sim_time_sec;
+
+  float 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;
+  set_rotation(_matrix, _position_deg, _center, _axis);
+  ((ssgTransform *)_branch)->setTransform(_matrix);
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of TimedAnimation
+////////////////////////////////////////////////////////////////////////
+
+TimedAnimation::TimedAnimation (SGPropertyNode_ptr props)
+  : Animation(props, new ssgSelector),
+    _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
+    _last_time_sec(0),
+    _step(-1)
+{
+}
+
+TimedAnimation::~TimedAnimation ()
+{
+}
+
+void
+TimedAnimation::update()
+{
+    if ((sim_time_sec - _last_time_sec) >= _duration_sec) {
+        _last_time_sec = sim_time_sec;
+        _step++;
+        if (_step >= getBranch()->getNumKids())
+            _step = 0;
+        ((ssgSelector *)getBranch())->selectStep(_step);
+    }
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of RotateAnimation
+////////////////////////////////////////////////////////////////////////
+
+RotateAnimation::RotateAnimation( SGPropertyNode *prop_root,
+                                  SGPropertyNode_ptr props )
+    : Animation(props, new ssgTransform),
+      _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
+      _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
+      _factor(props->getDoubleValue("factor", 1.0)),
+      _table(read_interpolation_table(props)),
+      _has_min(props->hasValue("min-deg")),
+      _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))
+{
+  _center[0] = props->getFloatValue("center/x-m", 0);
+  _center[1] = props->getFloatValue("center/y-m", 0);
+  _center[2] = props->getFloatValue("center/z-m", 0);
+  _axis[0] = props->getFloatValue("axis/x", 0);
+  _axis[1] = props->getFloatValue("axis/y", 0);
+  _axis[2] = props->getFloatValue("axis/z", 0);
+  sgNormalizeVec3(_axis);
+}
+
+RotateAnimation::~RotateAnimation ()
+{
+  delete _table;
+}
+
+void
+RotateAnimation::update()
+{
+  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());
+  }
+  set_rotation(_matrix, _position_deg, _center, _axis);
+  ((ssgTransform *)_branch)->setTransform(_matrix);
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of TranslateAnimation
+////////////////////////////////////////////////////////////////////////
+
+TranslateAnimation::TranslateAnimation( SGPropertyNode *prop_root,
+                                        SGPropertyNode_ptr props )
+  : Animation(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)),
+    _table(read_interpolation_table(props)),
+    _has_min(props->hasValue("min-m")),
+    _min_m(props->getDoubleValue("min-m")),
+    _has_max(props->hasValue("max-m")),
+    _max_m(props->getDoubleValue("max-m")),
+    _position_m(props->getDoubleValue("starting-position-m", 0))
+{
+  _axis[0] = props->getFloatValue("axis/x", 0);
+  _axis[1] = props->getFloatValue("axis/y", 0);
+  _axis[2] = props->getFloatValue("axis/z", 0);
+  sgNormalizeVec3(_axis);
+}
+
+TranslateAnimation::~TranslateAnimation ()
+{
+  delete _table;
+}
+
+void
+TranslateAnimation::update()
+{
+  if (_table == 0) {
+    _position_m = (_prop->getDoubleValue() + _offset_m) * _factor;
+    if (_has_min && _position_m < _min_m)
+      _position_m = _min_m;
+    if (_has_max && _position_m > _max_m)
+      _position_m = _max_m;
+  } else {
+    _position_m = _table->interpolate(_prop->getDoubleValue());
+  }
+  set_translation(_matrix, _position_m, _axis);
+  ((ssgTransform *)_branch)->setTransform(_matrix);
+}
+
+
+// end of animation.cxx
diff --git a/simgear/scene/model/animation.hxx b/simgear/scene/model/animation.hxx
new file mode 100644 (file)
index 0000000..a59c040
--- /dev/null
@@ -0,0 +1,232 @@
+// animation.hxx - classes to manage model animation.
+// Written by David Megginson, started 2002.
+//
+// This file is in the Public Domain, and comes with no warranty.
+
+#ifndef _SG_ANIMATION_HXX
+#define _SG_ANIMATION_HXX 1
+
+#ifndef __cplusplus
+# error This library requires C++
+#endif
+
+#include <vector>
+
+SG_USING_STD(vector);
+
+#include <plib/sg.h>
+#include <plib/ssg.h>
+
+#include <simgear/math/point3d.hxx>
+#include <simgear/props/props.hxx>
+
+
+// Don't pull in the headers, since we don't need them here.
+class ssgBranch;
+class ssgCutout;
+class ssgEntity;
+class ssgRangeSelector;
+class ssgSelector;
+class ssgTransform;
+
+class SGInterpTable;
+class FGCondition;
+class FGLocation;
+
+
+// Has anyone done anything *really* stupid, like making min and max macros?
+#ifdef min
+#undef min
+#endif
+#ifdef max
+#undef max
+#endif
+
+
+\f
+//////////////////////////////////////////////////////////////////////
+// Animation classes
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * Abstract base class for all animations.
+ */
+class Animation :  public ssgBase
+{
+public:
+
+  Animation (SGPropertyNode_ptr props, ssgBranch * branch);
+
+  virtual ~Animation ();
+
+  /**
+   * Get the SSG branch holding the animation.
+   */
+  virtual ssgBranch * getBranch () { return _branch; }
+
+  /**
+   * Initialize the animation, after children have been added.
+   */
+  virtual void init ();
+
+  /**
+   * Update the animation.
+   */
+  virtual void update();
+
+  /**
+   * Set the value of sim_time_sec.  This needs to be called every
+   * frame in order for the time based animations to work correctly.
+   */
+  static void set_sim_time_sec( double val ) { sim_time_sec = val; }
+
+protected:
+
+  static double sim_time_sec;
+
+  ssgBranch * _branch;
+
+};
+
+
+/**
+ * A no-op animation.
+ */
+class NullAnimation : public Animation
+{
+public:
+  NullAnimation (SGPropertyNode_ptr props);
+  virtual ~NullAnimation ();
+};
+
+
+/**
+ * A range, or level-of-detail (LOD) animation.
+ */
+class RangeAnimation : public Animation
+{
+public:
+  RangeAnimation (SGPropertyNode_ptr props);
+  virtual ~RangeAnimation ();
+};
+
+
+/**
+ * Animation to turn and face the screen.
+ */
+class BillboardAnimation : public Animation
+{
+public:
+  BillboardAnimation (SGPropertyNode_ptr props);
+  virtual ~BillboardAnimation ();
+};
+
+
+/**
+ * Animation to select alternative versions of the same object.
+ */
+class SelectAnimation : public Animation
+{
+public:
+  SelectAnimation( SGPropertyNode *prop_root,
+                   SGPropertyNode_ptr props );
+  virtual ~SelectAnimation ();
+  virtual void update();
+private:
+  FGCondition * _condition;
+};
+
+
+/**
+ * Animation to spin an object around a center point.
+ *
+ * This animation rotates at a specific velocity.
+ */
+class SpinAnimation : public Animation
+{
+public:
+  SpinAnimation( SGPropertyNode *prop_root,
+                 SGPropertyNode_ptr props,
+                 double sim_time_sec );
+  virtual ~SpinAnimation ();
+  virtual void update();
+private:
+  SGPropertyNode_ptr _prop;
+  double _factor;
+  double _position_deg;
+  double _last_time_sec;
+  sgMat4 _matrix;
+  sgVec3 _center;
+  sgVec3 _axis;
+};
+
+
+/**
+ * Animation to draw objects for a specific amount of time each.
+ */
+class TimedAnimation : public Animation
+{
+public:
+    TimedAnimation (SGPropertyNode_ptr props);
+    virtual ~TimedAnimation ();
+    virtual void update();
+private:
+    double _duration_sec;
+    double _last_time_sec;
+    int _step;
+};
+
+
+/**
+ * Animation to rotate an object around a center point.
+ *
+ * This animation rotates to a specific position.
+ */
+class RotateAnimation : public Animation
+{
+public:
+  RotateAnimation( SGPropertyNode *prop_root, SGPropertyNode_ptr props );
+  virtual ~RotateAnimation ();
+  virtual void update();
+private:
+  SGPropertyNode_ptr _prop;
+  double _offset_deg;
+  double _factor;
+  SGInterpTable * _table;
+  bool _has_min;
+  double _min_deg;
+  bool _has_max;
+  double _max_deg;
+  double _position_deg;
+  sgMat4 _matrix;
+  sgVec3 _center;
+  sgVec3 _axis;
+};
+
+
+/**
+ * Animation to slide along an axis.
+ */
+class TranslateAnimation : public Animation
+{
+public:
+  TranslateAnimation( SGPropertyNode *prop_root,
+                      SGPropertyNode_ptr props );
+  virtual ~TranslateAnimation ();
+  virtual void update();
+private:
+  SGPropertyNode_ptr _prop;
+  double _offset_m;
+  double _factor;
+  SGInterpTable * _table;
+  bool _has_min;
+  double _min_m;
+  bool _has_max;
+  double _max_m;
+  double _position_m;
+  sgMat4 _matrix;
+  sgVec3 _axis;
+};
+
+
+#endif // _SG_ANIMATION_HXX