]> Dogcows Code - chaz/yoink/blobdiff - src/moof/interpolator.hh
the massive refactoring effort
[chaz/yoink] / src / moof / interpolator.hh
diff --git a/src/moof/interpolator.hh b/src/moof/interpolator.hh
new file mode 100644 (file)
index 0000000..937ca8a
--- /dev/null
@@ -0,0 +1,204 @@
+
+/*]  Copyright (c) 2009-2010, Charles McGarvey  [**************************
+**]  All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_INTERPOLATOR_HH_
+#define _MOOF_INTERPOLATOR_HH_
+
+/**
+ * \file interpolator.hh
+ * Functions and classes concerning interpolations between values.
+ */
+
+#include <moof/math.hh>
+
+
+namespace moof {
+
+
+/**
+ * Interpolators should inherit from this base class to get some free
+ * functionality.  Subclasses of this base class will implement their own
+ * interpolation functions.
+ */
+template <class F, class T = scalar>
+class interpolator
+{
+public:
+
+       /**
+        * Interpolation mode.
+        */
+       enum mode
+       {
+               stop            = 0,    /// Interpolator will stop when done.
+               repeat          = 1,    /// Interpolator will go back to the beginning.
+               oscillate       = 2             /// Interpolator will reverse direction.
+       };
+
+
+       /**
+        * Construct an uninitialized interpolator.
+        */
+       interpolator() :
+               is_done_(true) {}
+
+       /**
+        * Construct an interpolator.
+        * \param a The initial value.
+        * \param b The target value.
+        * \param t The duration of the interpolation.
+        * \param mode The interpolation mode.
+        */
+       interpolator(const T& a, const T& b, scalar t = 1.0, mode mode = stop) :
+               state_(a),
+               prior_(a),
+               a_(a),
+               b_(b),
+               alpha_(SCALAR(0.0)),
+               scale_(SCALAR(1.0) / t),
+               mode_(mode),
+               is_done_(false) {}
+
+       /**
+        * Initialize the interpolator.  Any interpolation already being
+        * tracked by this object will be replaced with a new interpolation
+        * based on the initialization arguments.
+        * \param a The initial value.
+        * \param b The target value.
+        * \param t The duration of the interpolation.
+        * \param mode The interpolation mode.
+        */
+       void init(const T& a, const T& b, scalar t = 1.0, mode mode = stop)
+       {
+               a_ = a;
+               b_ = b;
+               alpha_ = 0.0;
+               scale_ = 1.0 / t;
+               mode_ = mode;
+               is_done_ = false;
+       }
+
+
+       /**
+        * Update the interpolation state with a timeslice.
+        * \param t The total time in seconds.
+        * \param dt The number of seconds passed since the last call to
+        * update.
+        */
+       void update(scalar t, scalar dt)
+       {
+               if (!is_done_)
+               {
+                       alpha_ += dt * scale_;
+                       prior_ = state_;
+                       state_ = function_(a_, b_, alpha_);
+
+                       if (alpha_ > 1.0)
+                       {
+                               switch (mode_)
+                               {
+                                       case stop:
+                                               alpha_ = SCALAR(1.0);
+                                               is_done_ = true;
+                                               break;
+                                       case repeat:
+                                               alpha_ -= SCALAR(1.0);
+                                               break;
+                                       case oscillate:
+                                               alpha_ = SCALAR(2.0) - alpha_;
+                                               scale_ = -scale_;
+                                               break;
+                               }
+                       }
+                       else if (alpha_ < 0.0)
+                       {
+                               switch (mode_)
+                               {
+                                       case stop:
+                                               alpha_ = SCALAR(0.0);
+                                               is_done_ = true;
+                                               break;
+                                       case repeat:
+                                               alpha_ += SCALAR(1.0);
+                                               break;
+                                       case oscillate:
+                                               alpha_ = -alpha_;
+                                               scale_ = -scale_;
+                                               break;
+                               }
+                       }
+               }
+       }
+
+
+       /**
+        * Get the interpolated value.
+        * \return The interpolated value.
+        */
+       T state() const
+       {
+               return state_;
+       }
+
+       /**
+        * Get the interpolated value interpolated between two updates.
+        * \param alpha The fraction between updates.
+        * \return The interpolated value.
+        */
+       T state(scalar alpha) const
+       {
+               return lerp(prior_, state_, alpha);
+       }
+
+       /**
+        * Get whether or not the interpolation is done.  This will only return
+        * true if the interpolation mode is stop.
+        * \return True if the interpolation has finished.
+        */
+       bool is_done() const
+       {
+               return is_done_;
+       }
+
+
+private:
+
+       T       state_;
+       T       prior_;
+       T       a_;
+       T       b_;
+
+       F       function_;
+
+       scalar  alpha_;
+       scalar  scale_;
+       mode    mode_;
+       bool    is_done_;
+};
+
+
+struct linear_interpolation_function
+{
+       template <class T>
+       T operator () (const T& a, const T& b, scalar alpha)
+       {
+               return lerp(a, b, alpha);
+       }
+};
+
+
+typedef interpolator<linear_interpolation_function> lerp_scalar;
+
+
+} // namespace moof
+
+#endif // _MOOF_INTERPOLATOR_HH_
+
This page took 0.022281 seconds and 4 git commands to generate.