This project has moved. For the latest updates, please go here.

Runge-Kutta 4 integration not helping?

Topics: Developer Forum, User Forum
Jan 26, 2008 at 11:21 PM
I tested the engine by stacking up 50 boxes, and discovered that in this situation, the boxes always collapse unless you increase the update frequency.
So, as an experiment, I tried writing an RK4 integration method that I hoped would improve the results. It didn't seem to make much difference. Maybe numerical error isn't what's causing the problem with stacked boxes, but I thought I'd post my code and see if I'm doing something wrong.

This is from Body.IntegratePosition(float dt):
//Integrating position:
//dp.X = bodylinearVelocity.X * dt;   //CHANGED
//dp.Y = bodylinearVelocity.Y * dt;   //CHANGED
RK4(force.Y * inverseMass, dt, bodylinearVelocity.Y, position.Y, out position.Y);   //CHANGED
RK4(force.X * inverseMass, dt, bodylinearVelocity.X, position.X, out position.X);   //CHANGED
previousPosition = position;
//INLINE: Vector2.Add(ref previousPosition, ref dp, out position);   //CHANGED
linearVelocityBias.X = 0;
linearVelocityBias.Y = 0;
bodyAngularVelocity = angularVelocity + angularVelocityBias;
//rotationChange = bodyAngularVelocity * dt;   //CHANGED
RK4(inverseMomentOfInertia * torque, dt, bodyAngularVelocity, rotation, out rotation);   //CHANGED
previousRotation = rotation;
//rotation = previousRotation + rotationChange;   //CHANGED

And this is the RK4 method itself:
//Works where where yp = ypp * t, in other words, where y'(t) is linear and depends only on t.
//example: RK4(acceleration, dt, initialVelocity, initialPosition, out newPosition)
float d6 = 1 / 6f;
private void RK4(float ypp, float dt, float yp0, float y0, out float y1)
      float halfdt = dt * 0.5f;
      float k1 = yp0;
      float k2 = (halfdt * ypp) + yp0;
      float k3 = k2;
      float k4 = (dt * ypp) + yp0;
      float dy = (dt * d6) * (k1 + 2*k2 + 2*k3 + k4);
      y1 = y0 + dy;