X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FInterpolator.hh;h=d918a8df1bea77a7c3c79d81a901901446157b45;hp=2c33844262db6835cc5eaf02258f09cf5d11d767;hb=837bae9f2bf7b25e1d3d2625eeaf39c1d2f48827;hpb=29e3d45f7bbbf31eadf793c41ff2b3d9c47b7539 diff --git a/src/Moof/Interpolator.hh b/src/Moof/Interpolator.hh index 2c33844..d918a8d 100644 --- a/src/Moof/Interpolator.hh +++ b/src/Moof/Interpolator.hh @@ -1,81 +1,26 @@ -/******************************************************************************* - - Copyright (c) 2009, Charles McGarvey - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*******************************************************************************/ +/*] Copyright (c) 2009-2010, Charles McGarvey [************************** +**] All rights reserved. +* +* vi:ts=4 sw=4 tw=75 +* +* Distributable under the terms and conditions of the 2-clause BSD license; +* see the file COPYING for a complete text of the license. +* +**************************************************************************/ #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,188 +28,131 @@ 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_; -}; + 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 BinomialInterpolator Lerps; // linear -typedef BinomialInterpolator Lerpv2; -typedef BinomialInterpolator Lerpv3; -typedef BinomialInterpolator Lerpv4; - -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 #endif // _MOOF_INTERPOLATOR_HH_ -/** vim: set ts=4 sw=4 tw=80: *************************************************/ -