X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FInterpolator.hh;h=e49ac694c2d0c3876c3b0028ca46e85e6131e462;hp=4de3f6974bd3a7ceeaf93945b9d7ca5323126c07;hb=4f9eb9259092994de9690cf12f11437c35a6791e;hpb=a4debfe4a5f5d339410788971b698ba00cb7f09c diff --git a/src/Moof/Interpolator.hh b/src/Moof/Interpolator.hh index 4de3f69..e49ac69 100644 --- a/src/Moof/Interpolator.hh +++ b/src/Moof/Interpolator.hh @@ -36,49 +36,8 @@ 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 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 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 -class PolynomialInterpolator : public InterpolatorBase -{ -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::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 PolynomialInterpolator<1,T> : public InterpolatorBase +template +class Linear { public: - PolynomialInterpolator() {} - PolynomialInterpolator(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 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 > Lerp; } // namespace Mf