Ode.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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. #pragma hdrstop
  21. #include "../precompiled.h"
  22. //===============================================================
  23. //
  24. // idODE_Euler
  25. //
  26. //===============================================================
  27. /*
  28. =============
  29. idODE_Euler::idODE_Euler
  30. =============
  31. */
  32. idODE_Euler::idODE_Euler( const int dim, deriveFunction_t dr, const void *ud ) {
  33. dimension = dim;
  34. derivatives = new (TAG_MATH) float[dim];
  35. derive = dr;
  36. userData = ud;
  37. }
  38. /*
  39. =============
  40. idODE_Euler::~idODE_Euler
  41. =============
  42. */
  43. idODE_Euler::~idODE_Euler() {
  44. delete[] derivatives;
  45. }
  46. /*
  47. =============
  48. idODE_Euler::Evaluate
  49. =============
  50. */
  51. float idODE_Euler::Evaluate( const float *state, float *newState, float t0, float t1 ) {
  52. float delta;
  53. int i;
  54. derive( t0, userData, state, derivatives );
  55. delta = t1 - t0;
  56. for ( i = 0; i < dimension; i++ ) {
  57. newState[i] = state[i] + delta * derivatives[i];
  58. }
  59. return delta;
  60. }
  61. //===============================================================
  62. //
  63. // idODE_Midpoint
  64. //
  65. //===============================================================
  66. /*
  67. =============
  68. idODE_Midpoint::idODE_Midpoint
  69. =============
  70. */
  71. idODE_Midpoint::idODE_Midpoint( const int dim, deriveFunction_t dr, const void *ud ) {
  72. dimension = dim;
  73. tmpState = new (TAG_MATH) float[dim];
  74. derivatives = new (TAG_MATH) float[dim];
  75. derive = dr;
  76. userData = ud;
  77. }
  78. /*
  79. =============
  80. idODE_Midpoint::~idODE_Midpoint
  81. =============
  82. */
  83. idODE_Midpoint::~idODE_Midpoint() {
  84. delete tmpState;
  85. delete derivatives;
  86. }
  87. /*
  88. =============
  89. idODE_Midpoint::~Evaluate
  90. =============
  91. */
  92. float idODE_Midpoint::Evaluate( const float *state, float *newState, float t0, float t1 ) {
  93. double delta, halfDelta;
  94. int i;
  95. delta = t1 - t0;
  96. halfDelta = delta * 0.5;
  97. // first step
  98. derive( t0, userData, state, derivatives );
  99. for ( i = 0; i < dimension; i++ ) {
  100. tmpState[i] = state[i] + halfDelta * derivatives[i];
  101. }
  102. // second step
  103. derive( t0 + halfDelta, userData, tmpState, derivatives );
  104. for ( i = 0; i < dimension; i++ ) {
  105. newState[i] = state[i] + delta * derivatives[i];
  106. }
  107. return delta;
  108. }
  109. //===============================================================
  110. //
  111. // idODE_RK4
  112. //
  113. //===============================================================
  114. /*
  115. =============
  116. idODE_RK4::idODE_RK4
  117. =============
  118. */
  119. idODE_RK4::idODE_RK4( const int dim, deriveFunction_t dr, const void *ud ) {
  120. dimension = dim;
  121. derive = dr;
  122. userData = ud;
  123. tmpState = new (TAG_MATH) float[dim];
  124. d1 = new (TAG_MATH) float[dim];
  125. d2 = new (TAG_MATH) float[dim];
  126. d3 = new (TAG_MATH) float[dim];
  127. d4 = new (TAG_MATH) float[dim];
  128. }
  129. /*
  130. =============
  131. idODE_RK4::~idODE_RK4
  132. =============
  133. */
  134. idODE_RK4::~idODE_RK4() {
  135. delete tmpState;
  136. delete d1;
  137. delete d2;
  138. delete d3;
  139. delete d4;
  140. }
  141. /*
  142. =============
  143. idODE_RK4::Evaluate
  144. =============
  145. */
  146. float idODE_RK4::Evaluate( const float *state, float *newState, float t0, float t1 ) {
  147. double delta, halfDelta, sixthDelta;
  148. int i;
  149. delta = t1 - t0;
  150. halfDelta = delta * 0.5;
  151. // first step
  152. derive( t0, userData, state, d1 );
  153. for ( i = 0; i < dimension; i++ ) {
  154. tmpState[i] = state[i] + halfDelta * d1[i];
  155. }
  156. // second step
  157. derive( t0 + halfDelta, userData, tmpState, d2 );
  158. for ( i = 0; i < dimension; i++ ) {
  159. tmpState[i] = state[i] + halfDelta * d2[i];
  160. }
  161. // third step
  162. derive( t0 + halfDelta, userData, tmpState, d3 );
  163. for ( i = 0; i < dimension; i++ ) {
  164. tmpState[i] = state[i] + delta * d3[i];
  165. }
  166. // fourth step
  167. derive( t0 + delta, userData, tmpState, d4 );
  168. sixthDelta = delta * (1.0/6.0);
  169. for ( i = 0; i < dimension; i++ ) {
  170. newState[i] = state[i] + sixthDelta * (d1[i] + 2.0 * (d2[i] + d3[i]) + d4[i]);
  171. }
  172. return delta;
  173. }
  174. //===============================================================
  175. //
  176. // idODE_RK4Adaptive
  177. //
  178. //===============================================================
  179. /*
  180. =============
  181. idODE_RK4Adaptive::idODE_RK4Adaptive
  182. =============
  183. */
  184. idODE_RK4Adaptive::idODE_RK4Adaptive( const int dim, deriveFunction_t dr, const void *ud ) {
  185. dimension = dim;
  186. derive = dr;
  187. userData = ud;
  188. maxError = 0.01f;
  189. tmpState = new (TAG_MATH) float[dim];
  190. d1 = new (TAG_MATH) float[dim];
  191. d1half = new (TAG_MATH) float [dim];
  192. d2 = new (TAG_MATH) float[dim];
  193. d3 = new (TAG_MATH) float[dim];
  194. d4 = new (TAG_MATH) float[dim];
  195. }
  196. /*
  197. =============
  198. idODE_RK4Adaptive::~idODE_RK4Adaptive
  199. =============
  200. */
  201. idODE_RK4Adaptive::~idODE_RK4Adaptive() {
  202. delete tmpState;
  203. delete d1;
  204. delete d1half;
  205. delete d2;
  206. delete d3;
  207. delete d4;
  208. }
  209. /*
  210. =============
  211. idODE_RK4Adaptive::SetMaxError
  212. =============
  213. */
  214. void idODE_RK4Adaptive::SetMaxError( const float err ) {
  215. if ( err > 0.0f ) {
  216. maxError = err;
  217. }
  218. }
  219. /*
  220. =============
  221. idODE_RK4Adaptive::Evaluate
  222. =============
  223. */
  224. float idODE_RK4Adaptive::Evaluate( const float *state, float *newState, float t0, float t1 ) {
  225. double delta, halfDelta, fourthDelta, sixthDelta;
  226. double error, max;
  227. int i, n;
  228. delta = t1 - t0;
  229. for ( n = 0; n < 4; n++ ) {
  230. halfDelta = delta * 0.5;
  231. fourthDelta = delta * 0.25;
  232. // first step of first half delta
  233. derive( t0, userData, state, d1 );
  234. for ( i = 0; i < dimension; i++ ) {
  235. tmpState[i] = state[i] + fourthDelta * d1[i];
  236. }
  237. // second step of first half delta
  238. derive( t0 + fourthDelta, userData, tmpState, d2 );
  239. for ( i = 0; i < dimension; i++ ) {
  240. tmpState[i] = state[i] + fourthDelta * d2[i];
  241. }
  242. // third step of first half delta
  243. derive( t0 + fourthDelta, userData, tmpState, d3 );
  244. for ( i = 0; i < dimension; i++ ) {
  245. tmpState[i] = state[i] + halfDelta * d3[i];
  246. }
  247. // fourth step of first half delta
  248. derive( t0 + halfDelta, userData, tmpState, d4 );
  249. sixthDelta = halfDelta * (1.0/6.0);
  250. for ( i = 0; i < dimension; i++ ) {
  251. tmpState[i] = state[i] + sixthDelta * (d1[i] + 2.0 * (d2[i] + d3[i]) + d4[i]);
  252. }
  253. // first step of second half delta
  254. derive( t0 + halfDelta, userData, tmpState, d1half );
  255. for ( i = 0; i < dimension; i++ ) {
  256. tmpState[i] = state[i] + fourthDelta * d1half[i];
  257. }
  258. // second step of second half delta
  259. derive( t0 + halfDelta + fourthDelta, userData, tmpState, d2 );
  260. for ( i = 0; i < dimension; i++ ) {
  261. tmpState[i] = state[i] + fourthDelta * d2[i];
  262. }
  263. // third step of second half delta
  264. derive( t0 + halfDelta + fourthDelta, userData, tmpState, d3 );
  265. for ( i = 0; i < dimension; i++ ) {
  266. tmpState[i] = state[i] + halfDelta * d3[i];
  267. }
  268. // fourth step of second half delta
  269. derive( t0 + delta, userData, tmpState, d4 );
  270. sixthDelta = halfDelta * (1.0/6.0);
  271. for ( i = 0; i < dimension; i++ ) {
  272. newState[i] = state[i] + sixthDelta * (d1[i] + 2.0 * (d2[i] + d3[i]) + d4[i]);
  273. }
  274. // first step of full delta
  275. for ( i = 0; i < dimension; i++ ) {
  276. tmpState[i] = state[i] + halfDelta * d1[i];
  277. }
  278. // second step of full delta
  279. derive( t0 + halfDelta, userData, tmpState, d2 );
  280. for ( i = 0; i < dimension; i++ ) {
  281. tmpState[i] = state[i] + halfDelta * d2[i];
  282. }
  283. // third step of full delta
  284. derive( t0 + halfDelta, userData, tmpState, d3 );
  285. for ( i = 0; i < dimension; i++ ) {
  286. tmpState[i] = state[i] + delta * d3[i];
  287. }
  288. // fourth step of full delta
  289. derive( t0 + delta, userData, tmpState, d4 );
  290. sixthDelta = delta * (1.0/6.0);
  291. for ( i = 0; i < dimension; i++ ) {
  292. tmpState[i] = state[i] + sixthDelta * (d1[i] + 2.0 * (d2[i] + d3[i]) + d4[i]);
  293. }
  294. // get max estimated error
  295. max = 0.0;
  296. for ( i = 0; i < dimension; i++ ) {
  297. error = idMath::Fabs( (newState[i] - tmpState[i]) / (delta * d1[i] + 1e-10) );
  298. if ( error > max ) {
  299. max = error;
  300. }
  301. }
  302. error = max / maxError;
  303. if ( error <= 1.0f ) {
  304. return delta * 4.0;
  305. }
  306. if ( delta <= 1e-7 ) {
  307. return delta;
  308. }
  309. delta *= 0.25;
  310. }
  311. return delta;
  312. }