1 /*
2 ======================================================================
3 interp.c
4
5 Interpolation (and extrapolation) of LightWave envelopes.
6
7 Ernie Wright 16 Nov 00
8
9 The LightWave plug-in SDK provides functions for evaluating envelopes
10 and channels at arbitrary times, which is what plug-ins should use.
11 This code shows how to evaluate envelopes in standalone programs.
12 ====================================================================== */
13
14 #include "xr_envelope.h"
15 #include "xr_math.h"
16
17 using namespace xray_re;
18
range(float v,float lo,float hi,int * i=0)19 static float range(float v, float lo, float hi, int* i = 0)
20 {
21 float r = hi - lo;
22 if (r == 0) {
23 if (i)
24 *i = 0;
25 return lo;
26 }
27 float v2 = lo + v - r*std::floor((v - lo)/r);
28 if (i)
29 *i = -(int)((v2 - v)/r + (v2 > v ? 0.5 : -0.5));
30 return v2;
31 }
32
hermite(float t,float * h1,float * h2,float * h3,float * h4)33 static void hermite(float t, float* h1, float* h2, float* h3, float* h4)
34 {
35 float t2 = t*t, t3 = t2*t;
36 *h2 = 3.f*t2 - t3 - t3;
37 *h1 = 1.f - *h2;
38 *h4 = t3 - t2;
39 *h3 = *h4 - t2 + t;
40 }
41
bezier(float x0,float x1,float x2,float x3,float t)42 static float bezier(float x0, float x1, float x2, float x3, float t)
43 {
44 float t2 = t*t, t3 = t2*t;
45
46 float c = 3.f*(x1 - x0);
47 float b = 3.f*(x2 - x1) - c;
48 float a = x3 - x0 - c - b;
49
50 return a*t3 + b*t2 + c*t + x0;
51 }
52
bez2_time(float x0,float x1,float x2,float x3,float time,float * t0,float * t1)53 static float bez2_time(float x0, float x1, float x2, float x3, float time,
54 float* t0, float* t1)
55 {
56 float t = *t0 + (*t1 - *t0)*0.5f;
57 float v = bezier(x0, x1, x2, x3, t);
58 if (std::abs(time - v) > 1e-4f) {
59 if (v > time)
60 *t1 = t;
61 else
62 *t0 = t;
63 return bez2_time(x0, x1, x2, x3, time, t0, t1);
64 } else {
65 return t;
66 }
67 }
68
bez2(const xr_key * key0,const xr_key * key1,float time)69 static float bez2(const xr_key* key0, const xr_key* key1, float time)
70 {
71 float x = (key0->shape == xr_key::SHAPE_BEZ2) ?
72 key0->time + key0->param[2] :
73 key0->time + (key1->time - key0->time)/3.f;
74 float t0 = 0.f, t1 = 1.f;
75 float t = bez2_time(key0->time, x, key1->time + key1->param[0], key1->time, time, &t0, &t1);
76
77 float y = (key0->shape == xr_key::SHAPE_BEZ2) ?
78 key0->value + key0->param[3] :
79 key0->value + key0->param[1]/3.f;
80 return bezier(key0->value, y, key1->param[1] + key1->value, key1->value, t);
81 }
82
outgoing(const xr_key * key0_prev,const xr_key * key0,const xr_key * key1)83 static float outgoing(const xr_key* key0_prev, const xr_key* key0, const xr_key* key1)
84 {
85 float a, b, d, t, out;
86 switch (key0->shape) {
87 case xr_key::SHAPE_TCB:
88 a = (1.f - key0->tension)*(1.f + key0->continuity)*(1.f + key0->bias);
89 b = (1.f - key0->tension)*(1.f - key0->continuity)*(1.f - key0->bias);
90 d = key1->value - key0->value;
91 if (key0_prev) {
92 t = (key1->time - key0->time)/(key1->time - key0_prev->time);
93 out = t*(a*(key0->value - key0_prev->value) + b*d);
94 } else {
95 out = b*d;
96 }
97 break;
98
99 case xr_key::SHAPE_LINE:
100 d = key1->value - key0->value;
101 if (key0_prev) {
102 t = (key1->time - key0->time)/(key1->time - key0_prev->time);
103 out = t*(key0->value - key0_prev->value + d);
104 } else {
105 out = d;
106 }
107 break;
108
109 case xr_key::SHAPE_BEZI:
110 case xr_key::SHAPE_HERM:
111 out = key0->param[1];
112 if (key0_prev)
113 out *= (key1->time - key0->time)/(key1->time - key0_prev->time);
114 break;
115
116 case xr_key::SHAPE_BEZ2:
117 out = key0->param[3]*(key1->time - key0->time);
118 if (std::abs(key0->param[2]) > 1e-5f)
119 out /= key0->param[2];
120 else
121 out *= 1e+5f;
122 break;
123
124 case xr_key::SHAPE_STEP:
125 default:
126 out = 0.f;
127 break;
128 }
129 return out;
130 }
131
incoming(const xr_key * key0,const xr_key * key1,const xr_key * key1_next)132 static float incoming(const xr_key* key0, const xr_key* key1, const xr_key* key1_next)
133 {
134 float a, b, d, t, in;
135 switch (key1->shape) {
136 case xr_key::SHAPE_LINE:
137 d = key1->value - key0->value;
138 if (key1_next) {
139 t = (key1->time - key0->time)/(key1_next->time - key0->time);
140 in = t*(key1_next->value - key1->value + d);
141 } else {
142 in = d;
143 }
144 break;
145
146 case xr_key::SHAPE_TCB:
147 a = (1.f - key1->tension)*(1.f - key1->continuity)*(1.f + key1->bias);
148 b = (1.f - key1->tension)*(1.f + key1->continuity)*(1.f - key1->bias);
149 d = key1->value - key0->value;
150 if (key1_next) {
151 t = (key1->time - key0->time)/(key1_next->time - key0->time);
152 in = t*(b*(key1_next->value - key1->value) + a*d);
153 } else {
154 in = a*d;
155 }
156 break;
157
158 case xr_key::SHAPE_BEZI:
159 case xr_key::SHAPE_HERM:
160 in = key1->param[0];
161 if (key1_next)
162 in *= (key1->time - key0->time)/(key1_next->time - key0->time);
163 break;
164
165 case xr_key::SHAPE_BEZ2:
166 in = key1->param[1]*(key1->time - key0->time);
167 if (std::abs(key1->param[0]) > 1e-5f)
168 in /= key1->param[0];
169 else
170 in *= 1e+5f;
171 break;
172
173 case xr_key::SHAPE_STEP:
174 default:
175 in = 0.f;
176 break;
177 }
178 return in;
179 }
180
evaluate(float time) const181 float xr_envelope::evaluate(float time) const
182 {
183 if (m_keys.empty())
184 return 0.f;
185
186 if (m_keys.size() == 1)
187 return m_keys.front()->value;
188
189 int noff;
190 float offset = 0;
191
192 xr_key* skey = m_keys.front();
193 xr_key* ekey = m_keys.back();
194 if (time < skey->time) {
195 switch (m_behaviour0) {
196 case BEH_RESET:
197 return 0.f;
198
199 case BEH_CONSTANT:
200 return skey->value;
201
202 case BEH_REPEAT:
203 time = range(time, skey->time, ekey->time);
204 break;
205
206 case BEH_OSCILLATE:
207 time = range(time, skey->time, ekey->time, &noff);
208 if (noff % 2)
209 time = ekey->time - skey->time - time;
210 break;
211
212 case BEH_OFFSET:
213 time = range(time, skey->time, ekey->time, &noff);
214 offset = noff*(ekey->value - skey->value);
215 break;
216
217 case BEH_LINEAR: {
218 xr_key* next = m_keys[1];
219 return outgoing(0, skey, next)/(next->time - skey->time)*(time - skey->time) + skey->value;
220 }
221 }
222 } else if (ekey->time < time) {
223 switch (m_behaviour1) {
224 case BEH_RESET:
225 return 0.f;
226
227 case BEH_CONSTANT:
228 return ekey->value;
229
230 case BEH_REPEAT:
231 time = range(time, skey->time, ekey->time);
232 break;
233
234 case BEH_OSCILLATE:
235 time = range(time, skey->time, ekey->time, &noff);
236 if (noff % 2)
237 time = ekey->time - skey->time - time;
238 break;
239
240 case BEH_OFFSET:
241 time = range(time, skey->time, ekey->time, &noff);
242 offset = noff*(ekey->value - skey->value);
243 break;
244
245 case BEH_LINEAR: {
246 xr_key* prev = *(m_keys.end() - 2);
247 return incoming(prev, ekey, 0)/(ekey->time - prev->time)*(time - ekey->time) + ekey->value;
248 }
249 }
250 }
251
252 xr_key_vec_cit it = m_keys.begin() + 1;
253 // FIXME: use bisection
254 while ((*it)->time < time)
255 ++it;
256 xr_key* key0 = *(it - 1);
257 xr_key* key1 = *it;
258
259 if (time == key0->time)
260 return key0->value + offset;
261 else if (time == key1->time)
262 return key1->value + offset;
263
264 float t = (time - key0->time)/(key1->time - key0->time);
265
266 switch (key1->shape) {
267 case xr_key::SHAPE_TCB:
268 case xr_key::SHAPE_BEZI:
269 case xr_key::SHAPE_HERM: {
270 float out = outgoing(key0 == skey ? 0 : *(it - 2), key0, key1);
271 float in = incoming(key0, key1, key1 == ekey ? 0 : *(it + 1));
272 float h1, h2, h3, h4;
273 hermite(t, &h1, &h2, &h3, &h4);
274 return h1*key0->value + h2*key1->value + h3*out + h4*in + offset;
275 }
276 case xr_key::SHAPE_BEZ2:
277 return bez2(key0, key1, time) + offset;
278
279 case xr_key::SHAPE_LINE:
280 return key0->value + t*(key1->value - key0->value) + offset;
281
282 case xr_key::SHAPE_STEP:
283 return key0->value + offset;
284
285 default:
286 return offset;
287 }
288 }
289