]> Dogcows Code - chaz/yoink/blob - src/Moof/Interpolator.hh
4de3f6974bd3a7ceeaf93945b9d7ca5323126c07
[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/Log.hh>
33 #include <Moof/Math.hh>
34
35
36 namespace Mf {
37
38
39 // TODO - cleanup these classes
40
41 class Interpolator
42 {
43 void clamp(Scalar& value)
44 {
45 if (value > 1.0)
46 {
47 switch (mode_)
48 {
49 case STOP:
50 value = 1.0;
51 done_ = true;
52 break;
53 case REPEAT:
54 value -= 1.0;
55 break;
56 case OSCILLATE:
57 value = 2.0 - value;
58 scale_ *= -1.0;
59 break;
60 }
61 }
62 else if (value < 0.0)
63 {
64 switch (mode_)
65 {
66 case STOP:
67 value = 0.0;
68 done_ = true;
69 break;
70 case REPEAT:
71 value += 1.0;
72 break;
73 case OSCILLATE:
74 value = -value;
75 scale_ *= -1.0;
76 break;
77 }
78 }
79 }
80
81 public:
82 typedef enum
83 {
84 STOP = 0,
85 REPEAT = 1,
86 OSCILLATE = 2
87 } Mode;
88
89 void init(Scalar seconds = 1.0, Mode mode = STOP)
90 {
91 scale_ = 1.0 / seconds;
92 alpha_ = 0.0;
93 setMode(mode);
94 }
95
96
97 void setMode(Mode mode)
98 {
99 mode_ = mode;
100 done_ = false;
101 }
102
103
104 void update(Scalar t, Scalar dt)
105 {
106 if (!done_)
107 {
108 alpha_ += dt * scale_;
109 clamp(alpha_);
110 calculate(alpha_);
111 }
112 }
113
114 bool isDone() const
115 {
116 return done_;
117 }
118
119 virtual void calculate(Scalar alpha) = 0;
120
121 private:
122
123 Scalar alpha_;
124 Mode mode_;
125 Scalar scale_;
126 bool done_;
127 };
128
129 template <class T = Scalar>
130 class InterpolatorBase : public Interpolator
131 {
132 public:
133 void init(Scalar seconds = 1.0, Mode mode = STOP)
134 {
135 Interpolator::init(seconds, mode);
136
137 calculate(0.0); // set value
138 previous_ = value_;
139 }
140
141 void calculate(Scalar alpha)
142 {
143 previous_ = value_;
144 calculate(value_, alpha);
145 }
146
147 virtual void calculate(T& value, Scalar alpha) = 0;
148
149 const T& getValue() const
150 {
151 return value_;
152 }
153
154 const T getState(Scalar alpha) const
155 {
156 return cml::lerp(previous_, value_, alpha);
157 }
158
159 private:
160 T value_;
161 T previous_;
162 };
163
164
165 template <int D, class T = Scalar>
166 class PolynomialInterpolator : public InterpolatorBase<T>
167 {
168 public:
169 PolynomialInterpolator() {}
170
171 PolynomialInterpolator(const T coefficients[D+1],
172 Scalar seconds = 1.0, Interpolator::Mode mode = Interpolator::STOP)
173 {
174 init(coefficients, seconds, mode);
175 }
176
177 void init(const T coefficients[D+1], Scalar seconds = 1.0,
178 Interpolator::Mode mode = Interpolator::STOP)
179 {
180 Scalar fac[D+1];
181
182 fac[0] = 1.0;
183 fac[1] = 1.0;
184
185 // build an array of the computed factorials we will need
186 for (int i = 2; i <= D; ++i)
187 {
188 fac[i] = i * fac[i - 1];
189 }
190
191 // combine the coefficients for fast updating
192 for (int i = 0; i <= D; ++i)
193 {
194 // n! / (k! * (n - k)!)
195 coefficients_[i] = coefficients[i] * fac[D] / (fac[i] * fac[D - i]);
196 }
197
198 InterpolatorBase<T>::init(seconds, mode);
199 }
200
201
202 void calculate(T& value, Scalar alpha)
203 {
204 Scalar beta = 1.0 - alpha;
205
206 value = coefficients_[0] * std::pow(beta, D);
207
208 for (int i = 1; i <= D; ++i)
209 {
210 value += coefficients_[i] * std::pow(beta, D - i) *
211 std::pow(alpha, i);
212 }
213 }
214
215 private:
216 T coefficients_[D+1];
217 };
218
219
220 // specialized linear interpolator
221
222 template <class T>
223 class PolynomialInterpolator<1,T> : public InterpolatorBase<T>
224 {
225 public:
226 PolynomialInterpolator() {}
227
228 PolynomialInterpolator(const T coefficients[2], Scalar seconds = 1.0,
229 Interpolator::Mode mode = Interpolator::STOP)
230 //InterpolatorBase<T>(seconds, mode)
231 {
232 init(coefficients, seconds, mode);
233 }
234
235 void init(const T coefficients[2], Scalar seconds = 1.0,
236 Interpolator::Mode mode = Interpolator::STOP)
237 {
238 a_ = coefficients[0];
239 b_ = coefficients[1];
240
241 InterpolatorBase<T>::init(seconds, mode);
242 }
243
244
245 void calculate(T& value, Scalar alpha)
246 {
247 value = cml::lerp(a_, b_, alpha);
248 }
249
250 private:
251 T a_;
252 T b_;
253 };
254
255
256 // Here are some aliases for more common interpolators. Also see the
257 // interpolation functions in cml for other types of interpolation such as
258 // slerp and some multi-alpha interpolators.
259
260 typedef PolynomialInterpolator<1> Lerp; // linear
261 typedef PolynomialInterpolator<1,Vector2> Lerp2;
262 typedef PolynomialInterpolator<1,Vector3> Lerp3;
263 typedef PolynomialInterpolator<1,Vector4> Lerp4;
264
265 typedef PolynomialInterpolator<2> Qerp; // quadratic
266 typedef PolynomialInterpolator<2,Vector2> Qerp2;
267 typedef PolynomialInterpolator<2,Vector3> Qerp3;
268 typedef PolynomialInterpolator<2,Vector4> Qerp4;
269
270 typedef PolynomialInterpolator<3> Cerp; // cubic
271 typedef PolynomialInterpolator<3,Vector2> Cerp2;
272 typedef PolynomialInterpolator<3,Vector3> Cerp3;
273 typedef PolynomialInterpolator<3,Vector4> Cerp4;
274
275
276 } // namespace Mf
277
278 #endif // _MOOF_INTERPOLATOR_HH_
279
280 /** vim: set ts=4 sw=4 tw=80: *************************************************/
281
This page took 0.038685 seconds and 3 git commands to generate.