|
|
@ -6,6 +6,57 @@ |
|
|
|
// Copyright 2011 Vadovas. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
/*
|
|
|
|
The interpolator interpolates between the current value and the value to interpolate to, both values are stored in the interpolator object. For easing there are different functors given (in the namespace interpolators: linear, cubic_in_out, quintic_in_out, cosine_in_out), but using a custom ease function is also possible (as long as it is convertible to std::function, see below for the type). |
|
|
|
|
|
|
|
The constructor takes three values: the first is the begin_value (usually 0), the second is the length of interpolation time, the last is the ease function. The interpolation time and the ease function can be changed later with the corresponding setters. |
|
|
|
|
|
|
|
The interpolated value can be retrieved with .get_value(), setting a new value to interpolate to is done via .set_value(new_value). Updating the time is done with .interpolate(dt). |
|
|
|
|
|
|
|
For example (interpolating a float from 0 to 10 in 5 seconds, with easing): |
|
|
|
// creation:
|
|
|
|
interpolator<float> my_value (0.0, 5.0, interpolators::cosine_in_out); |
|
|
|
my_value.set_value(10.0); |
|
|
|
|
|
|
|
// in update function:
|
|
|
|
my_value.interpolate(dt); |
|
|
|
do_magic(my_value.get_value()); |
|
|
|
|
|
|
|
It can also be used with c-style arrays and std::array's. This can be usefull for interpolating matrices or colours and such. |
|
|
|
|
|
|
|
Templates and types: |
|
|
|
interpolator<T, Time> |
|
|
|
T indicates the type of the value (for example: float, float[16], std::array<float, 16>) |
|
|
|
Time indicates the type of the time-steps, you can use int if the system is frame-based (default: float) |
|
|
|
|
|
|
|
ease_function has type std::function<S(S)> where S is the element-type of T, this means: |
|
|
|
If T = float (or any other single value) -> S = float |
|
|
|
If T = float[4] (or std::array) -> S = float |
|
|
|
In other cases (eg. custom types) it will probably not work. |
|
|
|
|
|
|
|
Synopsis: |
|
|
|
template <typename T, typename Time> |
|
|
|
class interpolator { |
|
|
|
// ctor
|
|
|
|
template <typename S, typename F> |
|
|
|
interpolator(S const & begin_value_, Time const & length_, F const & ease_function_ = interpolators::cubic_in_out()); |
|
|
|
|
|
|
|
// time-update:
|
|
|
|
void interpolate(Time const & dt = 1) |
|
|
|
|
|
|
|
// getters
|
|
|
|
operator T const & () const; |
|
|
|
T const & get_value() const; |
|
|
|
|
|
|
|
// setters
|
|
|
|
void set_value(T const & new_value); |
|
|
|
void set_length(Time new_length); |
|
|
|
|
|
|
|
template <typename F> |
|
|
|
void set_ease_function(F const & new_ease_function); |
|
|
|
}; |
|
|
|
*/ |
|
|
|
|
|
|
|
#ifndef J_interpolator_h |
|
|
|
#define J_interpolator_h |
|
|
|
|
|
|
@ -22,12 +73,12 @@ namespace interpolator_details { |
|
|
|
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]; |
|
|
|
interpolate(ratio, value[i], begin_value[i], 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]; |
|
|
|
interpolate(ratio, value[i], begin_value[i], end_value[i]); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename T> |
|
|
@ -77,39 +128,44 @@ namespace interpolators { |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
template <typename T> |
|
|
|
template <typename T, typename Time = float> |
|
|
|
class interpolator { |
|
|
|
typedef typename interpolator_details::scalar_of<T>::type Scalar; |
|
|
|
typedef std::tr1::function<Scalar (Scalar)> EaseFunction; |
|
|
|
|
|
|
|
EaseFunction ease_function; |
|
|
|
|
|
|
|
size_t length; |
|
|
|
size_t steps; |
|
|
|
Time length; |
|
|
|
Time steps; |
|
|
|
|
|
|
|
T value; |
|
|
|
T begin_value; |
|
|
|
T end_value; |
|
|
|
|
|
|
|
bool done; |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
template <typename S> |
|
|
|
interpolator(S const & begin_value_, size_t length_ = 30) : |
|
|
|
interpolator(S const & begin_value_, Time const & length_) : |
|
|
|
ease_function(interpolators::cubic_in_out()) |
|
|
|
, length(length_) |
|
|
|
, steps(length_) |
|
|
|
, value(begin_value_) |
|
|
|
, begin_value(begin_value_) |
|
|
|
, end_value(begin_value_) {} |
|
|
|
, end_value(begin_value_) |
|
|
|
, done(false) {} |
|
|
|
|
|
|
|
// NOTE: we can't use template-defaults in functions, so we have to make an overload for this one...
|
|
|
|
template <typename S, typename F> |
|
|
|
interpolator(S const & begin_value_, size_t length_, F const & ease_function_) : |
|
|
|
interpolator(S const & begin_value_, Time const & length_, F const & ease_function_) : |
|
|
|
ease_function(ease_function_) |
|
|
|
, length(length_) |
|
|
|
, steps(0) |
|
|
|
, value(begin_value_) |
|
|
|
, begin_value(begin_value_) |
|
|
|
, end_value(begin_value_) {} |
|
|
|
, end_value(begin_value_) |
|
|
|
, done(false) {} |
|
|
|
|
|
|
|
operator T const & () const{ |
|
|
|
return value; |
|
|
@ -123,6 +179,7 @@ public: |
|
|
|
begin_value = value; |
|
|
|
end_value = new_value; |
|
|
|
steps = 0; |
|
|
|
done = false; |
|
|
|
} |
|
|
|
|
|
|
|
// FIXME: temporary hack
|
|
|
@ -132,12 +189,14 @@ public: |
|
|
|
for(unsigned int i = 0; i < N; ++i) |
|
|
|
end_value[i] = new_value[i]; |
|
|
|
steps = 0; |
|
|
|
done = false; |
|
|
|
} |
|
|
|
|
|
|
|
void set_length(size_t new_length){ |
|
|
|
void set_length(Time new_length){ |
|
|
|
Scalar ratio = (Scalar) steps / (Scalar) length; |
|
|
|
length = new_length; |
|
|
|
steps = ratio*length; |
|
|
|
done = false; |
|
|
|
} |
|
|
|
|
|
|
|
template <typename F> |
|
|
@ -145,9 +204,13 @@ public: |
|
|
|
ease_function = new_ease_function; |
|
|
|
} |
|
|
|
|
|
|
|
void interpolate(){ |
|
|
|
if(steps >= length) return; |
|
|
|
++steps; |
|
|
|
void interpolate(Time const & dt = 1){ |
|
|
|
if(done) return; |
|
|
|
steps += dt; |
|
|
|
if(steps >= length){ |
|
|
|
steps = length; |
|
|
|
done = true; |
|
|
|
} |
|
|
|
Scalar ratio = (Scalar) steps / (Scalar) length; |
|
|
|
ratio = ease_function(ratio); |
|
|
|
interpolator_details::interpolate(ratio, value, begin_value, end_value); |
|
|
|