|
|
@ -11,11 +11,41 @@ |
|
|
|
|
|
|
|
#include <tr1/functional> |
|
|
|
|
|
|
|
// 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 <typename Scalar, typename T> |
|
|
|
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 <typename Scalar, typename T, size_t N> |
|
|
|
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 <typename Scalar, typename T, size_t N> |
|
|
|
void interpolate(Scalar const & ratio, std::array<T, N> & value, std::array<T, N> const & begin_value, std::array<T, N> 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 <typename T> |
|
|
|
struct scalar_of { |
|
|
|
// TODO: find out how to make it work for user-types
|
|
|
|
// maybe require T::Scalar
|
|
|
|
typedef T type; |
|
|
|
}; |
|
|
|
template <typename T, size_t N> |
|
|
|
struct scalar_of<T[N]> { |
|
|
|
typedef typename scalar_of<T>::type type; |
|
|
|
}; |
|
|
|
template <typename T, size_t N> |
|
|
|
struct scalar_of<std::array<T, N> > { |
|
|
|
typedef typename scalar_of<T>::type type; |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
namespace interpolators { |
|
|
|
struct linear{ |
|
|
|
template <typename T> |
|
|
@ -49,8 +79,10 @@ namespace interpolators { |
|
|
|
|
|
|
|
template <typename T> |
|
|
|
class interpolator { |
|
|
|
typedef typename interpolator_details::scalar_of<T>::type Scalar; |
|
|
|
typedef std::tr1::function<Scalar (Scalar)> EaseFunction; |
|
|
|
|
|
|
|
std::tr1::function<T (T)> ease_function; |
|
|
|
EaseFunction ease_function; |
|
|
|
|
|
|
|
size_t length; |
|
|
|
size_t steps; |
|
|
@ -62,7 +94,7 @@ class interpolator { |
|
|
|
public: |
|
|
|
|
|
|
|
template <typename S> |
|
|
|
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 <typename S, typename F> |
|
|
|
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,106 +119,38 @@ 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; |
|
|
|
} |
|
|
|
|
|
|
|
void set_length(size_t new_length){ |
|
|
|
T ratio = (T) steps / (T) length; |
|
|
|
length = new_length; |
|
|
|
steps = ratio*length; |
|
|
|
} |
|
|
|
|
|
|
|
template <typename F> |
|
|
|
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); |
|
|
|
value = (T(1) - ratio)*begin_value + ratio*end_value; |
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
template <typename T, size_t N> |
|
|
|
class interpolator<std::array<T, N> > { |
|
|
|
|
|
|
|
std::tr1::function<T (T)> ease_function; |
|
|
|
|
|
|
|
size_t length; |
|
|
|
size_t steps; |
|
|
|
|
|
|
|
std::array<T, N> value; |
|
|
|
std::array<T, N> begin_value; |
|
|
|
std::array<T, N> end_value; |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
template <typename S> |
|
|
|
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 <typename S, typename F> |
|
|
|
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<T, N> const & get_value() const{ |
|
|
|
return value; |
|
|
|
} |
|
|
|
|
|
|
|
operator std::array<T, N> const & () const{ |
|
|
|
return value; |
|
|
|
} |
|
|
|
|
|
|
|
void set_value(std::array<T, N> const & new_value){ |
|
|
|
begin_value = value; |
|
|
|
end_value = new_value; |
|
|
|
steps = 0; |
|
|
|
} |
|
|
|
|
|
|
|
void set_value(T const (& new_value)[N]){ |
|
|
|
// FIXME: temporary hack
|
|
|
|
template <size_t N> |
|
|
|
void set_value(Scalar const (& new_value)[N]){ |
|
|
|
begin_value = value; |
|
|
|
for (unsigned int i = 0; i < N; ++i) { |
|
|
|
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 <typename F> |
|
|
|
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); |
|
|
|
for (unsigned int i = 0; i < N; ++i) { |
|
|
|
value[i] = (T(1) - ratio)*begin_value[i] + ratio*end_value[i]; |
|
|
|
} |
|
|
|
interpolator_details::interpolate(ratio, value, begin_value, end_value); |
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|