]> Dogcows Code - chaz/yoink/blob - src/Moof/Interpolator.hh
new level-based controllers
[chaz/yoink] / src / Moof / Interpolator.hh
1
2 /*******************************************************************************
3
4 Copyright (c) 2009, Charles McGarvey
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 *******************************************************************************/
28
29 #ifndef _MOOF_INTERPOLATOR_HH_
30 #define _MOOF_INTERPOLATOR_HH_
31
32 #include <Moof/Math.hh>
33
34
35 namespace Mf {
36
37
38 // TODO - cleanup these classes
39
40 class Interpolator
41 {
42 void clamp(Scalar& value)
43 {
44 if (value > 1.0)
45 {
46 switch (mode_)
47 {
48 case STOP:
49 value = 1.0;
50 stopped_ = true;
51 break;
52 case REPEAT:
53 value -= 1.0;
54 break;
55 case OSCILLATE:
56 value = 2.0 - value;
57 scale_ *= -1.0;
58 break;
59 }
60 }
61 else if (value < 0.0)
62 {
63 switch (mode_)
64 {
65 case STOP:
66 value = 0.0;
67 stopped_ = true;
68 break;
69 case REPEAT:
70 value += 1.0;
71 break;
72 case OSCILLATE:
73 value = -value;
74 scale_ *= -1.0;
75 break;
76 }
77 }
78 }
79
80 public:
81 typedef enum
82 {
83 STOP = 0,
84 REPEAT = 1,
85 OSCILLATE = 2
86 } Mode;
87
88 void init(Scalar seconds = 1.0, Mode mode = STOP)
89 {
90 scale_ = 1.0 / seconds;
91 alpha_ = 0.0;
92 setMode(mode);
93 }
94
95
96 void setMode(Mode mode)
97 {
98 mode_ = mode;
99 stopped_ = false;
100 }
101
102
103 void update(Scalar dt)
104 {
105 if (!stopped_)
106 {
107 alpha_ += dt * scale_;
108 clamp(alpha_);
109 calculate(alpha_);
110 }
111 }
112
113 virtual void calculate(Scalar alpha) = 0;
114
115 private:
116 Scalar alpha_;
117 Mode mode_;
118 Scalar scale_;
119 bool stopped_;
120 };
121
122 template <class T = Scalar>
123 class InterpolatorBase : public Interpolator
124 {
125 public:
126 void init(Scalar seconds = 1.0, Mode mode = STOP)
127 {
128 Interpolator::init(seconds, mode);
129
130 calculate(0.0); // set value
131 previous_ = value_;
132 }
133
134 void calculate(Scalar alpha)
135 {
136 previous_ = value_;
137 calculate(value_, alpha);
138 }
139
140 virtual void calculate(T& value, Scalar alpha) = 0;
141
142 const T& getValue() const
143 {
144 return value_;
145 }
146
147 const T getState(Scalar alpha) const
148 {
149 return cml::lerp(previous_, value_, alpha);
150 }
151
152 private:
153 T value_;
154 T previous_;
155 };
156
157
158 template <int D, class T = Scalar>
159 class PolynomialInterpolator : public InterpolatorBase<T>
160 {
161 public:
162 PolynomialInterpolator() {}
163
164 PolynomialInterpolator(const T coefficients[D+1],
165 Scalar seconds = 1.0, Interpolator::Mode mode = Interpolator::STOP)
166 {
167 init(coefficients, seconds, mode);
168 }
169
170 void init(const T coefficients[D+1], Scalar seconds = 1.0,
171 Interpolator::Mode mode = Interpolator::STOP)
172 {
173 Scalar fac[D+1];
174
175 fac[0] = 1.0;
176 fac[1] = 1.0;
177
178 // build an array of the computed factorials we will need
179 for (int i = 2; i <= D; ++i)
180 {
181 fac[i] = i * fac[i - 1];
182 }
183
184 // combine the coefficients for fast updating
185 for (int i = 0; i <= D; ++i)
186 {
187 // n! / (k! * (n - k)!)
188 coefficients_[i] = coefficients[i] * fac[D] / (fac[i] * fac[D - i]);
189 }
190
191 InterpolatorBase<T>::init(seconds, mode);
192 }
193
194
195 void calculate(T& value, Scalar alpha)
196 {
197 Scalar beta = 1.0 - alpha;
198
199 value = coefficients_[0] * std::pow(beta, D);
200
201 for (int i = 1; i <= D; ++i)
202 {
203 value += coefficients_[i] * std::pow(beta, D - i) *
204 std::pow(alpha, i);
205 }
206 }
207
208 private:
209 T coefficients_[D+1];
210 };
211
212
213 // specialized linear interpolator
214
215 template <class T>
216 class PolynomialInterpolator<1,T> : public InterpolatorBase<T>
217 {
218 public:
219 PolynomialInterpolator() {}
220
221 PolynomialInterpolator(const T coefficients[2], Scalar seconds = 1.0,
222 Interpolator::Mode mode = Interpolator::STOP)
223 //InterpolatorBase<T>(seconds, mode)
224 {
225 init(coefficients, seconds, mode);
226 }
227
228 void init(const T coefficients[2], Scalar seconds = 1.0,
229 Interpolator::Mode mode = Interpolator::STOP)
230 {
231 a_ = coefficients[0];
232 b_ = coefficients[1];
233
234 InterpolatorBase<T>::init(seconds, mode);
235 }
236
237
238 void calculate(T& value, Scalar alpha)
239 {
240 value = cml::lerp(a_, b_, alpha);
241 }
242
243 private:
244 T a_;
245 T b_;
246 };
247
248
249 // Here are some aliases for more common interpolators. Also see the
250 // interpolation functions in cml for other types of interpolation such as
251 // slerp and some multi-alpha interpolators.
252
253 typedef PolynomialInterpolator<1> Lerp; // linear
254 typedef PolynomialInterpolator<1,Vector2> Lerp2;
255 typedef PolynomialInterpolator<1,Vector3> Lerp3;
256 typedef PolynomialInterpolator<1,Vector4> Lerp4;
257
258 typedef PolynomialInterpolator<2> Qerp; // quadratic
259 typedef PolynomialInterpolator<2,Vector2> Qerp2;
260 typedef PolynomialInterpolator<2,Vector3> Qerp3;
261 typedef PolynomialInterpolator<2,Vector4> Qerp4;
262
263 typedef PolynomialInterpolator<3> Cerp; // cubic
264 typedef PolynomialInterpolator<3,Vector2> Cerp2;
265 typedef PolynomialInterpolator<3,Vector3> Cerp3;
266 typedef PolynomialInterpolator<3,Vector4> Cerp4;
267
268
269 } // namespace Mf
270
271 #endif // _MOOF_INTERPOLATOR_HH_
272
273 /** vim: set ts=4 sw=4 tw=80: *************************************************/
274
This page took 0.041522 seconds and 5 git commands to generate.