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