RCIX RCIX -4 years ago 100
C# Question

Verlet Integration is blowing up my physics engine

I'm building a physics engine and i had some sort of "pseudo-verlet" thing going and i wanted to upgrade it to "real" verlet. So i found an article and set to work. After i added what i think is a good approximation, the engine doesn't work anymore. Can someone help me understand what i'm doing wrong?

My main physics body class's update, apply force, and apply impulse systems:

public void Update(float timestepLength)
{
if (!this._isStatic)
{
Vector2 velocity = Vector2.Subtract(_position, _lastPosition);
Vector2 nextPos = _position + (_position - _lastPosition) + _acceleration * (timestepLength * timestepLength);
_lastPosition = _position;
_position = nextPos;
_acceleration = Vector2.Zero;
}
}

public void ApplyForce(Vector2 accelerationValue)
{
if (!this._isStatic)
_acceleration += (accelerationValue) * _mass;
}
public void ApplyImpulse(Vector2 impulse)
{
if (!this._isStatic)
_acceleration +=-1 * impulse;
}


Edit:
I've fixed it and it works like a charm, but i have two questions about the following code:


  • Is the impulse application code correct, and if not what should it be?

  • How do i change the position property so that setting it preserves the current velocity of the body?



Here is the code:

public Vector2 Position
{
get { return _position; }
set { _position = value;}
}
public void Update(float timestepLength)
{
if (!this._isStatic)
{
Vector2 velocity = Vector2.Subtract(_position, _lastPosition);
Vector2 velocityChange = Vector2.Subtract(velocity, Vector2.Subtract(_lastPosition, _twoStepsAgoPosition));
Vector2 nextPos = _position + (_position - _lastPosition) + _acceleration * (timestepLength * timestepLength);
_twoStepsAgoPosition = _lastPosition;
_lastPosition = _position;
_position = nextPos;
_acceleration = Vector2.Multiply(velocityChange, timestepLength);
}
}

public void ApplyForce(Vector2 force)
{
if (!this._isStatic)
_lastPosition -= force;
}
public void ApplyImpulse(Vector2 impulse)
{
if (!this._isStatic)
_acceleration +=-1 * impulse;
}

Answer Source

as a reference to others... the verlet paper you are probably refering to is this: advanced character physics made by the team who created hitman and was one of the first to have ragdoll based physics

anyhow... the original code they used was:

 void ParticleSystem::Verlet() {
       for(int i=0; i<NUM_PARTICLES; i++) {
             Vector3& x = m_x[i];
             Vector3 temp = x;
             Vector3& oldx = m_oldx[i];
             Vector3& a = m_a[i];
             x += x-oldx+a*fTimeStep*fTimeStep;
             oldx = temp;
       }
 }

and you are right that your code does a similar thing.

The one thing which always blew up my simulations was the use of a too big timestep. Also, with this verlet integration, make sure that the timestep you use is constant throughout the game. (e.g 30 frames/sec for instance (so timestep is 1/30)) and doesn't fluctuate. If it does you should use the time corrected verlet integration which accounts for this

EDIT:

answer to question2: to move your position (without changing velocity/acceleration) just update the position to the new position, and then as an extra step add the delta of this movment(so newPosition-oldPosition) to the oldposs, so this gets updated accordingly.

answer to question1: Impulse is the force applied to an object over a period of time. So your solution is not correct. The impulse would be that over X timesteps(or frames), you call your applyForce function with a fixed force.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download