diff --git a/J/interpolator.h b/J/interpolator.h index f6a6003..b0735e2 100644 --- a/J/interpolator.h +++ b/J/interpolator.h @@ -11,10 +11,40 @@ #include -// NOTE: there is a specialisation for std::array -// But i'm not glad with how this is done... - namespace J { + +namespace interpolator_details { + // some templates to handle arrays... + template + void interpolate(Scalar const & ratio, T & value, T const & begin_value, T const & end_value){ + value = (Scalar(1.0) - ratio)*begin_value + ratio*end_value; + } + template + void interpolate(Scalar const & ratio, T (& value)[N], T const (& begin_value)[N], T const (& end_value)[N]){ + for (unsigned int i = 0; i < N; ++i) + value[i] = (Scalar(1.0) - ratio)*begin_value[i] + ratio*end_value[i]; + } + template + void interpolate(Scalar const & ratio, std::array & value, std::array const & begin_value, std::array const & end_value){ + for (unsigned int i = 0; i < N; ++i) + value[i] = (Scalar(1.0) - ratio)*begin_value[i] + ratio*end_value[i]; + } + + template + struct scalar_of { + // TODO: find out how to make it work for user-types + // maybe require T::Scalar + typedef T type; + }; + template + struct scalar_of { + typedef typename scalar_of::type type; + }; + template + struct scalar_of > { + typedef typename scalar_of::type type; + }; +} namespace interpolators { struct linear{ @@ -49,8 +79,10 @@ namespace interpolators { template class interpolator { + typedef typename interpolator_details::scalar_of::type Scalar; + typedef std::tr1::function EaseFunction; - std::tr1::function ease_function; + EaseFunction ease_function; size_t length; size_t steps; @@ -62,7 +94,7 @@ class interpolator { public: template - interpolator(S begin_value_, size_t length_ = 100) : + interpolator(S const & begin_value_, size_t length_ = 30) : ease_function(interpolators::cubic_in_out()) , length(length_) , steps(length_) @@ -71,7 +103,7 @@ public: , end_value(begin_value_) {} template - interpolator(S begin_value_, size_t length_, F ease_function_) : + interpolator(S const & begin_value_, size_t length_, F const & ease_function_) : ease_function(ease_function_) , length(length_) , steps(0) @@ -87,110 +119,42 @@ public: return value; } - void set_value(T new_value){ + void set_value(T const & new_value){ begin_value = value; end_value = new_value; steps = 0; } + // FIXME: temporary hack + template + void set_value(Scalar const (& new_value)[N]){ + begin_value = value; + for(unsigned int i = 0; i < N; ++i) + end_value[i] = new_value[i]; + steps = 0; + } + void set_length(size_t new_length){ - T ratio = (T) steps / (T) length; + Scalar ratio = (Scalar) steps / (Scalar) length; length = new_length; steps = ratio*length; } template - void set_ease_function(F new_ease_function){ + void set_ease_function(F const & new_ease_function){ ease_function = new_ease_function; } void interpolate(){ if(steps >= length) return; ++steps; - T ratio = (T) steps / (T) length; + Scalar ratio = (Scalar) steps / (Scalar) length; ratio = ease_function(ratio); - value = (T(1) - ratio)*begin_value + ratio*end_value; + interpolator_details::interpolate(ratio, value, begin_value, end_value); } }; - -template - class interpolator > { - - std::tr1::function ease_function; - - size_t length; - size_t steps; - - std::array value; - std::array begin_value; - std::array end_value; - -public: - - template - interpolator(S begin_value_, size_t length_ = 100) : - ease_function(interpolators::cubic_in_out()) - , length(length_) - , steps(length_) - , value(begin_value_) - , begin_value(begin_value_) - , end_value(begin_value_) {} - - template - interpolator(S const & begin_value_, size_t length_, F const & ease_function_) : - ease_function(ease_function_) - , length(length_) - , steps(0) - , value(begin_value_) - , begin_value(begin_value_) - , end_value(begin_value_) {} - - std::array const & get_value() const{ - return value; - } - - operator std::array const & () const{ - return value; - } - - void set_value(std::array const & new_value){ - begin_value = value; - end_value = new_value; - steps = 0; - } - void set_value(T const (& new_value)[N]){ - begin_value = value; - for (unsigned int i = 0; i < N; ++i) { - end_value[i] = new_value[i]; - } - steps = 0; - } - - void set_length(size_t new_length){ - T ratio = (T) steps / (T) length; - length = new_length; - steps = ratio*length; - } - - template - void set_ease_function(F new_ease_function){ - ease_function = new_ease_function; - } - - void interpolate(){ - if(steps >= length) return; - ++steps; - T ratio = (T) steps / (T) length; - ratio = ease_function(ratio); - for (unsigned int i = 0; i < N; ++i) { - value[i] = (T(1) - ratio)*begin_value[i] + ratio*end_value[i]; - } - } - -}; - } // namespace J #endif