Gaffer on Games

Glenn Fiedler, an Australian Game Developer in LA.

Gaffer on Games header image 3

Integration Basics

Introduction

Hi, I’m Glenn Fiedler and welcome to my series of articles on game physics.

If you have ever wondered how the physics in computer games works then this series of articles will explain it for you. I will assume that you are proficient with C++ and have a basic grasp of physics and mathematics. Nothing else will be required to follow along if you pay attention and study the source code.

So how does physics simulation work? At the heart of it, if we know the current physics state of an object (its position, how fast it is moving and so on), and what forces are being applied to it, then we can integrate to determine how the object’s physics state changes over time. If we display the object at this integrated state at 60 frames a second it will appear to animate realistically following the laws of physics.

Exactly how to implement this integration is the subject of this article.

Integrating the Equations of Motion

You should remember from high school or university physics that Force = Mass times Acceleration. We can switch this equation around to see that Acceleration = Force divided by Mass. This makes sense because the more an object weighs, the less acceleration it will receive from the same amount of force.

The important thing to realize is that acceleration is the rate of change in velocity over time. This means that if we can integrate (sum) these changes in velocity over time we can keep track of the velocity at each point in time v(t). Now that we know the velocity at any time we can use it to update position over time called x(t). This is because velocity is the rate of change of position over time just as acceleration is the rate of change of velocity.

So:

F=ma becomes a = F/m

and:

dv/dt = a (acceleration is the change of velocity over time)
dx/dt = v (velocity is the change of position over time)

This means that if we know the the forces applied to an object we can integrate to find its velocity and position over time.

Numerical Integration

For those who have not formally studied differential equations at university, take heart for you are in just as good a position as those who have! This is because we are not going to solve the differential equations as you would normally do in first year mathematics, instead we are going to numerically integrate to find the solution.

Here is how numerical integration works. Start at a certain initial position and velocity, then take a small step forward in time to find our velocity and position at the next time value. Do this repeatedly to go forward in time in small increments. For example games usually move forward in small steps about 1/60th of a second long.

For simplicity, lets assume we are stepping forward one second at a time. First we start at our initial velocity and position, then work out how much the velocity and position change over the course of one second. Then, we add this change to the velocity and position and repeat the process. Starting with the velocity values we now have at 1 second, we work out how much the values will now change over the next second to find the values at 2 seconds and so on for 3, 4, 5, 6… etc.

But how do we find the amount of change in velocity and position each step? The answer lies in the equations of motion presented in the paragraph above. We work out how much acceleration is being applied by dividing force by mass. Since acceleration is literally change in velocity per second, we realize that the change in velocity is acceleration * (time in seconds). Similarly, the change in position is velocity * (time in seconds).

We will call our current time ‘t’ and the change in time between each step ‘dt’ (delta time). Now we can present the equations of motion in a form that should make sense to anyone:

acceleration = force divided by mass
change in velocity = acceleration times delta time
change in position = velocity times delta time

It makes sense because we know if you are traveling 60 kilometers per hour in a car, then in one hour we’ll be exactly 60 kilometers further down the road. Similarly, if a car is accelerating at 10 kilometers per hour per second from a standing start, then in 10 seconds it must be traveling at exactly 100 kilometers per hour.

Lets put this into code. Assuming that our initial position and velocity are zero, we can integrate the equations of motion over time simply by adding the change in position and velocity to the previous values each timestep:

    float t = 0;
    float dt = 1;

    float velocity = 0;
    float position = 0;
    float force = 10;
    float mass = 1;

    while ( t < = 10 )
    {
         position = position + velocity * dt;
         velocity = velocity + ( force / mass ) * dt;
         t = t + dt;
    }

Notice how the integrated velocity feeds into the integration of the position next frame. This uses the most recently integrated velocity value to update the position of the car over time so that at each second we know how far the car has travelled down the road and how fast it is traveling.

Why Euler is never good enough

What we just did above is called Euler Integration. To save you any future embarrassment, I must point out now that Euler is pronounced “Oiler” not “yew-ler” as it is the last name of the Swiss mathematician Leonhard Euler who first discovered the technique.

