Interpolator.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. static Flt InterpolatorFrac(Flt frac)
  6. {
  7. // allow prediction for frac 1..2
  8. #if 0 // linear
  9. if(frac>2) // but when frac goes beyond that
  10. {
  11. #if 1 // then go back to last known position in frac 2..3
  12. frac=((frac>=3) ? 1 : 2*2-frac); // go back
  13. #else
  14. frac=2; // limit prediction
  15. #endif
  16. }
  17. #else // quadratic
  18. if(frac>1) // convert frac from 1 .. 2 .. 3 to: 1 .. 1.5 .. 1 using quadratic function
  19. {
  20. // x-x*x/2, where x=frac-1
  21. //frac=frac-1 - (frac-1)*(frac-1)/2+1;
  22. //frac=frac - (frac*frac + 1 - 2*frac)/2;
  23. frac=((frac>=3) ? 1 : -0.5f*frac*frac + 2*frac - 0.5f); // -0.5*x*x + 2*x - 0.5
  24. }
  25. #endif
  26. return frac;
  27. }
  28. InterpolatorTime& InterpolatorTime::reset()
  29. {
  30. _elms=_count=0;
  31. _time=_cur_duration=_next_duration=0;
  32. _left=FLT_MAX;
  33. return T;
  34. }
  35. void InterpolatorTime::add(Flt duration, InterpolatorTemp &temp)
  36. {
  37. // check this first
  38. //if(_elms>=2) check not needed since in worst case the value will be negative and ignored
  39. {
  40. Flt left=_next_duration+_cur_duration-_time-Time.rd(); // calculate how much time we had left without this call
  41. MIN(_left, left); // minimize time left
  42. _count=Min(_count+1, 255); // increase counter
  43. }
  44. switch(_elms)
  45. {
  46. case 0: _elms=1; temp.op=0; break; // we now have 'prev'
  47. case 1: _elms=2; _time=0; _cur_duration=duration; temp.op=1; break; // we now have 'prev'+'cur', we can start interpolation, so reset time
  48. case 2:
  49. {
  50. if(_time>_cur_duration) // check if we're currently predicting (we don't have 'next' and we've exceeded 'cur')
  51. {
  52. _time=0; _cur_duration=duration; temp.op=2; // reset time progress
  53. }else
  54. {
  55. _elms=3; _next_duration=duration; temp.op=3;
  56. }
  57. }break;
  58. case 3: _next_duration+=duration; temp.op=3; break;
  59. }
  60. }
  61. void InterpolatorTime::update(InterpolatorTemp &temp)
  62. {
  63. temp.op=0;
  64. _time+=Time.rd();
  65. if(_elms==3 && _time>_cur_duration)
  66. {
  67. temp.op=1;
  68. _elms =2;
  69. _time-=_cur_duration;
  70. _cur_duration=_next_duration; _next_duration=0;
  71. if(_count>=4) // higher number increases smoothness, but is slower to respond to network delays
  72. {
  73. _count=0;
  74. if(_left>0) // if we're too slow, then speedup
  75. {
  76. Flt time=_cur_duration-_time; // actual time left
  77. if( time>0)
  78. {
  79. Flt target=Max(0, time-_left), // desired time left
  80. mul=target/time; // scale factor
  81. _time*=mul;
  82. _cur_duration*=mul;
  83. }
  84. }
  85. _left=FLT_MAX;
  86. }
  87. }
  88. // do this last
  89. temp.frac=(_cur_duration ? InterpolatorFrac(_time/_cur_duration) : 0);
  90. }
  91. /******************************************************************************
  92. struct HistoryInterpolator2
  93. {
  94. // get
  95. Vec2 operator()()C;
  96. // operations
  97. void add(C Vec2 &value, Flt duration);
  98. void update();
  99. HistoryInterpolator2();
  100. #if !EE_PRIVATE
  101. private:
  102. #endif
  103. struct Elm
  104. {
  105. Vec2 value;
  106. Flt duration;
  107. };
  108. Byte _elms, _count;
  109. Flt _time, _left; _left could be encoded in history[0].time or use separate InterpolatorTime?
  110. Elm _history[3];
  111. };
  112. /******************************************************************************
  113. HistoryInterpolator2::HistoryInterpolator2()
  114. {
  115. _elms=_count=0;
  116. _time=0;
  117. _left=FLT_MAX;
  118. REPA(_history)
  119. {
  120. _history[i].value.zero();
  121. _history[i].duration=0;
  122. }
  123. }
  124. Vec2 HistoryInterpolator2::operator()()C
  125. {
  126. if(_elms<=1)return _history[0].value;
  127. Flt frac=InterpolatorFrac(_time/_history[1].duration); // fraction between #0 and #1
  128. return Lerp(_history[0].value, _history[1].value, frac);
  129. }
  130. void HistoryInterpolator2::add(C Vec2 &value, Flt duration)
  131. {
  132. // check this first
  133. //if(_elms>=2) check not needed since in worst case the value will be negative and ignored
  134. {
  135. Flt left=-_time-Time.rd(); for(Int i=_elms-1; i>=1; i--)left+=_history[i].duration; // calculate how much time we had left without this call
  136. MIN(_left, left); // minimize time left
  137. _count=Min(_count+1, 255); // increase counter
  138. }
  139. constexpr Int total=ELMS(_history);
  140. if(_elms>=total)
  141. {
  142. // find element with shortest duration (the most insignificant)
  143. Int i=2; // start from elm #2 to leave those currently used for interpolation intact
  144. Int shortest=i; // assume the first is the shortest
  145. Flt shortest_duration=_history[shortest].duration; // remember shortest duration
  146. for(; ++i<total; )
  147. {
  148. Flt d=_history[i].duration;
  149. if(d<shortest_duration)
  150. {
  151. shortest_duration=d;
  152. shortest=i;
  153. }
  154. }
  155. if(InRange(shortest+1, total)) // if next one is in the history
  156. {
  157. MoveFastN(&_history[shortest], &_history[shortest+1], total-shortest-1); // remove the shortest from history
  158. _history[shortest].duration+=shortest_duration; // increase duration of the next one
  159. }else duration+=shortest_duration; // next one is the new one
  160. _elms--;
  161. }else
  162. if(_elms==1)_time=0;else
  163. if(1 // this code makes adjustment to prevent jumps, if we're predicting, then it will adjust the history, so instead of jumping, we will interpolate from current (predicted) position into the new one
  164. && _elms==2 && _time>_history[1].duration) // check if we're currently predicting
  165. {
  166. #if 1 // if we're too fast then we have to slow down
  167. _history[0].value=T(); // start interpolating from current position
  168. _time=0; // reset time progress
  169. _elms--;
  170. #else
  171. // adjust old history so after adding new value, the interpolated one will be the same as now
  172. Vec2 current=T(); // calculate current position
  173. _time-=_history[1].duration;
  174. //_elms =2; is already 2
  175. _history[1].value =value;
  176. _history[1].duration=duration;
  177. Flt frac=T.frac();
  178. // now we have to make sure that T()==current
  179. // Lerp(_history[0].value, _history[1].value, frac)==current
  180. // _history[0].value*(1-frac) + _history[1].value*frac == current
  181. // _history[0].value*(1-frac) == current - _history[1].value*frac
  182. // _history[0].value == (current - _history[1].value*frac) / (1-frac)
  183. if(Flt div=1-frac)_history[0].value=(current-_history[1].value*frac)/div; // if frac!=1
  184. else _history[0].value=value; // frac==1
  185. #if 0
  186. #pragma message("!! Warning: Use this only for debugging !!")
  187. DEBUG_ASSERT(Equal(current, T()), "Intepolator predict error");
  188. #endif
  189. return;
  190. #endif
  191. }
  192. Elm &elm=_history[_elms++];
  193. elm.value =value;
  194. elm.duration=duration;
  195. }
  196. void HistoryInterpolator2::update()
  197. {
  198. _time+=Time.rd();
  199. if(_elms>2 && _time>_history[1].duration)
  200. {
  201. Int i=1;
  202. again:
  203. _time-=_history[i].duration; _elms--;
  204. if(_elms>2 && _time>_history[i+1].duration){i++; goto again;}
  205. MoveFastN(&_history[0], &_history[i], _elms);
  206. if(_count>=4) // higher number increases smoothness, but is slower to respond to network delays
  207. {
  208. _count=0;
  209. if(_left>0) // if we're too slow, then speedup
  210. {
  211. Flt time=_history[1].duration-_time; for(Int i=2; i<_elms; i++)time+=_history[i].duration; // actual time left
  212. if( time>0)
  213. {
  214. Flt target=Max(0, time-_left), // desired time left
  215. mul=target/time; // scale factor
  216. _time*=mul;
  217. for(Int i=1; i<_elms; i++)_history[i].duration*=mul;
  218. }
  219. }
  220. _left=FLT_MAX;
  221. }
  222. }
  223. }
  224. /******************************************************************************
  225. struct InterpolatorTime
  226. {
  227. // get
  228. Flt operator()()C {return _frac ;} // get current time fraction (0..1) between received data
  229. Bool empty ()C {return _empty;} // if is empty (no data was yet received)
  230. // operations
  231. void update(); // call this method at least once per frame before using this object for methods of other classes ('AngularInterpolator', 'LinearInterpolator', 'SplineInterpolator')
  232. void step (); // call this method when received new data, however after calling 'step' method of other classes ('AngularInterpolator', 'LinearInterpolator', 'SplineInterpolator')
  233. InterpolatorTime& reset(); // reset to initial settings
  234. InterpolatorTime() {reset();}
  235. private:
  236. Flt _frac, _latency;
  237. Dbl _last_receive_time;
  238. Bool _empty;
  239. };
  240. T1(TYPE) struct AngularInterpolator
  241. {
  242. // get
  243. C TYPE& operator()()C {return _c;} // get current value
  244. // operations
  245. AngularInterpolator& update( C InterpolatorTime &time); // update current value according to history and current time, call once per frame
  246. void step (C TYPE &value, C InterpolatorTime &time); // call this method when received new data
  247. void clearHistory() {_c=_h[0]=_h[1];} // clear value history, you can call this method when new value is drastically different than previous values in order to disable interpolation between old values (for example when interpolating player position which has suddenly teleported to a distant location, interpolator would normally return his position as interpolation between original and new position, however after calling this method new position will be returned immediately without interpolation with old position)
  248. AngularInterpolator() {_h[0]=_h[1]=_c=0;}
  249. private:
  250. TYPE _c, _h[2];
  251. };
  252. T1(TYPE) struct LinearInterpolator
  253. {
  254. // get
  255. C TYPE& operator()()C {return _c;} // get current value
  256. // operations
  257. LinearInterpolator& update( C InterpolatorTime &time); // update current value according to history and current time, call once per frame
  258. void step (C TYPE &value, C InterpolatorTime &time); // call this method when received new data
  259. void clearHistory() {_c=_h[0]=_h[1];} // clear value history, you can call this method when new value is drastically different than previous values in order to disable interpolation between old values (for example when interpolating player position which has suddenly teleported to a distant location, interpolator would normally return his position as interpolation between original and new position, however after calling this method new position will be returned immediately without interpolation with old position)
  260. LinearInterpolator() {_h[0]=_h[1]=_c=0;}
  261. private:
  262. TYPE _c, _h[2];
  263. };
  264. T1(TYPE) struct SplineInterpolator
  265. {
  266. // get
  267. C TYPE& operator()()C {return _c;} // get current value
  268. // operations
  269. SplineInterpolator& update( C InterpolatorTime &time); // update current value according to history and current time, call once per frame
  270. void step (C TYPE &value, C InterpolatorTime &time); // call this method when received new data
  271. void clearHistory() {_c=_h[0]=_h[1]=_h[3]=_h[2];} // clear value history, you can call this method when new value is drastically different than previous values in order to disable interpolation between old values (for example when interpolating player position which has suddenly teleported to a distant location, interpolator would normally return his position as interpolation between original and new position, however after calling this method new position will be returned immediately without interpolation with old position)
  272. SplineInterpolator() {_h[0]=_h[1]=_h[2]=_h[3]=_c=0;}
  273. private:
  274. TYPE _c, _h[4];
  275. };
  276. InterpolatorTime& InterpolatorTime::reset()
  277. {
  278. _empty=true;
  279. _frac=_latency=0;
  280. _last_receive_time=0;
  281. return T;
  282. }
  283. void InterpolatorTime::update()
  284. {
  285. if(_latency)
  286. {
  287. Flt delta=Time.realTime()-_last_receive_time;
  288. _frac=Min(delta/_latency, 1.25f);
  289. }
  290. }
  291. void InterpolatorTime::step()
  292. {
  293. Flt latency=Time.realTime()-_last_receive_time;
  294. if(_last_receive_time)
  295. {
  296. T._latency=Lerp(T._latency, latency, (latency>T._latency) ? 0.9f : 0.1f);
  297. }else
  298. {
  299. T._latency=Time.rd();
  300. }
  301. T._last_receive_time=Time.realTime();
  302. T._frac =0;
  303. T._empty=false;
  304. }
  305. /******************************************************************************
  306. struct _Interpolator // don't use this class, use 'Interpolator' instead
  307. {
  308. struct _Elm
  309. {
  310. Flt x;
  311. //TYPE y;
  312. };
  313. Bool loop , // if elements are looped (last interpolates to first) , default=false
  314. clamp; // if clamp value when accessing element out of range and looping is disabled, default=true
  315. Flt min_x, max_x; // minimum and maximum possible values of 'x' (used only when looping)
  316. Int elms ()C {return _elms.elms();} // get number of elements
  317. void clear() {_elms.clear(); min_x=FLT_MAX; max_x=-FLT_MAX;} // clear elements and reset min/max ranges
  318. private:
  319. Memc<_Elm> _elms;
  320. _Elm* _add (Flt x ) ;
  321. void _get (Flt x, Int &prev, Int &next, Flt &frac)C;
  322. void _get4(Flt x, Int &prev2, Int &prev, Int &next, Int &next2, Flt &frac)C;
  323. _Interpolator();
  324. T1(TYPE) friend struct Interpolator;
  325. };
  326. T1(TYPE) struct Interpolator : _Interpolator
  327. {
  328. struct Elm : _Elm
  329. {
  330. TYPE y;
  331. };
  332. Interpolator& add(Flt x, C TYPE &y) ; // create new element at 'x' position
  333. Elm& operator[](Int i )C; // get i-th element
  334. TYPE operator()(Flt x )C; // get linear interpolated value at 'x' position
  335. TYPE smooth(Flt x )C; // get smooth interpolated value at 'x' position (using 4 value, hermite spline interpolation)
  336. Interpolator& operator=(C Interpolator &src);
  337. Interpolator();
  338. Interpolator(C Interpolator &src);
  339. };
  340. inline Int Elms(C _Interpolator &interpolator) {return interpolator.elms();}
  341. /******************************************************************************
  342. T1(TYPE) Interpolator<TYPE> & Interpolator<TYPE>::add (Flt x, C TYPE &y) {if(typename Interpolator<TYPE>::Elm *elm=(typename Interpolator<TYPE>::Elm*)_add(x))elm->y=y; return T;}
  343. T1(TYPE) typename Interpolator<TYPE>::Elm& Interpolator<TYPE>::operator[](Int i )C {return (typename Interpolator<TYPE>::Elm&)_elms[i];}
  344. T1(TYPE) TYPE Interpolator<TYPE>::operator()(Flt x )C
  345. {
  346. Int prev, next; Flt frac; _get(x, prev, next, frac);
  347. if( prev==next)
  348. {
  349. if(prev<0)return 0;
  350. return T[prev].y;
  351. }
  352. return Lerp(T[prev].y, T[next].y, frac);
  353. }
  354. T1(TYPE) TYPE Interpolator<TYPE>::smooth(Flt x)C
  355. {
  356. Int prev2, prev, next, next2; Flt frac; _get4(x, prev2, prev, next, next2, frac);
  357. if( prev==next)
  358. {
  359. if(prev<0)return 0;
  360. return T[prev].y;
  361. }
  362. return Lerp4((prev2<0) ? T[prev].y*2-T[next].y : T[prev2].y, T[prev].y, T[next].y, (next2<0) ? T[next].y*2-T[prev].y : T[next2].y, frac);
  363. }
  364. T1(TYPE) Interpolator<TYPE>& Interpolator<TYPE>::operator=(C Interpolator &src)
  365. {
  366. loop =src.loop;
  367. clamp=src.clamp;
  368. min_x=src.min_x;
  369. max_x=src.max_x;
  370. _elms.setNum(src.elms());
  371. FREPAO(T)=src[i];
  372. return T;
  373. }
  374. T1(TYPE) Interpolator<TYPE>::Interpolator( ) {_elms.replaceClass<Elm>();}
  375. T1(TYPE) Interpolator<TYPE>::Interpolator(C Interpolator &src) : Interpolator() {T=src;}
  376. /******************************************************************************
  377. static Int CompareInterpolator(C _Interpolator::_Elm &elm, C Flt &x) {return Compare(elm.x, x);}
  378. _Interpolator::_Interpolator()
  379. {
  380. loop=false; clamp=true; min_x=FLT_MAX; max_x=-FLT_MAX;
  381. }
  382. _Interpolator::_Elm* _Interpolator::_add(Flt x)
  383. {
  384. Int i; if(!_elms.binarySearch(x, i, CompareInterpolator)){_Elm &e=_elms.NewAt(i); e.x=x; MAX(max_x, x); MIN(min_x, x); return &e;}
  385. return null;
  386. }
  387. void _Interpolator::_get(Flt x, Int &prev, Int &next, Flt &frac)C // get interpolated value at 'x' position
  388. {
  389. switch(elms())
  390. {
  391. case 0: prev=next=-1; break; // set both to invalid
  392. case 1: prev=next= 0; break; // set both to first
  393. default:
  394. {
  395. if(loop)x=Frac(x-min_x, max_x-min_x)+min_x;
  396. if(_elms.binarySearch(x, next, CompareInterpolator))prev=next;else // if found precisely
  397. {
  398. prev=next-1;
  399. if(!InRange(next, T)) // no next
  400. {
  401. if(loop)
  402. {
  403. next=0; // set next as first
  404. if(Flt length=(max_x-_elms.last().x)+(_elms.first().x-min_x))frac=(x-_elms.last().x)/length;else prev=next=elms()-1;
  405. }else
  406. if(clamp)prev=next=elms()-1;else
  407. {
  408. prev--;
  409. next--;
  410. frac=LerpR(_elms[prev].x, _elms[next].x, x); // this will be >1
  411. }
  412. }else
  413. if(!InRange(prev, T)) // no previous
  414. {
  415. if(loop)
  416. {
  417. prev=elms()-1; // set prev as last
  418. if(Flt length=(max_x-_elms.last().x)+(_elms.first().x-min_x))frac=(1-(_elms.first().x-x))/length;else prev=next=0;
  419. }else
  420. if(clamp)prev=next=0;else
  421. {
  422. prev++;
  423. next++;
  424. frac=LerpR(_elms[prev].x, _elms[next].x, x); // this will be <0
  425. }
  426. }else
  427. {
  428. frac=LerpR(_elms[prev].x, _elms[next].x, x); // this will be 0..1
  429. }
  430. }
  431. }break;
  432. }
  433. }
  434. void _Interpolator::_get4(Flt x, Int &prev2, Int &prev, Int &next, Int &next2, Flt &frac)C
  435. {
  436. _get(x, prev, next, frac);
  437. if(prev!=next)
  438. {
  439. prev2=prev-1; if(prev2<0) // invalid
  440. {
  441. if(loop )prev2=elms()-1;else // set prev as last
  442. if(clamp)prev2=prev;else
  443. prev2=-1;
  444. }
  445. next2=next+1; if(next2>=elms()) // invalid
  446. {
  447. if(loop )next2=0;else // set next as first
  448. if(clamp)next2=next;else
  449. next2=-1;
  450. }
  451. }
  452. }
  453. /******************************************************************************/
  454. }
  455. /******************************************************************************/