X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FInterpolator.hh;h=e49ac694c2d0c3876c3b0028ca46e85e6131e462;hp=5c9f09788172cb62fd21f03ff4fc748b76b7498e;hb=4f9eb9259092994de9690cf12f11437c35a6791e;hpb=7f3984f3f9524f5b6813e01ceb2fe576dadff94e diff --git a/src/Moof/Interpolator.hh b/src/Moof/Interpolator.hh index 5c9f097..e49ac69 100644 --- a/src/Moof/Interpolator.hh +++ b/src/Moof/Interpolator.hh @@ -36,51 +36,7 @@ namespace Mf { -// TODO - cleanup these classes - -class Interpolator -{ - void clamp(Scalar& value) - { - if (value > 1.0) - { - switch (mMode) - { - case STOP: - value = 1.0; - mDone = true; - break; - case REPEAT: - value -= 1.0; - break; - case OSCILLATE: - value = 2.0 - value; - mScale *= -1.0; - break; - } - } - else if (value < 0.0) - { - switch (mMode) - { - case STOP: - value = 0.0; - mDone = true; - break; - case REPEAT: - value += 1.0; - break; - case OSCILLATE: - value = -value; - mScale *= -1.0; - break; - } - } - } - -public: - - virtual ~Interpolator() {} +namespace Interp { typedef enum { @@ -89,199 +45,128 @@ public: OSCILLATE = 2 } Mode; - void init(Scalar seconds = 1.0, Mode mode = STOP) +} // namespace Interp + + +template +class Interpolator : public T +{ +public: + + Interpolator(Scalar t = 1.0, Interp::Mode mode = Interp::STOP) { - mScale = 1.0 / seconds; - mAlpha = 0.0; - setMode(mode); + reset(t, mode); } - - void setMode(Mode mode) + void reset(Scalar t = 1.0, Interp::Mode mode = Interp::STOP) { + mAlpha = 0.0; + mScale = 1.0 / t; mMode = mode; - mDone = false; + mIsDone = false; } - void update(Scalar t, Scalar dt) { - if (!mDone) + if (!mIsDone) { + mPrevState = T::getValue(); mAlpha += dt * mScale; - clamp(mAlpha); - calculate(mAlpha); + clamp(); + if (mPrevState == T::calculate(mAlpha)) mIsDone = true; } } - bool isDone() const - { - return mDone; - } - - virtual void calculate(Scalar alpha) = 0; - -private: - - Scalar mAlpha; - Mode mMode; - Scalar mScale; - bool mDone; -}; - -template -class InterpolatorBase : public Interpolator -{ -public: - - virtual ~InterpolatorBase() {} - - void init(Scalar seconds = 1.0, Mode mode = STOP) + typename T::Type getState(Scalar alpha) const { - Interpolator::init(seconds, mode); - - calculate(0.0); // set value - mPrevious = mValue; + return cml::lerp(mPrevState, T::getValue(), alpha); } - void calculate(Scalar alpha) - { - mPrevious = mValue; - calculate(mValue, alpha); - } - - virtual void calculate(T& value, Scalar alpha) = 0; - - const T& getValue() const - { - return mValue; - } - - const T getState(Scalar alpha) const + bool isDone() const { - return cml::lerp(mPrevious, mValue, alpha); + return mIsDone; } private: - T mValue; - T mPrevious; -}; - - -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]; - } - - // combine the coefficients for fast updating - for (int i = 0; i <= D; ++i) - { - // n! / (k! * (n - k)!) - mCoefficients[i] = coefficients[i] * fac[D] / (fac[i] * fac[D - i]); + 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; + } } - - InterpolatorBase::init(seconds, mode); - } - - - void calculate(T& value, Scalar alpha) - { - Scalar beta = 1.0 - alpha; - - value = mCoefficients[0] * std::pow(beta, D); - - for (int i = 1; i <= D; ++i) + else if (mAlpha < 0.0) { - value += mCoefficients[i] * std::pow(beta, D - i) * - std::pow(alpha, 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; + } } } -private: + Scalar mAlpha; + Scalar mScale; + Interp::Mode mMode; + bool mIsDone; - T mCoefficients[D+1]; + typename T::Type mPrevState; }; -// specialized linear interpolator - -template -class PolynomialInterpolator<1,T> : public InterpolatorBase +template +class Linear { public: - PolynomialInterpolator() {} + typedef T Type; - PolynomialInterpolator(const T coefficients[2], Scalar seconds = 1.0, - Interpolator::Mode mode = Interpolator::STOP) - //InterpolatorBase(seconds, mode) + 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) { - mA = coefficients[0]; - mB = 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(mA, mB, alpha); + return mState; } private: - T mA; - T mB; + Type mState; + Type mStart; + Type mFinish; }; -// 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; - -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