Morph-SynRJ

view mth_hermite.h @ 0:22de913c2d84

morph-synrj intro
author "Cedric Pinson <cedric.pinson@alcove.fr> <mornifle@plopbyte.net>"
date Tue Nov 27 15:23:52 2007 +0100 (2007-11-27)
parents
children
line source
1 /** @file mth_hermite.h
2 *
3 * @brief hermite curve
4 *
5 *****************************************************************************
6 *
7 * @author psc80
8 *
9 * @date Created 2003/05 modified for sota intro
10 *
11 * @version $Id: mth_hermite.h,v 1.4 2004/01/22 13:23:37 psc80 Exp $
12 *
13 ****************************************************************************/
15 #ifndef MTH_HERMITE_H
16 #define MTH_HERMITE_H
18 #include "mth.h"
19 #include "sys_assert.h"
21 #define WITHOUT_EXTRADATA
23 namespace mth {
27 struct HermiteKey_t
28 {
29 typedef Vector3_t data_type;
30 typedef float param_type;
31 #ifndef WITHOUT_EXTRADATA
32 param_type tens;
33 param_type cont;
34 param_type bias;
35 #endif
36 param_type time;
38 data_type data;
44 /**
45 * Init internal parmaters
46 */
47 void Init() {
48 time=0;
49 #ifndef WITHOUT_EXTRADATA
50 tens=0;
51 cont=0;
52 bias=0;
53 #endif
54 }
56 /**
57 * Default Constructor
58 */
59 HermiteKey_t() {Init();}
63 void Init(const param_type& _time,
64 const data_type& _data
65 #ifndef WITHOUT_EXTRADATA
66 ,const param_type& _tens=(param_type)0,
67 const param_type& _cont=(param_type)0,
68 const param_type& _bias=(param_type)0
69 #endif
70 )
71 {
72 time=_time;
73 data=_data;
74 #ifndef WITHOUT_EXTRADATA
75 tens=_tens;
76 cont=_cont;
77 bias=_bias;
78 #endif
79 }
82 /**
83 * Accessors
84 */
85 const data_type& Data() const { return data;}
86 data_type& Data() { return data;}
88 };
95 /**
96 * General hermite curve.
97 */
98 class Hermite_t
99 {
100 typedef HermiteKey_t* T2ptr_t;
102 HermiteKey_t** keys;
103 int nbKeys;
105 // short cut of type
106 typedef HermiteKey_t::param_type param_key;
107 typedef HermiteKey_t::data_type data_key;
111 void BuildSi(int _prev,int _cur,int _next,data_key& _ts) {
113 SYS_ASSERT(_prev>=0 && _prev<nbKeys);
114 SYS_ASSERT(_cur >=0 && _cur <nbKeys);
115 SYS_ASSERT(_next>=0 && _next<nbKeys);
117 data_key tmp1=keys[_cur]->Data()-keys[_prev]->Data();
118 data_key tmp2=keys[_next]->Data()-keys[_cur]->Data();
120 const param_key one=1; //just to avoid big syntax
121 const param_key two=2; //just to avoid big syntax
122 const param_key half=0.5; //just to avoid big syntax
124 #ifndef WITHOUT_EXTRADATA
125 param_key pars3= one - keys[_cur]->tens;
126 param_key pars0= pars3 * ( one + keys[_cur]->bias )*( one - keys[_cur]->cont) * half;
127 param_key pars1= pars3 * ( one - keys[_cur]->bias )*( one + keys[_cur]->cont) * half;
128 #else
129 const param_key pars0=0.5;
130 const param_key pars1=0.5;
131 #endif
132 param_key curDeltaI=keys[_next]->time-keys[_cur]->time;
133 param_key prevDeltaI=keys[_cur]->time-keys[_prev]->time;
135 param_key delta=two * curDeltaI/(prevDeltaI+curDeltaI);
137 _ts=(tmp1*pars0+tmp2*pars1)*delta;
138 }
141 void BuildDi(int _prev,int _cur,int _next,data_key& _td) {
143 SYS_ASSERT(_prev>=0 && _prev<nbKeys);
144 SYS_ASSERT(_cur >=0 && _cur <nbKeys);
145 SYS_ASSERT(_next>=0 && _next<nbKeys);
147 data_key tmp1=keys[_cur]->Data()-keys[_prev]->Data();
148 data_key tmp2=keys[_next]->Data()-keys[_cur]->Data();
150 const param_key one=1; //just to avoid big syntax
151 const param_key two=2; //just to avoid big syntax
152 const param_key half=0.5; //just to avoid big syntax
154 #ifndef WITHOUT_EXTRADATA
155 param_key pars3= one - keys[_cur]->tens;
156 param_key pars0= pars3 * ( one + keys[_cur]->bias)*( one + keys[_cur]->cont) * half;
157 param_key pars1= pars3 * ( one - keys[_cur]->bias)*( one - keys[_cur]->cont) * half;
158 #else
159 const param_key pars0=0.5;
160 const param_key pars1=0.5;
162 #endif
163 param_key curDeltaI=keys[_next]->time-keys[_cur]->time;
164 param_key prevDeltaI=keys[_cur]->time-keys[_prev]->time;
166 param_key delta= two *prevDeltaI/(prevDeltaI+curDeltaI);
168 _td=(tmp1*pars0+tmp2*pars1)*delta;
169 }
173 const int MAX_KEYS;
175 public:
177 /**
178 * Default constructor
179 */
180 Hermite_t(int _size) : MAX_KEYS(_size) {
181 keys=new T2ptr_t[_size];
182 nbKeys=0;
183 }
185 ~Hermite_t() {
186 delete [] keys;
187 }
191 /**
192 * Clear the list of keyframes
193 */
194 void Clear() { nbKeys=0;}
196 /**
197 * Insert a key frame with this time in the spline.
198 * warning you can't insert more than one time an element
199 *
200 * @param mthHermiteKeyFrame_T* key to insert
201 * @return 0 if ok else -1
202 */
203 void AddKey(HermiteKey_t* _key) {
205 SYS_ASSERT(_key);
207 SYS_ASSERT(nbKeys<MAX_KEYS);
208 keys[nbKeys++]=_key;
209 }
212 /**
213 * GetData return a interpolated value from time given as parameter
214 * We use data type defined by keyframe
215 *
216 * @param mthHermiteKeyFrame_T::param_type time step you want
217 * @param mthHermiteKeyFrame_T::data_type& result of interpolation
218 * @param bool loop or not
219 * @return int 0 if ok else -1
220 */
221 int GetData(param_key _time,data_key& _result,bool _loop=1) {
223 if (!nbKeys)
224 return -1;
227 if (nbKeys<2) {
228 _result=keys[0]->Data();
229 return 0;
230 }
233 // cheking range
234 param_key limit_t0=keys[0]->time;
235 param_key limit_t1=keys[nbKeys-1]->time;
238 if (_loop) {
239 // loop mode
240 if (_time < limit_t0)
241 _time=limit_t0;
242 if (_time>limit_t1) {
243 param_key dist=limit_t1-limit_t0;
244 _time=_time/dist;
245 _time=Frac(_time)*dist;
246 }
248 } else {
249 // stop mode
250 if (_time < limit_t0)
251 _time=limit_t0;
253 if (_time>limit_t1)
254 _time=limit_t1;
255 }
258 int itPrev,itCur,itNext,itNext2;
259 itCur=0;
261 itCur++; //start at the second key
262 // give me the good interval p0---t------p1
263 while ( _time>keys[itCur]->time) {
264 itCur++;
265 }
266 itCur--;
268 // check valid prev and next
269 itPrev=itCur;
270 if (itCur!=0)
271 itPrev--;
273 itNext=itCur;
274 if (itCur!=nbKeys-1)
275 itNext++;
278 param_key t=(_time-keys[itCur]->time)/(keys[itNext]->time-keys[itCur]->time); // rescale the time
279 param_key t2=t*t;
280 param_key t3=t2*t;
282 param_key c2t3= t3 * (param_key)2;
283 param_key c3t2= t2 * (param_key)3;
285 // p=(2t3-3t2+1)*p0 + (t3-2t2+t)*tg0 + (-2t3+3t2)*p1 + (t3-t2)*tg1
286 param_key one=1;
287 param_key two=2;
288 param_key h1= c2t3 - c3t2 + one; // 2t3-3t2+1
289 param_key h2= t3 + t - t2 * two; // t3-2t2+t
290 param_key h3= -c2t3 + c3t2; // -2t3+3t2
291 param_key h4= t3 - t2; // t3-t2
293 data_key tg0,tg1;
295 BuildDi(itPrev,itCur,itNext,tg0);
298 itNext2=itNext;
299 if (itNext!=nbKeys-1)
300 itNext2++;
302 BuildSi(itCur,itNext,itNext2,tg1);
304 _result=keys[itCur]->Data()*h1+ tg0*h2 + keys[itNext]->Data()*h3+ tg1*h4;
305 return 0;
306 }
309 };
311 }
314 #undef WITHOUT_EXTRADATA
317 #endif