Interpolate.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #ifndef __MATH_INTERPOLATE_H__
  21. #define __MATH_INTERPOLATE_H__
  22. /*
  23. ==============================================================================================
  24. Linear interpolation.
  25. ==============================================================================================
  26. */
  27. template< class type >
  28. class idInterpolate {
  29. public:
  30. idInterpolate();
  31. void Init( const int startTime, const int duration, const type &startValue, const type &endValue );
  32. void SetStartTime( int time ) { this->startTime = time; }
  33. void SetDuration( int duration ) { this->duration = duration; }
  34. void SetStartValue( const type &startValue ) { this->startValue = startValue; }
  35. void SetEndValue( const type &endValue ) { this->endValue = endValue; }
  36. type GetCurrentValue( int time ) const;
  37. bool IsDone( int time ) const { return ( time >= startTime + duration ); }
  38. int GetStartTime() const { return startTime; }
  39. int GetEndTime() const { return startTime + duration; }
  40. int GetDuration() const { return duration; }
  41. const type & GetStartValue() const { return startValue; }
  42. const type & GetEndValue() const { return endValue; }
  43. private:
  44. int startTime;
  45. int duration;
  46. type startValue;
  47. type endValue;
  48. };
  49. /*
  50. ====================
  51. idInterpolate::idInterpolate
  52. ====================
  53. */
  54. template< class type >
  55. ID_INLINE idInterpolate<type>::idInterpolate() {
  56. startTime = duration = 0;
  57. memset( &startValue, 0, sizeof( startValue ) );
  58. memset( &endValue, 0, sizeof( endValue ) );
  59. }
  60. /*
  61. ====================
  62. idInterpolate::Init
  63. ====================
  64. */
  65. template< class type >
  66. ID_INLINE void idInterpolate<type>::Init( const int startTime, const int duration, const type &startValue, const type &endValue ) {
  67. this->startTime = startTime;
  68. this->duration = duration;
  69. this->startValue = startValue;
  70. this->endValue = endValue;
  71. }
  72. /*
  73. ====================
  74. idInterpolate::GetCurrentValue
  75. ====================
  76. */
  77. template< class type >
  78. ID_INLINE type idInterpolate<type>::GetCurrentValue( int time ) const {
  79. if ( time <= startTime ) {
  80. return startValue;
  81. } else if ( time >= startTime + duration ) {
  82. return endValue;
  83. } else {
  84. const float deltaTime = time - startTime;
  85. const float f = deltaTime / (float)duration;
  86. const type range = ( endValue - startValue );
  87. return startValue + ( range * f );
  88. }
  89. }
  90. /*
  91. ==============================================================================================
  92. Continuous interpolation with linear acceleration and deceleration phase.
  93. The velocity is continuous but the acceleration is not.
  94. ==============================================================================================
  95. */
  96. template< class type >
  97. class idInterpolateAccelDecelLinear {
  98. public:
  99. idInterpolateAccelDecelLinear();
  100. void Init( const int startTime, const int accelTime, const int decelTime, const int duration, const type &startValue, const type &endValue );
  101. void SetStartTime( int time ) { startTime = time; Invalidate(); }
  102. void SetStartValue( const type &startValue ) { this->startValue = startValue; Invalidate(); }
  103. void SetEndValue( const type &endValue ) { this->endValue = endValue; Invalidate(); }
  104. type GetCurrentValue( int time ) const;
  105. type GetCurrentSpeed( int time ) const;
  106. bool IsDone( int time ) const { return ( time >= startTime + accelTime + linearTime + decelTime ); }
  107. int GetStartTime() const { return startTime; }
  108. int GetEndTime() const { return startTime + accelTime + linearTime + decelTime; }
  109. int GetDuration() const { return accelTime + linearTime + decelTime; }
  110. int GetAcceleration() const { return accelTime; }
  111. int GetDeceleration() const { return decelTime; }
  112. const type & GetStartValue() const { return startValue; }
  113. const type & GetEndValue() const { return endValue; }
  114. private:
  115. int startTime;
  116. int accelTime;
  117. int linearTime;
  118. int decelTime;
  119. type startValue;
  120. type endValue;
  121. mutable idExtrapolate<type> extrapolate;
  122. void Invalidate();
  123. void SetPhase( int time ) const;
  124. };
  125. /*
  126. ====================
  127. idInterpolateAccelDecelLinear::idInterpolateAccelDecelLinear
  128. ====================
  129. */
  130. template< class type >
  131. ID_INLINE idInterpolateAccelDecelLinear<type>::idInterpolateAccelDecelLinear() {
  132. startTime = accelTime = linearTime = decelTime = 0;
  133. memset( &startValue, 0, sizeof( startValue ) );
  134. endValue = startValue;
  135. }
  136. /*
  137. ====================
  138. idInterpolateAccelDecelLinear::Init
  139. ====================
  140. */
  141. template< class type >
  142. ID_INLINE void idInterpolateAccelDecelLinear<type>::Init( const int startTime, const int accelTime, const int decelTime, const int duration, const type &startValue, const type &endValue ) {
  143. this->startTime = startTime;
  144. this->accelTime = accelTime;
  145. this->decelTime = decelTime;
  146. this->startValue = startValue;
  147. this->endValue = endValue;
  148. if ( duration <= 0 ) {
  149. return;
  150. }
  151. if ( this->accelTime + this->decelTime > duration ) {
  152. this->accelTime = this->accelTime * duration / ( this->accelTime + this->decelTime );
  153. this->decelTime = duration - this->accelTime;
  154. }
  155. this->linearTime = duration - this->accelTime - this->decelTime;
  156. const type speed = ( endValue - startValue ) * ( 1000.0f / ( (float) this->linearTime + ( this->accelTime + this->decelTime ) * 0.5f ) );
  157. if ( this->accelTime ) {
  158. extrapolate.Init( startTime, this->accelTime, startValue, ( startValue - startValue ), speed, EXTRAPOLATION_ACCELLINEAR ); //-V501
  159. } else if ( this->linearTime ) {
  160. extrapolate.Init( startTime, this->linearTime, startValue, ( startValue - startValue ), speed, EXTRAPOLATION_LINEAR ); //-V501
  161. } else {
  162. extrapolate.Init( startTime, this->decelTime, startValue, ( startValue - startValue ), speed, EXTRAPOLATION_DECELLINEAR ); //-V501
  163. }
  164. }
  165. /*
  166. ====================
  167. idInterpolateAccelDecelLinear::Invalidate
  168. ====================
  169. */
  170. template< class type >
  171. ID_INLINE void idInterpolateAccelDecelLinear<type>::Invalidate() {
  172. extrapolate.Init( 0, 0, extrapolate.GetStartValue(), extrapolate.GetBaseSpeed(), extrapolate.GetSpeed(), EXTRAPOLATION_NONE );
  173. }
  174. /*
  175. ====================
  176. idInterpolateAccelDecelLinear::SetPhase
  177. ====================
  178. */
  179. template< class type >
  180. ID_INLINE void idInterpolateAccelDecelLinear<type>::SetPhase( int time ) const {
  181. const float deltaTime = time - startTime;
  182. if ( deltaTime < accelTime ) {
  183. if ( extrapolate.GetExtrapolationType() != EXTRAPOLATION_ACCELLINEAR ) {
  184. extrapolate.Init( startTime, accelTime, startValue, extrapolate.GetBaseSpeed(), extrapolate.GetSpeed(), EXTRAPOLATION_ACCELLINEAR );
  185. }
  186. } else if ( deltaTime < accelTime + linearTime ) {
  187. if ( extrapolate.GetExtrapolationType() != EXTRAPOLATION_LINEAR ) {
  188. extrapolate.Init( startTime + accelTime, linearTime, startValue + extrapolate.GetSpeed() * ( accelTime * 0.001f * 0.5f ), extrapolate.GetBaseSpeed(), extrapolate.GetSpeed(), EXTRAPOLATION_LINEAR );
  189. }
  190. } else {
  191. if ( extrapolate.GetExtrapolationType() != EXTRAPOLATION_DECELLINEAR ) {
  192. extrapolate.Init( startTime + accelTime + linearTime, decelTime, endValue - ( extrapolate.GetSpeed() * ( decelTime * 0.001f * 0.5f ) ), extrapolate.GetBaseSpeed(), extrapolate.GetSpeed(), EXTRAPOLATION_DECELLINEAR );
  193. }
  194. }
  195. }
  196. /*
  197. ====================
  198. idInterpolateAccelDecelLinear::GetCurrentValue
  199. ====================
  200. */
  201. template< class type >
  202. ID_INLINE type idInterpolateAccelDecelLinear<type>::GetCurrentValue( int time ) const {
  203. SetPhase( time );
  204. return extrapolate.GetCurrentValue( time );
  205. }
  206. /*
  207. ====================
  208. idInterpolateAccelDecelLinear::GetCurrentSpeed
  209. ====================
  210. */
  211. template< class type >
  212. ID_INLINE type idInterpolateAccelDecelLinear<type>::GetCurrentSpeed( int time ) const {
  213. SetPhase( time );
  214. return extrapolate.GetCurrentSpeed( time );
  215. }
  216. /*
  217. ==============================================================================================
  218. Continuous interpolation with sinusoidal acceleration and deceleration phase.
  219. Both the velocity and acceleration are continuous.
  220. ==============================================================================================
  221. */
  222. template< class type >
  223. class idInterpolateAccelDecelSine {
  224. public:
  225. idInterpolateAccelDecelSine();
  226. void Init( const int startTime, const int accelTime, const int decelTime, const int duration, const type &startValue, const type &endValue );
  227. void SetStartTime( int time ) { startTime = time; Invalidate(); }
  228. void SetStartValue( const type &startValue ) { this->startValue = startValue; Invalidate(); }
  229. void SetEndValue( const type &endValue ) { this->endValue = endValue; Invalidate(); }
  230. type GetCurrentValue( int time ) const;
  231. type GetCurrentSpeed( int time ) const;
  232. bool IsDone( int time ) const { return ( time >= startTime + accelTime + linearTime + decelTime ); }
  233. int GetStartTime() const { return startTime; }
  234. int GetEndTime() const { return startTime + accelTime + linearTime + decelTime; }
  235. int GetDuration() const { return accelTime + linearTime + decelTime; }
  236. int GetAcceleration() const { return accelTime; }
  237. int GetDeceleration() const { return decelTime; }
  238. const type & GetStartValue() const { return startValue; }
  239. const type & GetEndValue() const { return endValue; }
  240. private:
  241. int startTime;
  242. int accelTime;
  243. int linearTime;
  244. int decelTime;
  245. type startValue;
  246. type endValue;
  247. mutable idExtrapolate<type> extrapolate;
  248. void Invalidate();
  249. void SetPhase( int time ) const;
  250. };
  251. /*
  252. ====================
  253. idInterpolateAccelDecelSine::idInterpolateAccelDecelSine
  254. ====================
  255. */
  256. template< class type >
  257. ID_INLINE idInterpolateAccelDecelSine<type>::idInterpolateAccelDecelSine() {
  258. startTime = accelTime = linearTime = decelTime = 0;
  259. memset( &startValue, 0, sizeof( startValue ) );
  260. memset( &endValue, 0, sizeof( endValue ) );
  261. }
  262. /*
  263. ====================
  264. idInterpolateAccelDecelSine::Init
  265. ====================
  266. */
  267. template< class type >
  268. ID_INLINE void idInterpolateAccelDecelSine<type>::Init( const int startTime, const int accelTime, const int decelTime, const int duration, const type &startValue, const type &endValue ) {
  269. this->startTime = startTime;
  270. this->accelTime = accelTime;
  271. this->decelTime = decelTime;
  272. this->startValue = startValue;
  273. this->endValue = endValue;
  274. if ( duration <= 0 ) {
  275. return;
  276. }
  277. if ( this->accelTime + this->decelTime > duration ) {
  278. this->accelTime = this->accelTime * duration / ( this->accelTime + this->decelTime );
  279. this->decelTime = duration - this->accelTime;
  280. }
  281. this->linearTime = duration - this->accelTime - this->decelTime;
  282. const type speed = ( endValue - startValue ) * ( 1000.0f / ( (float) this->linearTime + ( this->accelTime + this->decelTime ) * idMath::SQRT_1OVER2 ) );
  283. if ( this->accelTime ) {
  284. extrapolate.Init( startTime, this->accelTime, startValue, ( startValue - startValue ), speed, EXTRAPOLATION_ACCELSINE ); //-V501
  285. } else if ( this->linearTime ) {
  286. extrapolate.Init( startTime, this->linearTime, startValue, ( startValue - startValue ), speed, EXTRAPOLATION_LINEAR ); //-V501
  287. } else {
  288. extrapolate.Init( startTime, this->decelTime, startValue, ( startValue - startValue ), speed, EXTRAPOLATION_DECELSINE ); //-V501
  289. }
  290. }
  291. /*
  292. ====================
  293. idInterpolateAccelDecelSine::Invalidate
  294. ====================
  295. */
  296. template< class type >
  297. ID_INLINE void idInterpolateAccelDecelSine<type>::Invalidate() {
  298. extrapolate.Init( 0, 0, extrapolate.GetStartValue(), extrapolate.GetBaseSpeed(), extrapolate.GetSpeed(), EXTRAPOLATION_NONE );
  299. }
  300. /*
  301. ====================
  302. idInterpolateAccelDecelSine::SetPhase
  303. ====================
  304. */
  305. template< class type >
  306. ID_INLINE void idInterpolateAccelDecelSine<type>::SetPhase( int time ) const {
  307. const float deltaTime = time - startTime;
  308. if ( deltaTime < accelTime ) {
  309. if ( extrapolate.GetExtrapolationType() != EXTRAPOLATION_ACCELSINE ) {
  310. extrapolate.Init( startTime, accelTime, startValue, extrapolate.GetBaseSpeed(), extrapolate.GetSpeed(), EXTRAPOLATION_ACCELSINE );
  311. }
  312. } else if ( deltaTime < accelTime + linearTime ) {
  313. if ( extrapolate.GetExtrapolationType() != EXTRAPOLATION_LINEAR ) {
  314. extrapolate.Init( startTime + accelTime, linearTime, startValue + extrapolate.GetSpeed() * ( accelTime * 0.001f * idMath::SQRT_1OVER2 ), extrapolate.GetBaseSpeed(), extrapolate.GetSpeed(), EXTRAPOLATION_LINEAR );
  315. }
  316. } else {
  317. if ( extrapolate.GetExtrapolationType() != EXTRAPOLATION_DECELSINE ) {
  318. extrapolate.Init( startTime + accelTime + linearTime, decelTime, endValue - ( extrapolate.GetSpeed() * ( decelTime * 0.001f * idMath::SQRT_1OVER2 ) ), extrapolate.GetBaseSpeed(), extrapolate.GetSpeed(), EXTRAPOLATION_DECELSINE );
  319. }
  320. }
  321. }
  322. /*
  323. ====================
  324. idInterpolateAccelDecelSine::GetCurrentValue
  325. ====================
  326. */
  327. template< class type >
  328. ID_INLINE type idInterpolateAccelDecelSine<type>::GetCurrentValue( int time ) const {
  329. SetPhase( time );
  330. return extrapolate.GetCurrentValue( time );
  331. }
  332. /*
  333. ====================
  334. idInterpolateAccelDecelSine::GetCurrentSpeed
  335. ====================
  336. */
  337. template< class type >
  338. ID_INLINE type idInterpolateAccelDecelSine<type>::GetCurrentSpeed( int time ) const {
  339. SetPhase( time );
  340. return extrapolate.GetCurrentSpeed( time );
  341. }
  342. #endif /* !__MATH_INTERPOLATE_H__ */