/*] 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 { namespace Interp { typedef enum { STOP = 0, REPEAT = 1, OSCILLATE = 2 } Mode; } // namespace Interp template class Interpolator : public T { public: Interpolator(Scalar t = 1.0, Interp::Mode mode = Interp::STOP) { reset(t, mode); } void reset(Scalar t = 1.0, Interp::Mode mode = Interp::STOP) { mAlpha = 0.0; mScale = 1.0 / t; mMode = mode; mIsDone = false; } void update(Scalar t, Scalar dt) { if (!mIsDone) { mPrevState = T::getValue(); mAlpha += dt * mScale; clamp(); if (mPrevState == T::calculate(mAlpha)) mIsDone = true; } } typename T::Type getState(Scalar alpha) const { return cml::lerp(mPrevState, T::getValue(), alpha); } bool isDone() const { return mIsDone; } private: void clamp() { if (mAlpha > 1.0) { 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; } } else if (mAlpha < 0.0) { 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; } } } Scalar mAlpha; Scalar mScale; Interp::Mode mMode; bool mIsDone; typename T::Type mPrevState; }; template class Linear { public: typedef T Type; void init(const Type& a, const Type& b) { mStart = a; mFinish = b; } const Type& calculate(Scalar alpha) { mState = cml::lerp(mStart, mFinish, alpha); return mState; } const Type& getValue() const { return mState; } private: Type mState; Type mStart; Type mFinish; }; typedef Interpolator< Linear > Lerp; } // namespace Mf #endif // _MOOF_INTERPOLATOR_HH_