]> Dogcows Code - chaz/yoink/blob - src/interpolator.hh
beginnings of scene rendering
[chaz/yoink] / src / 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 _INTERPOLATOR_HH_
30 #define _INTERPOLATOR_HH_
31
32
33 namespace dc {
34
35
36 class interpolator
37 {
38 void clamp(scalar& value)
39 {
40 if (value > 1.0)
41 {
42 switch (theMode)
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 (theMode)
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 onFinish = stop)
85 {
86 scale = 1.0 / seconds;
87 alpha = 0.0;
88 setMode(onFinish);
89 }
90
91
92 void setMode(mode onFinish)
93 {
94 theMode = onFinish;
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 mode theMode;
113 scalar alpha;
114 scalar scale;
115 bool stopped;
116 };
117
118 template <class T>
119 class interpolator_base : public interpolator
120 {
121 public:
122 void init(scalar seconds = 1.0, mode onFinish = stop)
123 {
124 interpolator::init(seconds, onFinish);
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 binomial_interpolator : public interpolator_base<T>
156 {
157 public:
158 binomial_interpolator() {}
159
160 explicit binomial_interpolator(const T coeff[D+1], scalar seconds = 1.0,
161 interpolator::mode onFinish = interpolator::stop)
162 {
163 init(coeff, seconds, onFinish);
164 }
165
166 void init(const T coeff[D+1], scalar seconds = 1.0,
167 interpolator::mode onFinish = 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 coefficient[i] = coeff[i] * fac[D] / (fac[i] * fac[D - i]);
185 }
186
187 interpolator_base<T>::init(seconds, onFinish);
188 }
189
190
191 void calculate(T& value, scalar alpha)
192 {
193 scalar beta = 1.0 - alpha;
194
195 value = coefficient[0] * std::pow(beta, D);
196
197 for (int i = 1; i <= D; i++)
198 {
199 value += coefficient[i] * std::pow(beta, D - i) * std::pow(alpha, i);
200 }
201 }
202
203 private:
204
205 T coefficient[D+1];
206 };
207
208
209 template <class T>
210 class binomial_interpolator<T,1> : public interpolator_base<T>
211 {
212 public:
213 binomial_interpolator() {}
214
215 explicit binomial_interpolator(const T coeff[2], scalar seconds = 1.0,
216 interpolator::mode onFinish = interpolator::stop)
217 //interpolator_base<T>(seconds, onFinish)
218 {
219 init(coeff, seconds, onFinish);
220 }
221
222 void init(const T coeff[2], scalar seconds = 1.0,
223 interpolator::mode onFinish = interpolator::stop)
224 {
225 coefficient[0] = coeff[0];
226 coefficient[1] = coeff[1];
227
228 interpolator_base<T>::init(seconds, onFinish);
229 }
230
231
232 void calculate(T& value, scalar alpha)
233 {
234 value = cml::lerp(coefficient[0], coefficient[1], alpha);
235 }
236
237 private:
238 T coefficient[2];
239 };
240
241
242 // Here are some aliases for more common interpolators. Also see the
243 // interpolation functions in cml for other types of interpolation such as
244 // slerp and some multi-alpha interpolators.
245
246 typedef binomial_interpolator<scalar, 1> lerps; // linear
247 typedef binomial_interpolator<vector2,1> lerpv2;
248 typedef binomial_interpolator<vector3,1> lerpv3;
249 typedef binomial_interpolator<vector4,1> lerpv4;
250
251 typedef binomial_interpolator<scalar ,2> qerps; // quadratic
252 typedef binomial_interpolator<vector2,2> qerpv2;
253 typedef binomial_interpolator<vector3,2> qerpv3;
254 typedef binomial_interpolator<vector4,2> qerpv4;
255
256 typedef binomial_interpolator<scalar ,3> cerps; // cubic
257 typedef binomial_interpolator<vector2,3> cerpv2;
258 typedef binomial_interpolator<vector3,3> cerpv3;
259 typedef binomial_interpolator<vector4,3> cerpv4;
260
261
262 } // namespace dc
263
264 #endif // _INTERPOLATOR_HH_
265
266 /** vim: set ts=4 sw=4 tw=80: *************************************************/
267
This page took 0.046795 seconds and 4 git commands to generate.