2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 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 Source Code. If not, please request a copy in writing from id Software at the address below.
24 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.
26 ===========================================================================
29 #include "../precompiled.h"
32 //===============================================================
36 //===============================================================
40 idODE_Euler::idODE_Euler
43 idODE_Euler::idODE_Euler( const int dim, deriveFunction_t dr, const void *ud ) {
45 derivatives = new float[dim];
52 idODE_Euler::~idODE_Euler
55 idODE_Euler::~idODE_Euler( void ) {
64 float idODE_Euler::Evaluate( const float *state, float *newState, float t0, float t1 ) {
68 derive( t0, userData, state, derivatives );
70 for ( i = 0; i < dimension; i++ ) {
71 newState[i] = state[i] + delta * derivatives[i];
76 //===============================================================
80 //===============================================================
84 idODE_Midpoint::idODE_Midpoint
87 idODE_Midpoint::idODE_Midpoint( const int dim, deriveFunction_t dr, const void *ud ) {
89 tmpState = new float[dim];
90 derivatives = new float[dim];
97 idODE_Midpoint::~idODE_Midpoint
100 idODE_Midpoint::~idODE_Midpoint( void ) {
107 idODE_Midpoint::~Evaluate
110 float idODE_Midpoint::Evaluate( const float *state, float *newState, float t0, float t1 ) {
111 double delta, halfDelta;
115 halfDelta = delta * 0.5;
117 derive( t0, userData, state, derivatives );
118 for ( i = 0; i < dimension; i++ ) {
119 tmpState[i] = state[i] + halfDelta * derivatives[i];
122 derive( t0 + halfDelta, userData, tmpState, derivatives );
124 for ( i = 0; i < dimension; i++ ) {
125 newState[i] = state[i] + delta * derivatives[i];
130 //===============================================================
134 //===============================================================
141 idODE_RK4::idODE_RK4( const int dim, deriveFunction_t dr, const void *ud ) {
145 tmpState = new float[dim];
154 idODE_RK4::~idODE_RK4
157 idODE_RK4::~idODE_RK4( void ) {
170 float idODE_RK4::Evaluate( const float *state, float *newState, float t0, float t1 ) {
171 double delta, halfDelta, sixthDelta;
175 halfDelta = delta * 0.5;
177 derive( t0, userData, state, d1 );
178 for ( i = 0; i < dimension; i++ ) {
179 tmpState[i] = state[i] + halfDelta * d1[i];
182 derive( t0 + halfDelta, userData, tmpState, d2 );
183 for ( i = 0; i < dimension; i++ ) {
184 tmpState[i] = state[i] + halfDelta * d2[i];
187 derive( t0 + halfDelta, userData, tmpState, d3 );
188 for ( i = 0; i < dimension; i++ ) {
189 tmpState[i] = state[i] + delta * d3[i];
192 derive( t0 + delta, userData, tmpState, d4 );
194 sixthDelta = delta * (1.0/6.0);
195 for ( i = 0; i < dimension; i++ ) {
196 newState[i] = state[i] + sixthDelta * (d1[i] + 2.0 * (d2[i] + d3[i]) + d4[i]);
201 //===============================================================
205 //===============================================================
209 idODE_RK4Adaptive::idODE_RK4Adaptive
212 idODE_RK4Adaptive::idODE_RK4Adaptive( const int dim, deriveFunction_t dr, const void *ud ) {
217 tmpState = new float[dim];
219 d1half = new float [dim];
227 idODE_RK4Adaptive::~idODE_RK4Adaptive
230 idODE_RK4Adaptive::~idODE_RK4Adaptive( void ) {
241 idODE_RK4Adaptive::SetMaxError
244 void idODE_RK4Adaptive::SetMaxError( const float err ) {
252 idODE_RK4Adaptive::Evaluate
255 float idODE_RK4Adaptive::Evaluate( const float *state, float *newState, float t0, float t1 ) {
256 double delta, halfDelta, fourthDelta, sixthDelta;
262 for ( n = 0; n < 4; n++ ) {
264 halfDelta = delta * 0.5;
265 fourthDelta = delta * 0.25;
267 // first step of first half delta
268 derive( t0, userData, state, d1 );
269 for ( i = 0; i < dimension; i++ ) {
270 tmpState[i] = state[i] + fourthDelta * d1[i];
272 // second step of first half delta
273 derive( t0 + fourthDelta, userData, tmpState, d2 );
274 for ( i = 0; i < dimension; i++ ) {
275 tmpState[i] = state[i] + fourthDelta * d2[i];
277 // third step of first half delta
278 derive( t0 + fourthDelta, userData, tmpState, d3 );
279 for ( i = 0; i < dimension; i++ ) {
280 tmpState[i] = state[i] + halfDelta * d3[i];
282 // fourth step of first half delta
283 derive( t0 + halfDelta, userData, tmpState, d4 );
285 sixthDelta = halfDelta * (1.0/6.0);
286 for ( i = 0; i < dimension; i++ ) {
287 tmpState[i] = state[i] + sixthDelta * (d1[i] + 2.0 * (d2[i] + d3[i]) + d4[i]);
290 // first step of second half delta
291 derive( t0 + halfDelta, userData, tmpState, d1half );
292 for ( i = 0; i < dimension; i++ ) {
293 tmpState[i] = state[i] + fourthDelta * d1half[i];
295 // second step of second half delta
296 derive( t0 + halfDelta + fourthDelta, userData, tmpState, d2 );
297 for ( i = 0; i < dimension; i++ ) {
298 tmpState[i] = state[i] + fourthDelta * d2[i];
300 // third step of second half delta
301 derive( t0 + halfDelta + fourthDelta, userData, tmpState, d3 );
302 for ( i = 0; i < dimension; i++ ) {
303 tmpState[i] = state[i] + halfDelta * d3[i];
305 // fourth step of second half delta
306 derive( t0 + delta, userData, tmpState, d4 );
308 sixthDelta = halfDelta * (1.0/6.0);
309 for ( i = 0; i < dimension; i++ ) {
310 newState[i] = state[i] + sixthDelta * (d1[i] + 2.0 * (d2[i] + d3[i]) + d4[i]);
313 // first step of full delta
314 for ( i = 0; i < dimension; i++ ) {
315 tmpState[i] = state[i] + halfDelta * d1[i];
317 // second step of full delta
318 derive( t0 + halfDelta, userData, tmpState, d2 );
319 for ( i = 0; i < dimension; i++ ) {
320 tmpState[i] = state[i] + halfDelta * d2[i];
322 // third step of full delta
323 derive( t0 + halfDelta, userData, tmpState, d3 );
324 for ( i = 0; i < dimension; i++ ) {
325 tmpState[i] = state[i] + delta * d3[i];
327 // fourth step of full delta
328 derive( t0 + delta, userData, tmpState, d4 );
330 sixthDelta = delta * (1.0/6.0);
331 for ( i = 0; i < dimension; i++ ) {
332 tmpState[i] = state[i] + sixthDelta * (d1[i] + 2.0 * (d2[i] + d3[i]) + d4[i]);
335 // get max estimated error
337 for ( i = 0; i < dimension; i++ ) {
338 error = idMath::Fabs( (newState[i] - tmpState[i]) / (delta * d1[i] + 1e-10) );
343 error = max / maxError;
345 if ( error <= 1.0f ) {
348 if ( delta <= 1e-7 ) {