You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
3.9 KiB
196 lines
3.9 KiB
//
|
|
// interpolator.h
|
|
// J
|
|
//
|
|
// Created by Joshua Moerman on 9/2/11.
|
|
// Copyright 2011 Vadovas. All rights reserved.
|
|
//
|
|
|
|
#ifndef J_interpolator_h
|
|
#define J_interpolator_h
|
|
|
|
#include <tr1/functional>
|
|
|
|
// NOTE: there is a specialisation for std::array
|
|
// But i'm not glad with how this is done...
|
|
|
|
namespace J {
|
|
|
|
namespace interpolators {
|
|
struct linear{
|
|
template <typename T>
|
|
T operator()(T x){
|
|
return x;
|
|
}
|
|
};
|
|
|
|
struct cubic_in_out{
|
|
template <typename T>
|
|
T operator()(T x){
|
|
return 3*x*x - 2*x*x*x;
|
|
}
|
|
};
|
|
|
|
struct quintic_in_out{
|
|
template <typename T>
|
|
T operator()(T x){
|
|
return 6*x*x*x*x*x - 15*x*x*x*x + 10*x*x*x;
|
|
return x*x*x*(x*(x*6-15)+10);
|
|
}
|
|
};
|
|
|
|
struct cosine_in_out{
|
|
template <typename T>
|
|
T operator()(T x){
|
|
return 0.5f - 0.5f*std::cos(x*M_PI);
|
|
}
|
|
};
|
|
}
|
|
|
|
template <typename T>
|
|
class interpolator {
|
|
|
|
std::tr1::function<T (T)> ease_function;
|
|
|
|
size_t length;
|
|
size_t steps;
|
|
|
|
T value;
|
|
T begin_value;
|
|
T 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 begin_value_, size_t length_, F ease_function_) :
|
|
ease_function(ease_function_)
|
|
, length(length_)
|
|
, steps(0)
|
|
, value(begin_value_)
|
|
, begin_value(begin_value_)
|
|
, end_value(begin_value_) {}
|
|
|
|
operator T const & () const{
|
|
return value;
|
|
}
|
|
|
|
T const & get_value() const{
|
|
return value;
|
|
}
|
|
|
|
void set_value(T 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]){
|
|
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 <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);
|
|
for (unsigned int i = 0; i < N; ++i) {
|
|
value[i] = (T(1) - ratio)*begin_value[i] + ratio*end_value[i];
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
} // namespace J
|
|
|
|
#endif
|
|
|