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