Euler integration is the most basic of numerical integration techniques. It is only 100% accurate if the rate of change is constant over the timestep. For example it is accurate in integrating velocity over time in the example above because acceleration is a constant 10 meters per second per second. But when we integrate velocity to get the position in the example, it is not completely accurate. This is because velocity is not constant, it is changing over time due to the acceleration.

This means that the values for x(t) and v(t) that the integrator produces over time are different from the true values for the functions of position and velocity over time. In the example above the distance travelled down the road is somewhat inaccurate because of the integrator.

Just how inaccurate is the Euler integrator? From basic physics we know that:

s = ut + 0.5at^2

That is, given a constant acceleration a, and an initial velocity u, we can work out how much distance (s) is travelled over the time t.

In our case, u=0 because the car is at a standing start, so:

s = 0.5at^2
s = 0.5(10)(10)^2
s = 0.5(10)(100)
s = 500 meters

If we use the Euler integrator above instead of solving exactly we get:

t=0: position = 0, velocity = 0
t=1: position = 0, velocity = 10
t=2: position = 10, velocity = 20
t=3: position = 30, velocity = 30
t=4: position = 60, velocity = 40
t=5: position = 100, velocity = 50
t=6: position = 150, velocity = 60
t=7: position = 210, velocity = 70
t=8: position = 280, velocity = 80
t=9: position = 360, velocity = 90
t=10: position = 450, velocity = 100

So when using the Euler integrator we have an inaccuracy of 50 meters for this simple calculation after only 10 seconds! The bad news is that this error keeps getting larger as time goes on.

One solution to this problem is to decrease the time step. For example we can reduce the time step to dt = 1/100th of second each Euler integration instead of one second. Doing this will get us a result much closer to the exact value.

However, no matter how much you reduce your timestep, the simple truth is that the error will always be there and that it will keep increasing over time. Given that this is an extremely simple simulation, imagine something as simple as adding a torque curve to the car, or adding gears. Suddenly the car’s acceleration is not a constant, it changes over time. Now there is error when integrating the velocity, and these errors are magnified even further when integrating the position.

If you use Euler then you are a bloody idiot

The bottom line is that the Euler Integrator is basically crap and you should never use it. We need a better alternative. One that is able to detect curvature in the derivatives when integrating a value, so it is reasonably accurate even when the derivatives change over the timestep.

Rather than introduce you to the vast array of different integrators that exist, I’m going to cut to the chase and go straight to the best. This integrator is called the Runge Kutta order 4 integrator aka RK4. This is the standard integrator used for numerical integration these days and is sufficiently accurate for just about anything required in game physics, given an appropriate timestep. As far as I know its safe to just pronounce “Runge Kutta” as it reads, but its quite ugly sounding so it is usually just referred to as RK4 when speaking.

Technically RK4 has error O(5) (read “order 5″) in the Taylor’s Series expansion of the solution to the differential equation. I’m not going to go into the details of deriving or explaining how an RK4 integrator is derived, but I will say intuitively that what it is doing is detecting curvature (change over time) when integrating down to the fourth derivative. RK4 is not completely accurate, but its order of accuracy is extremely good and this is what counts.

An RK4 integrator works by evaluating the derivatives at several points in the timestep to detect this curvature, then it combines these sampled derivatives with a weighted average to get the single best approximation of the derivative that it can provide over the timestep.

Implementing RK4 is not as hard as it looks

I could present to you RK4 in form of general mathematical equations which you could use to integrate some function using its derivative f(x,t) as is usually done, but seeing as my target audience for this article are programmers, not mathematicians, I will explain using code instead. From my point of view, processes like this are best described in code anyway.

So before we go any further I will define the state of an object as a struct in C++ so that we have both position and velocity values conveniently stored in one place.

    struct State
    {
         float x;          // position
         float v;          // velocity
    };

We’ll also need a struct to store the derivatives of the state values so we can easily pass them around to functions. The derivatives we store are velocity and acceleration:

    struct Derivative
    {
         float dx;          // derivative of position: velocity
         float dv;          // derivative of velocity: acceleration
    };

(A quick aside for those programmers who are mathematically inclined: the struct State represents the phase space vector x for the object which would be passed in to evaluate the derivative f(x,t) for the state x and time t, which is represented by the Derivative struct.)

