TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/host/attribute/ValueInterpolator.hpp
Go to the documentation of this file.
00001 #ifndef VALUE_INTERPOLATOR_HPP
00002 #define VALUE_INTERPOLATOR_HPP
00003 
00004 /* Helper classes for animated parameters */
00005 
00006 #include <ofxCore.h>
00007 
00008 namespace tuttle {
00009 namespace host {
00010 namespace attribute {
00011 
00012 /* A "key frame" for an animated param */
00013 template<typename T>
00014 class TimeValue
00015 {
00016 public:
00017         OfxTime time;
00018         T value;
00019 
00020         bool operator<( const TimeValue<T> &t ) const
00021         {
00022                 return time < t.time;
00023         }
00024 
00025         bool operator==( const TimeValue<T> &t ) const
00026         {
00027                 return time == t.time;
00028         }
00029 };
00030 
00031 /* An Interpolator determines the shape of the curve between key frames in an animation */
00032 template<typename T>
00033 class Interpolator
00034 {
00035         typedef Interpolator<T> This;
00036         typedef TimeValue<T> TimeValueT;
00037 
00038 public:
00039         virtual ~Interpolator( ) = 0;
00040 
00041     virtual This* clone() const = 0;
00042         
00043         /* Given two key frames and a time between them, get the appropriate value for that time */
00044         virtual OfxStatus getValue( const TimeValueT& prev, const TimeValueT& next, const OfxTime t, T& v ) = 0;
00045 };
00046 
00047 template<typename T>
00048 Interpolator<T>::~Interpolator( ) { }
00049 
00050 /* Reduces interpolation to a value between 0 and 1 */
00051 
00052 /* Extend with a custom interpolate() function to provide different behaviors.*/
00053 template<typename T>
00054 class GenericInterpolator : public Interpolator<T>
00055 {
00056         typedef TimeValue<T> TimeValueT;
00057 
00058 public:
00059         virtual ~GenericInterpolator( ) = 0;
00060 
00061         OfxStatus getValue( const TimeValueT& prev, const TimeValueT& next, const OfxTime t, T& v )
00062         {
00063 
00064                 /* If the time is before the first key frame or both key frames are the same,
00065                    use the first key frame's value */
00066                 if( t <= prev.time || prev.time == next.time )
00067                 {
00068                         v = prev.value;
00069 
00070                         /* If the time is after the last keyframe, use the last keyframe's value */
00071                 }
00072                 else if( t >= next.time )
00073                 {
00074                         v = next.value;
00075 
00076                         /* If the time is between the two values, interpolate */
00077                 }
00078                 else
00079                 {
00080                         v = ( T ) ( prev.value + ( next.value - prev.value ) * interpolate( (double) ( t - prev.time ) / (double) ( next.time - prev.time ) ) );
00081                 }
00082                 return kOfxStatOK;
00083         }
00084 
00085 protected:
00086         /* given a position on the timeline between 0.0 and 1.0 return the
00087            interpolated value. */
00088         virtual double interpolate( const double pos ) const = 0;
00089 };
00090 
00091 template<typename T>
00092 GenericInterpolator<T>::~GenericInterpolator( ) { }
00093 
00094 /* No smoothing */
00095 template<typename T>
00096 class LinearInterpolator : public GenericInterpolator<T>
00097 {
00098 public:
00099         typedef LinearInterpolator<T> This;
00100     This* clone() const { return new This(*this); };
00101 
00102 protected:
00103         double interpolate( const double pos ) const
00104         {
00105                 return pos;
00106         }
00107 };
00108 
00109 /* Ease in and ease out */
00110 template<typename T>
00111 class SmoothInterpolator : public GenericInterpolator<T>
00112 {
00113 public:
00114         typedef SmoothInterpolator<T> This;
00115     This* clone() const { return new This(*this); };
00116 
00117 protected:
00118         double interpolate( const double pos ) const
00119         {
00120                 return -2 * pos * pos * pos + 3 * pos*pos;
00121         }
00122 };
00123 
00124 /* Ease out */
00125 template<typename T>
00126 class FastInterpolator : public GenericInterpolator<T>
00127 {
00128 public:
00129         typedef FastInterpolator<T> This;
00130     This* clone() const { return new This(*this); };
00131 
00132 protected:
00133         double interpolate( const double pos ) const
00134         {
00135                 return -1 * pos * pos + 2 * pos;
00136         }
00137 };
00138 
00139 /* Ease in */
00140 template<typename T>
00141 class SlowInterpolator : public GenericInterpolator<T>
00142 {
00143 public:
00144         typedef SlowInterpolator<T> This;
00145     This* clone() const { return new This(*this); };
00146 
00147 protected:
00148         double interpolate( const double pos ) const
00149         {
00150                 return pos*pos;
00151         }
00152 };
00153 
00154 }
00155 }
00156 }
00157 
00158 #endif
00159