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