X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FInterpolator.hh;h=e49ac694c2d0c3876c3b0028ca46e85e6131e462;hp=2c33844262db6835cc5eaf02258f09cf5d11d767;hb=4f9eb9259092994de9690cf12f11437c35a6791e;hpb=29e3d45f7bbbf31eadf793c41ff2b3d9c47b7539 diff --git a/src/Moof/Interpolator.hh b/src/Moof/Interpolator.hh index 2c33844..e49ac69 100644 --- a/src/Moof/Interpolator.hh +++ b/src/Moof/Interpolator.hh @@ -29,53 +29,15 @@ #ifndef _MOOF_INTERPOLATOR_HH_ #define _MOOF_INTERPOLATOR_HH_ +#include #include 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, @@ -83,183 +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; - stopped_ = false; - } - - - 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 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 - previous_ = value_; - } - - 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 BinomialInterpolator : public InterpolatorBase -{ -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::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 BinomialInterpolator : public InterpolatorBase +template +class Linear { public: - BinomialInterpolator() {} - explicit BinomialInterpolator(const T coefficients[2], Scalar seconds = 1.0, - Interpolator::Mode mode = Interpolator::STOP) - //InterpolatorBase(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::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 Lerps; // linear -typedef BinomialInterpolator Lerpv2; -typedef BinomialInterpolator Lerpv3; -typedef BinomialInterpolator Lerpv4; + Type mState; + Type mStart; + Type mFinish; +}; -typedef BinomialInterpolator Qerps; // quadratic -typedef BinomialInterpolator Qerpv2; -typedef BinomialInterpolator Qerpv3; -typedef BinomialInterpolator Qerpv4; -typedef BinomialInterpolator Cerps; // cubic -typedef BinomialInterpolator Cerpv2; -typedef BinomialInterpolator Cerpv3; -typedef BinomialInterpolator Cerpv4; +typedef Interpolator< Linear > Lerp; } // namespace Mf