Browse Source

added documentation to interpolator

master
Joshua Moerman 13 years ago
parent
commit
32d5b348bc
  1. 23
      J/J.m
  2. 89
      J/interpolator.h

23
J/J.m

@ -1,23 +0,0 @@
//
// J.m
// J
//
// Created by Joshua Moerman on 8/28/11.
// Copyright 2011 Vadovas. All rights reserved.
//
#import "J.h"
@implementation J
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
@end

89
J/interpolator.h

@ -6,6 +6,57 @@
// Copyright 2011 Vadovas. All rights reserved. // 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 #ifndef J_interpolator_h
#define J_interpolator_h #define J_interpolator_h
@ -22,12 +73,12 @@ namespace interpolator_details {
template <typename Scalar, typename T, size_t N> 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]){ 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) 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> 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){ 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) 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> template <typename T>
@ -77,39 +128,44 @@ namespace interpolators {
}; };
} }
template <typename T> template <typename T, typename Time = float>
class interpolator { class interpolator {
typedef typename interpolator_details::scalar_of<T>::type Scalar; typedef typename interpolator_details::scalar_of<T>::type Scalar;
typedef std::tr1::function<Scalar (Scalar)> EaseFunction; typedef std::tr1::function<Scalar (Scalar)> EaseFunction;
EaseFunction ease_function; EaseFunction ease_function;
size_t length; Time length;
size_t steps; Time steps;
T value; T value;
T begin_value; T begin_value;
T end_value; T end_value;
bool done;
public: public:
template <typename S> 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()) ease_function(interpolators::cubic_in_out())
, length(length_) , length(length_)
, steps(length_) , steps(length_)
, value(begin_value_) , value(begin_value_)
, begin_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> 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_) ease_function(ease_function_)
, length(length_) , length(length_)
, steps(0) , steps(0)
, value(begin_value_) , value(begin_value_)
, begin_value(begin_value_) , begin_value(begin_value_)
, end_value(begin_value_) {} , end_value(begin_value_)
, done(false) {}
operator T const & () const{ operator T const & () const{
return value; return value;
@ -123,6 +179,7 @@ public:
begin_value = value; begin_value = value;
end_value = new_value; end_value = new_value;
steps = 0; steps = 0;
done = false;
} }
// FIXME: temporary hack // FIXME: temporary hack
@ -132,12 +189,14 @@ public:
for(unsigned int i = 0; i < N; ++i) for(unsigned int i = 0; i < N; ++i)
end_value[i] = new_value[i]; end_value[i] = new_value[i];
steps = 0; steps = 0;
done = false;
} }
void set_length(size_t new_length){ void set_length(Time new_length){
Scalar ratio = (Scalar) steps / (Scalar) length; Scalar ratio = (Scalar) steps / (Scalar) length;
length = new_length; length = new_length;
steps = ratio*length; steps = ratio*length;
done = false;
} }
template <typename F> template <typename F>
@ -145,9 +204,13 @@ public:
ease_function = new_ease_function; ease_function = new_ease_function;
} }
void interpolate(){ void interpolate(Time const & dt = 1){
if(steps >= length) return; if(done) return;
++steps; steps += dt;
if(steps >= length){
steps = length;
done = true;
}
Scalar ratio = (Scalar) steps / (Scalar) length; Scalar ratio = (Scalar) steps / (Scalar) length;
ratio = ease_function(ratio); ratio = ease_function(ratio);
interpolator_details::interpolate(ratio, value, begin_value, end_value); interpolator_details::interpolate(ratio, value, begin_value, end_value);