TuttleOFX
1
|
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