The final piece of the puzzle that we need to implement the RK4 integrator is a function that can advance the physics state ahead from t to t+dt using one set of derivatives, then once there, recalculate the derivatives using this new state. This routine is the heart of the RK4 integrator and when implemented in C++ it looks like this:

    Derivative evaluate(const State &initial, float t, float dt, const Derivative &d)
    {
         State state;
         state.x = initial.x + d.dx*dt;
         state.v = initial.v + d.dv*dt;

         Derivative output;
         output.dx = state.v;
         output.dv = acceleration(state, t+dt);
         return output;
    }

It is absolutely critical that you understand what this method is doing. First it takes the current state of the object (its position and velocity) and advances it ahead dt seconds using an Euler Integration step with the derivatives that were passed in (velocity and acceleration). Once this new position and velocity are calculated, it calculates new derivatives at this point in time using the integrated state. These derivatives will be different to the derivatives that were initially passed in to the method if the derivatives are not constant over the timestep.

In order to calculate the derivatives it copies the current state velocity into the derivative struct (this is the trick to doing position and velocity integration simultaneously) then it calls the acceleration function to calculate the acceleration for the current state at the time t+dt. The acceleration function is what drives the entire simulation and in the example source code for this article I define it as follows:

    float acceleration(const State &state, float t)
    {
         const float k = 10;
         const float b = 1;
         return -k * state.x - b*state.v;
    }

This method calculates a spring and damper force and returns it as the acceleration assuming unit mass. What you write here of course is completely simulation dependent, but it is crucial that you structure your simulation in such a way that it can calculate the acceleration or force derivatives completely from inside this method given the current state and time, otherwise your simulation cannot work with the RK4 integrator.

Finally we get to the integration routine itself which integrates the state ahead from t to t+dt using RK4:

    void integrate(State &state, float t, float dt)
    {
         Derivative a = evaluate(state, t);                    // note: overloaded 'evaluate' just returns derivative at current time 't'
         Derivative b = evaluate(state, t, dt*0.5f, a);
         Derivative c = evaluate(state, t, dt*0.5f, b);
         Derivative d = evaluate(state, t, dt, c);

         const float dxdt = 1.0f/6.0f * (a.dx + 2.0f*(b.dx + c.dx) + d.dx);
         const float dvdt = 1.0f/6.0f * (a.dv + 2.0f*(b.dv + c.dv) + d.dv)

         state.x = state.x + dxdt * dt;
         state.v = state.v + dvdt * dt;
    }

Notice the multiple calls to evaluate that make up this routine. RK4 samples derivatives four times to detect curvature instead of just once in Euler integration. The important thing to understand is how it actually does this sampling.

If you look at the code above it should be clear what is going on. Notice how it uses the previous derivative when calculating the next one. When calculating derivative b it steps ahead from t to t+dt*0.5 using derivative a, then to calculate c it steps ahead using derivative b, and finally d is calculated by stepping ahead with c. This feedback of the current derivative into the calculation of the next one is what gives the RK4 integrator its accuracy.

Once the four derivative samples have been evaluated, the best overall derivative is calculated using a weighted sum of the derivatives which comes from the Taylor Series expansion. This single value can then be used to advance the position and velocity over dt as we did before in the Euler integrator.

Notice that even when using a complicated integrator such as RK4, it all boils down into something = something + change in something * change in time. This is because differentiation and integration are fundamentally linear operations. For now we are just integrating single values, but rest assured that it all ends up like this when integrating vectors, or even quaternions and matrices for rotational dynamics.

Conclusion

I have demonstrated how to implement an RK4 integrator for a basic physics simulation. At this point if you are serious about learning game physics you should study the example source code that comes with this article and play around with it.

Click here to download the source code for this article.

Here are some ideas for study:

  1. Switch from integrating velocity directly from acceleration to integrating momentum from force instead (the derivative of momentum is force). You will need to add “mass” and “inverseMass” to the State struct and I recommend adding a method called “recalculate” which updates velocity = momentum * inverseMass whenever it is called. Every time you modify the momentum value you need to recalculate the velocity. You should also rename the acceleration method to “force”. Why do this? Later on when working with rotational dynamics you will need to work with angular momentum directly instead of angular velocity, so you might as well start now.
  2. Try modifying the integrate method to implement an Euler integrator. Compare the results of the simulation against the RK4 integrator. How much can you increase the spring constant k before the simulation explodes with Euler? How large can you make it with RK4?
  3. Extend position, velocity and force to 3D quantities using vectors. If you use your intuition you should easily be able to extend the RK4 integrator to do this.

