]> Dogcows Code - chaz/yoink/blobdiff - src/Moof/Interpolator.hh
cleaned up interpolator classes
[chaz/yoink] / src / Moof / Interpolator.hh
index 4de3f6974bd3a7ceeaf93945b9d7ca5323126c07..e49ac694c2d0c3876c3b0028ca46e85e6131e462 100644 (file)
 namespace Mf {
 
 
-// TODO - cleanup these classes
+namespace Interp {
 
-class Interpolator
-{
-       void clamp(Scalar& value)
-       {
-               if (value > 1.0)
-               {
-                       switch (mode_)
-                       {
-                               case STOP:
-                                       value = 1.0;
-                                       done_ = true;
-                                       break;
-                               case REPEAT:
-                                       value -= 1.0;
-                                       break;
-                               case OSCILLATE:
-                                       value = 2.0 - value;
-                                       scale_ *= -1.0;
-                                       break;
-                       }
-               }
-               else if (value < 0.0)
-               {
-                       switch (mode_)
-                       {
-                               case STOP:
-                                       value = 0.0;
-                                       done_ = true;
-                                       break;
-                               case REPEAT:
-                                       value += 1.0;
-                                       break;
-                               case OSCILLATE:
-                                       value = -value;
-                                       scale_ *= -1.0;
-                                       break;
-                       }
-               }
-       }
-
-public:
        typedef enum
        {
                STOP            = 0,
@@ -86,191 +45,128 @@ public:
                OSCILLATE       = 2
        } Mode;
 
-       void init(Scalar seconds = 1.0, Mode mode = STOP)
-       {
-               scale_ = 1.0 / seconds;
-               alpha_ = 0.0;
-               setMode(mode);
-       }
+} // namespace Interp
 
 
-       void setMode(Mode mode)
-       {
-               mode_ = mode;
-               done_ = false;
-       }
-
+template <class T>
+class Interpolator : public T
+{
+public:
 
-       void update(Scalar t, Scalar dt)
+       Interpolator(Scalar t = 1.0, Interp::Mode mode = Interp::STOP)
        {
-               if (!done_)
-               {
-                       alpha_ += dt * scale_;
-                       clamp(alpha_);
-                       calculate(alpha_);
-               }
+               reset(t, mode);
        }
 
-       bool isDone() const
+       void reset(Scalar t = 1.0, Interp::Mode mode = Interp::STOP)
        {
-               return done_;
+               mAlpha = 0.0;
+               mScale = 1.0 / t;
+               mMode = mode;
+               mIsDone = false;
        }
 
-       virtual void calculate(Scalar alpha) = 0;
-
-private:
-
-       Scalar  alpha_;
-       Mode    mode_;
-       Scalar  scale_;
-       bool    done_;
-};
-
-template <class T = Scalar>
-class InterpolatorBase : public Interpolator
-{
-public:
-       void init(Scalar seconds = 1.0, Mode mode = STOP)
-       {
-               Interpolator::init(seconds, mode);
-
-               calculate(0.0); // set value
-               previous_ = value_;
-       }
-
-       void calculate(Scalar alpha)
+       void update(Scalar t, Scalar dt)
        {
-               previous_ = value_;
-               calculate(value_, alpha);
+               if (!mIsDone)
+               {
+                       mPrevState = T::getValue();
+                       mAlpha += dt * mScale;
+                       clamp();
+                       if (mPrevState == T::calculate(mAlpha)) mIsDone = true;
+               }
        }
 
-       virtual void calculate(T& value, Scalar alpha) = 0;
-
-       const T& getValue() const
+       typename T::Type getState(Scalar alpha) const
        {
-               return value_;
+               return cml::lerp(mPrevState, T::getValue(), alpha);
        }
 
-       const T getState(Scalar alpha) const
+       bool isDone() const
        {
-               return cml::lerp(previous_, value_, alpha);
+               return mIsDone;
        }
 
 private:
-       T value_;
-       T previous_;
-};
-
-
-template <int D, class T = Scalar>
-class PolynomialInterpolator : public InterpolatorBase<T>
-{
-public:
-       PolynomialInterpolator() {}
-
-       PolynomialInterpolator(const T coefficients[D+1],
-                       Scalar seconds = 1.0, Interpolator::Mode mode = Interpolator::STOP)
-       {
-               init(coefficients, seconds, mode);
-       }
 
-       void init(const T coefficients[D+1], Scalar seconds = 1.0,
-                       Interpolator::Mode mode = Interpolator::STOP)
+       void clamp()
        {
-               Scalar fac[D+1];
-
-               fac[0] = 1.0;
-               fac[1] = 1.0;
-
-               // build an array of the computed factorials we will need
-               for (int i = 2; i <= D; ++i)
+               if (mAlpha > 1.0)
                {
-                       fac[i] = i * fac[i - 1];
+                       switch (mMode)
+                       {
+                               case Interp::STOP:
+                                       mAlpha = SCALAR(1.0);
+                                       break;
+                               case Interp::REPEAT:
+                                       mAlpha -= SCALAR(1.0);
+                                       break;
+                               case Interp::OSCILLATE:
+                                       mAlpha = SCALAR(2.0) - mAlpha;
+                                       mScale = -mScale;
+                                       break;
+                       }
                }
-
-               // combine the coefficients for fast updating
-               for (int i = 0; i <= D; ++i)
+               else if (mAlpha < 0.0)
                {
-                       // n! / (k! * (n - k)!)
-                       coefficients_[i] = coefficients[i] * fac[D] / (fac[i] * fac[D - i]);
+                       switch (mMode)
+                       {
+                               case Interp::STOP:
+                                       mAlpha = SCALAR(0.0);
+                                       break;
+                               case Interp::REPEAT:
+                                       mAlpha += SCALAR(1.0);
+                                       break;
+                               case Interp::OSCILLATE:
+                                       mAlpha = -mAlpha;
+                                       mScale = -mScale;
+                                       break;
+                       }
                }
-
-               InterpolatorBase<T>::init(seconds, mode);
        }
 
+       Scalar                          mAlpha;
+       Scalar                          mScale;
+       Interp::Mode            mMode;
+       bool                            mIsDone;
 
-       void calculate(T& value, Scalar alpha)
-       {
-               Scalar beta = 1.0 - alpha;
-
-               value = coefficients_[0] * std::pow(beta, D);
-
-               for (int i = 1; i <= D; ++i)
-               {
-                       value += coefficients_[i] * std::pow(beta, D - i) *
-                               std::pow(alpha, i);
-               }
-       }
-
-private:
-       T coefficients_[D+1];
+       typename T::Type        mPrevState;
 };
 
 
-// specialized linear interpolator
-
-template <class T>
-class PolynomialInterpolator<1,T> : public InterpolatorBase<T>
+template <typename T = Scalar>
+class Linear
 {
 public:
-       PolynomialInterpolator() {}
 
-       PolynomialInterpolator(const T coefficients[2], Scalar seconds = 1.0,
-                       Interpolator::Mode mode = Interpolator::STOP)
-               //InterpolatorBase<T>(seconds, mode)
+       typedef T Type;
+
+       void init(const Type& a, const Type& b)
        {
-               init(coefficients, seconds, mode);
+               mStart = a;
+               mFinish = b;
        }
 
-       void init(const T coefficients[2], Scalar seconds = 1.0,
-                       Interpolator::Mode mode = Interpolator::STOP)
+       const Type& calculate(Scalar alpha)
        {
-               a_ = coefficients[0];
-               b_ = coefficients[1];
-
-               InterpolatorBase<T>::init(seconds, mode);
+               mState = cml::lerp(mStart, mFinish, alpha);
+               return mState;
        }
 
-
-       void calculate(T& value, Scalar alpha)
+       const Type& getValue() const
        {
-               value = cml::lerp(a_, b_, alpha);
+               return mState;
        }
 
 private:
-       T a_;
-       T b_;
-};
-
 
-// Here are some aliases for more common interpolators.  Also see the
-// interpolation functions in cml for other types of interpolation such as
-// slerp and some multi-alpha interpolators.
-
-typedef PolynomialInterpolator<1>                      Lerp;   // linear
-typedef PolynomialInterpolator<1,Vector2>      Lerp2;
-typedef PolynomialInterpolator<1,Vector3>      Lerp3;
-typedef PolynomialInterpolator<1,Vector4>      Lerp4;
+       Type    mState;
+       Type    mStart;
+       Type    mFinish;
+};
 
-typedef PolynomialInterpolator<2>                      Qerp;   // quadratic
-typedef PolynomialInterpolator<2,Vector2>      Qerp2;
-typedef PolynomialInterpolator<2,Vector3>      Qerp3;
-typedef PolynomialInterpolator<2,Vector4>      Qerp4;
 
-typedef PolynomialInterpolator<3>                      Cerp;   // cubic
-typedef PolynomialInterpolator<3,Vector2>      Cerp2;
-typedef PolynomialInterpolator<3,Vector3>      Cerp3;
-typedef PolynomialInterpolator<3,Vector4>      Cerp4;
+typedef Interpolator< Linear<Scalar> > Lerp;
 
 
 } // namespace Mf
This page took 0.023619 seconds and 4 git commands to generate.