#ifndef _MOOF_INTERPOLATOR_HH_
#define _MOOF_INTERPOLATOR_HH_
+#include <Moof/Log.hh>
+#include <Moof/Math.hh>
+
namespace Mf {
-class Interpolator
-{
- void clamp(Scalar& value)
- {
- if (value > 1.0)
- {
- switch (mode_)
- {
- case STOP:
- value = 1.0;
- stopped_ = 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;
- stopped_ = true;
- break;
- case REPEAT:
- value += 1.0;
- break;
- case OSCILLATE:
- value = -value;
- scale_ *= -1.0;
- break;
- }
- }
- }
+namespace Interp {
-public:
typedef enum
{
STOP = 0,
OSCILLATE = 2
} Mode;
- void init(Scalar seconds = 1.0, Mode mode = STOP)
- {
- scale_ = 1.0 / seconds;
- alpha_ = 0.0;
- setMode(mode);
- }
-
-
- void setMode(Mode mode)
- {
- mode_ = mode;
- stopped_ = false;
- }
+} // namespace Interp
- void update(Scalar dt)
- {
- if (!stopped_)
- {
- alpha_ += dt * scale_;
- clamp(alpha_);
- calculate(alpha_);
- }
- }
-
- virtual void calculate(Scalar alpha) = 0;
-
-private:
- Scalar alpha_;
- Mode mode_;
- Scalar scale_;
- bool stopped_;
-};
-
template <class T>
-class InterpolatorBase : public Interpolator
+class Interpolator : public T
{
public:
- void init(Scalar seconds = 1.0, Mode mode = STOP)
- {
- Interpolator::init(seconds, mode);
- calculate(0.0); // set value
- calculate(0.0); // set previous
- }
-
- void calculate(Scalar alpha)
+ Interpolator(Scalar t = 1.0, Interp::Mode mode = Interp::STOP)
{
- previous_ = value_;
- calculate(value_, alpha);
+ reset(t, mode);
}
- virtual void calculate(T& value, Scalar alpha) = 0;
-
- const T& getValue()
+ void reset(Scalar t = 1.0, Interp::Mode mode = Interp::STOP)
{
- return value_;
+ mAlpha = 0.0;
+ mScale = 1.0 / t;
+ mMode = mode;
+ mIsDone = false;
}
- const T getState(Scalar alpha)
+ void update(Scalar t, Scalar dt)
{
- return cml::lerp(previous_, value_, alpha);
+ if (!mIsDone)
+ {
+ mPrevState = T::getValue();
+ mAlpha += dt * mScale;
+ clamp();
+ if (mPrevState == T::calculate(mAlpha)) mIsDone = true;
+ }
}
-private:
- T value_;
- T previous_;
-};
-
-
-template <class T, int D>
-class BinomialInterpolator : public InterpolatorBase<T>
-{
-public:
- BinomialInterpolator() {}
-
- explicit BinomialInterpolator(const T coefficients[D+1],
- Scalar seconds = 1.0, Interpolator::Mode mode = Interpolator::STOP)
+ typename T::Type getState(Scalar alpha) const
{
- init(coefficients, seconds, mode);
+ return cml::lerp(mPrevState, T::getValue(), alpha);
}
- void init(const T coefficients[D+1], Scalar seconds = 1.0,
- Interpolator::Mode mode = Interpolator::STOP)
+ bool isDone() const
{
- Scalar fac[D+1];
+ return mIsDone;
+ }
- fac[0] = 1.0;
- fac[1] = 1.0;
+private:
- // build an array of the computed factorials we will need
- for (int i = 2; i <= D; i++)
+ void clamp()
+ {
+ 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;
};
-template <class T>
-class BinomialInterpolator<T,1> : public InterpolatorBase<T>
+template <typename T = Scalar>
+class Linear
{
public:
- BinomialInterpolator() {}
- explicit BinomialInterpolator(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 BinomialInterpolator<Scalar, 1> Lerps; // linear
-typedef BinomialInterpolator<Vector2,1> Lerpv2;
-typedef BinomialInterpolator<Vector3,1> Lerpv3;
-typedef BinomialInterpolator<Vector4,1> Lerpv4;
+ Type mState;
+ Type mStart;
+ Type mFinish;
+};
-typedef BinomialInterpolator<Scalar ,2> Qerps; // quadratic
-typedef BinomialInterpolator<Vector2,2> Qerpv2;
-typedef BinomialInterpolator<Vector3,2> Qerpv3;
-typedef BinomialInterpolator<Vector4,2> Qerpv4;
-typedef BinomialInterpolator<Scalar ,3> Cerps; // cubic
-typedef BinomialInterpolator<Vector2,3> Cerpv2;
-typedef BinomialInterpolator<Vector3,3> Cerpv3;
-typedef BinomialInterpolator<Vector4,3> Cerpv4;
+typedef Interpolator< Linear<Scalar> > Lerp;
} // namespace Mf