56 Comments

56 responses so far ↓

  • 1 yv // Sep 27, 2006 at 11:19 am

    I was looking for Runge-Kutta Integration Techniques on the web and stumbled on this article. Thank you for this wonderful explanation.

  • 2 pTymN // Oct 13, 2006 at 9:48 am

    Hey, thank you for providing actual code for RK4! I’m a little curious about RK4’s stability, because right now I’m using Euler @ 100Hz and it looks fine. If my simulation starts falling apart below 30Hz, would RK4 be stable down to 20Hz, or some sort of quantified value for the increased stability?

  • 3 Sajid // Oct 16, 2006 at 9:36 pm

    Hi Glenn,

    I believe their is a typo in the last equation:

    change in position over time dt = velocity * dt

    should be dx = velocity * dt

    regards
    Saj

  • 4 Glenn Fiedler // Oct 17, 2006 at 5:10 pm

    nah, you misread it - i’m saying the change in position (dx) over time dt = velocity * dt

    i’ll see what i can do to make it clearer, cheers

  • 5 Glenn Fiedler // Oct 20, 2006 at 11:56 am

    updated: changed to make it easier to read

  • 6 Kamal // Nov 24, 2006 at 7:50 am

    Thank you for the valuable information.

  • 7 Alex // Nov 30, 2006 at 3:12 am

    In the acceleration() function, you declare the parameter float t, but you never use it. Is this intended?

  • 8 Glenn Fiedler // Nov 30, 2006 at 12:25 pm

    yes, its intentional - in this case it is usused, but generally, you often want to apply forces parameterized by t (eg. think of applying a force that is a sin(t) )

  • 9 Alex // Nov 30, 2006 at 4:45 pm

    Ah ok, thanks for clearing that up. Makes sense.

  • 10 Jasper // Dec 2, 2006 at 6:47 pm

    I dont entirely get why the RK4 method works yet, but I am seeing two minor errors(regarding physics notation) eliminate each other. notice the line in evaluate():
    output.dv = acceleration(state, t+dt) the dimension(as in unit) of the left side is speed (L/T), and the right is acceleration (L/T^2).
    This is compensated in integrate():
    dvdt = 1.0f/6.0f * (a.dv + 2.0f*(b.dv + c.dv) + d.dv)
    where the left side is an acceleration and the right a speed, but then again the latter wasnt a speed but an acceleration because of the previous error.
    Note that the error is merely in the physical interpretation the variable names suggest. This would be correct if in evaluate a factor dt is added, and that factor is divided in integrate, but that would just be a waste of cpu time. I think that you should call Derivative::dv Derivative::dvdt, then the names suggest the correct dimensions, only con is that name is longer.
    “If you use Euler then you are a bloody idiot”
    I know you partly retracted this in another article, but its quite a exaggeration.. Eulers method is a lot simpler, a child could think of that. Also for all potential users know (i know) it could give unforseen problems using RK4. Also it has to be “four times quicker to get stable” if acceleration is the function that costs the most cpu, and cost *sizeof(int) more space.(but space is usualy cheap in stuff like this) Probably in simulations you can get those acceleration() calls as one using that they are all about at one time, in that case it could be very handy.

  • 11 Glenn Fiedler // Dec 3, 2006 at 12:55 pm

    i’m sorry, you are incorrect - the derivative of velocity is acceleration, hence dv = acceleration( … ) is the correct units

    you are confusing velocity (s/t) with delta velocity (s/t/t = s/t^2)

    update:

    note that i sometimes refer to “dvdt” as just “dv” for brevity in the source code, note that i mean “dv” as “dvdt” not just some difference in v alone

    cheers

  • 12 scantid // Dec 18, 2006 at 3:36 pm

    so is runge pronounced runj or run-ge?

  • 13 Mike B // Dec 26, 2006 at 10:31 pm

    Thankyou, a very clear explanation of RK4, you also saved me from looking silly as I have been saying “Yewler” instead of “Oiler”!

    Regards Mike.

  • 14 Sam // Dec 29, 2006 at 12:36 pm

    Two things.

    First. Great article. clear, lucid, and technically accurate. Best explanation of Runge Kutta I’ve ever come across for programmers (not bad for mathematicians, either. Don’t get me wrong).

    Second. As a teacher of technical topics (Software, hardware) I’m jealous of your style.

    Thanks.

    Take care,

    Sam

  • 15 v // Jan 2, 2007 at 9:13 pm

    Your calculation for Euler integration at t=4 (and later) seems to be incorrect. The value for position should be 60, not 70, and for t=10 position will end up as 450 instead of 470.

  • 16 Glenn Fiedler // Jan 4, 2007 at 2:42 pm

    you are correct! thanks - i’ve fixed it

  • 17 sam // Jan 7, 2007 at 6:20 am

    You haven’t updated the inaccuracy, though:

    “So when using the Euler integrator we have an inaccuracy of 30 meters for this simple calculation after only 10 seconds!”

  • 18 Glenn Fiedler // Jan 8, 2007 at 12:43 am

    fixed! what would i do without you, dear readers!

    thanks

  • 19 Willy // Feb 12, 2007 at 3:02 pm

    I do have a question considering springs. If a spring is connected to two bodies and we are using rk4 to integrate, how would our acceleration/force method look like?

    We are changing the state of only ONE body a a time, but the spring uses the position of both bodies to calculate the current force. Shouln’t we change the state of BOTH bodies in order to calculate the correct force at the specified point in time?

  • 20 Glenn Fiedler // Feb 13, 2007 at 10:36 am

    you integrate both bodies together, ideally you have a single method that returns an array of forces to apply to the points — you cant update each body independently with RK4

    cheers

  • 21 joop renes // Feb 23, 2007 at 12:48 am

    there are special RK methods for ’second order’ ODE’s.
    like a = mF.I did both numerical analysis and theoretical physics and thereby know that it takes some effort to cram the two together, in fact i made a job out of it.
    BTW , chapeau for your article
    best regards
    joop renes

  • 22 bridges // Mar 12, 2007 at 5:30 am

    first of all, thanks for this article, its best explanation i´ve found so far.
    but i have a problem understanding the RK4 integrator.
    is it right that in your example the acceleration is changing over time?
    i am working on a physics simulation and i have a constant acceleration.
    so is dv the same in every derivative in case of constant acceleration?

  • 23 Glenn Fiedler // Mar 12, 2007 at 9:52 am

    yes. in the case of constant acceleration, there is not much point to using RK4, because in the 4 steps of the integration, you are just doing extra work to come up with the same constant dv

  • 24 Trevor Adams // Mar 15, 2007 at 11:58 am

    (bridges): Midpoint or RK2 may be what you need is you are just using constant acceleration, Euler as from the article, fails at even constant acceleration.
    (Glenn): Awesome article, thanks to your explanation of RK4, I was able to create a separate class structure for integrating ODEs(numerically) separate from the physics(although that is its primary purpose). The ODE solvers rely on operators and functions from a generic derivative class, and the physics just interprets its specific derivatives(velocity, force, and such). Thanks again Glenn.

  • 25 Wic // Mar 29, 2007 at 8:38 am

    I’m currently dabbling with using an embedded 3-axis accelerometer. I’m trying to find a way to get the velocity and position from it by twice-integrating the acceleration values from the device.

    Do you think it would be possible to use RK4 for this, ie just rewrite your acceleration() function so the it simply returns the current reading from the device?

  • 26 Glenn Fiedler // Mar 29, 2007 at 4:04 pm

    sure, but you’ll get drift over time - try it and see

  • 27 Glenn Fiedler // Mar 29, 2007 at 4:06 pm

    just hooking up the current value into the acceleration() wont work

    you’d be best to take the raw acceleration values to a buffer - then process them 4 at a time, using the middle ones as the extra samples

    failing this, try doing it with a simple explicit euler integration first, just to get your head around it

    cheers

  • 28 Glenn Fiedler // Mar 29, 2007 at 4:12 pm

    actually, i take this back - no i dont believe you’ll get any benefit with RK4, with the way i described it above, because fundamentally you need to be able to sample the derivative quantity in ways which your device does not support

    note that in the calculation of derivatives a,b,c,d that you pass the previous derivative each time you evaluate the next, eg. evaluating derivative b, requires derivative a, c requires b etc. — this is meaningless when you just have a discrete function of a(t), there is no way for you to do this calculation

    so i’d say, you probably need a different technique, which will be more like a filter, not RK4

    failing that, you could just try euler integration of acceleration to find velocity, then euler integrate velocity to find position - and see what sort of results you get

    cheers

  • 29 Wic // Mar 30, 2007 at 2:03 am

    Thanks! Yes, you’re probably right. According to wikipedia the a,b,c,d are different slopes calculated during the interval, which in the case of discrete acceleration is not possible to get at.

    Problem, from what I’ve read, is that using euler with an accelerometer is bound to give lots of errors very fast (ie http://instruct1.cit.cornell.edu/courses/ee476/FinalProjects/s2005/mouse%20webpage%20KM249_AK288/conclusion.htm). Dunno what other methods to use, I may have read something about using Simpsons Rule, whatever that is. :-)

  • 30 Amar // Apr 11, 2007 at 3:42 pm

    Awesome and very cool way of explaining things to programmers. I liked your approach. Thank you bro…

  • 31 Naveen // May 10, 2007 at 10:14 pm

    Don’t disparage Verlet methods - RK4 is accurate enough for game simulations, but unfortunately does not conserve energy over long periods of time (which doesn’t really matter for game physics, but does if you want to do real physics). Google “symplectic integrators” for more details.

  • 32 Dave // Jul 10, 2007 at 3:40 pm

    I love your writing style! “If you use Euler then you are a bloody idiot” Love it ;) Thanks for the great explanation!

  • 33 Martin Rhodes // Aug 13, 2007 at 7:23 am

    Very interesting and educational piece, just what I was looking for.

    While you are right about the pronunciation of Euler being “Oiler” in his native tongue, I doubt you’ll ever hear people pronounce Einstein as “AynShtine” or Heisenberg as “HaysenBehrg”, so I would like to think that “Yewler” is a perfectly acceptable, anglicised way of saying his name (Just like we say “IneStine” or “Hisenburg” instead of their actual names).

    That’s the only point in your write-up that I had any sort of issue with ,)

    Thanks again!

  • 34 Glenn Fiedler // Aug 13, 2007 at 4:17 pm

    i’ve been laughed at for saying yewler, live and learn :)

  • 35 moj // Sep 11, 2007 at 10:27 pm

    Thanks for the great document Glenn!

  • 36 capn_midnight // Dec 27, 2007 at 12:09 am

    Well, the problem with updating our displacement in your original Euler example is that you didn’t do it right. Under acceleration change in displacement is the integral of change in velocity. An integrator such as what you have demonstrated approximates this integral, thus the name “integrator”. But there is no need to approxiamate, we can just include the integral in our calculations:

    d’ = d + v*t + 0.5*a*t*t
    v’ = v + a*t

    we can quite easily see that this is “right” because the change in velocity is the exact derivative of the change in displacement with respect to change in time. If we take the derivative of change in velocity with respect to change in time, we get a’ = a, which again holds to the basic definitions of velocity being the first and acceleration being the second derivative of displacement.

  • 37 Glenn Fiedler // Jan 2, 2008 at 10:10 am

    sure, but what you described there is ballistic integration not euler integration - whats your point? :)

  • 38 s+@n // Feb 23, 2008 at 1:41 pm

    May I just ask why the position has to be updated before the velocity?
    Why not the other way?

    If you do it the other way, what are the consequences?

    Thank you.

  • 39 Anonymous Engineer // Feb 27, 2008 at 11:04 pm

    Euler, Improved Euler and Runge-Kutta (4th Order) are all taught as numerical methods at my university in the “Differential Equations” class.

    I hated doing them by hand because I would always mess up so I wrote a C++ program for each method (yes, it was easier and it worked). I remember we had to compare the error values and such for the three methods and Euler’s method is only accurate if you choose a very small step size, whereas Runge-Kutta is much MUCH more accurate with a pretty large step size.

    Great work on explaining, hope to see more on other math principles around the site.

  • 40 Rias // Mar 28, 2008 at 1:30 am

    Great page been looking 4 something like this. I was wondering if you could help. I need to RK4 quaternions, how would the code above need to be changed to achieve this? thanx

  • 41 Glenn Fiedler // Mar 28, 2008 at 9:54 am

    This article explains how:

    http://www.gaffer.org/game-physics/physics-in-3d

  • 42 Vobla // Apr 26, 2008 at 9:24 am

    Hi,
    Brilliant article (and others too). I have a question though. Why do you use references of variables as a parameters in a method calls if you do not intend to change their value?

    Derivative evaluate(const State &initial // <-
    float acceleration(const State &state // <-
    void integrate(State &state // <-

    In my opinion code gets really messy.. But what’s the bright side? :)

    Cheers.

  • 43 Glenn Fiedler // Apr 26, 2008 at 7:24 pm

    well, passing is as reference avoids a copy - and the state structure can get quite large, so this is important

    now, when we want to avoid the copy and dont want to change the value, we use a const reference to pass in

    this is all standard c++ practice!

    cheers

  • 44 Joe V // Apr 28, 2008 at 4:02 pm

    Brilliant explanation! Thank you.

  • 45 Steve Davis // May 28, 2008 at 4:16 am

    Excellent indeed!

    Thank you for publishing this (in fact thanks for the entire series)!

  • 46 Steve Davis // May 28, 2008 at 4:19 am

    …it did strike me when reading that if you were doing updates at each dt=1 you’d be more accurate to use… newpos = pos + vel + 0.5 * acceleration …which would also save on a bit of math!

  • 47 Glenn Fiedler // May 28, 2008 at 10:39 am

    sure, thats just

    s = ut + 1/2at^2

    its a ballistic integrator, works perfectly for constant acceleration

    but, game engines don’t often have constant acceleration all the time =)

  • 48 Jay Lemmon // May 28, 2008 at 1:32 pm

    I’ve been trying to find out what the integration method for position: r(t) = r(0) + v(0) * t + a(0)/2 * t ^ 2 is called. You seem to call it a ballistic integrator. I’ve also heard it called a “parabolic” integrator by Erin Catto in the Bullet Physics forum. However googling for either terms doesn’t provide any useful references. The only reference I can find to it is on Wikipedia where it’s a member of the SUVAT equations (so I call it a SUVAT integrator for lack of a better term).

    I’d greatly appreciate any links to references on what to call it. Makes me feel less stupid when I discuss it if I know what it’s called :P

  • 49 Steve Davis // May 29, 2008 at 2:43 am

    @48 - trajectory may be a better search term - remembering that g is just a constant a

  • 50 Jay Lemmon // May 29, 2008 at 12:09 pm

    trajectory isn’t useful either. I get links, but nothing that talks about it from a numerical integration standpoint. I’d like to write an article on it for wikipedia, but I’d need a definate reference on what to call it to proceed :/

  • 51 Tom // Jun 19, 2008 at 5:54 pm

    Great job my friend.

  • 52 Gravity // Aug 1, 2008 at 4:40 am

    Hi,

    Great article!. I’m having trouble understanding the evaluate function. Yes I see that you’re getting the current state vector by using the derivative values passed into the function, but what I don’t understand is why you’re setting the rate of change of velocity in the derivative to the current velocity.

    Thanks.

  • 53 Gravity // Aug 1, 2008 at 4:54 am

    Sorry for my stupid question above. I’ve just looked at the source code and found that you’ve overloaded the evaluate functions. I was looking at the wrong one!. D’oh.

    Keep up the good work. :)

  • 54 John Connors // Aug 16, 2008 at 12:01 pm

    Apparently I’m a bloody idiot ;-) I agree with you about RK4 being vastly superior to Oily’s method, but am struggling to work out how to apply RK4 to quaternions for angular velocity..

  • 55 John Connors // Aug 16, 2008 at 12:03 pm

    And I’m even more of a pratt, now as I’ve read the other comments and found youv’e already addressed this. Gah!

  • 56 grabovski // Aug 28, 2008 at 1:17 am

    Thanks, now that is one useful, easy to comprehend article!

Leave a Comment