• 15
• 15
• 11
• 9
• 10

# 2D Rigid Body Collision Response

This topic is 2504 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I've recently been writing a 2D physics engine in Java, and I have been using oliii's PollyColly tutorials to help me with the coding. My engine only support Box's currently, but I found an annoying glitch. Whenever there are two contacts points (such as a box falling to the ground) the response does not exert enough impulse. In the code, it simply uses the same collision response for 1 contact point when calculating response for 2 contacts except it repeats it for both points.

eg - A box falling onto a static horizontal plane...both objects are parallel - so two contact points
Second plane is static, so for the plane 1 / mass = 0 (I removed these from the formula)

Impulse Mag. = v * nc / (1 / mass + (ra x nc) * (ra x nc) / moi) <----- With rotation
Impulse Mag. = v * nc / (1 / mass) <------ Without rotation
v = relative velocities at contact point
nc = normal of the collision
ra = Vector from center of A to contact point
moi = moment of inertia

As you can see from the example collision there should obviously be no rotation, so we should be able to use either formula. These two equations will only yield equal results when (ra x nc) * (ra x nc) = 0.

For each contact point, nc will be straight upwards and ra will be at 225 or 315 degrees (from the center of the box, to each of its lower corners). Since ra x nc = |ra| * |nc| * sin(theta), and sin(theta) * sin(theta) will always equal 0.5, the first equation will never yield a correct result.

For now, I just merge the two contact points into one point located in between them. Although this looks good, I don't think it is correct...

What is the correct solution for this collision response?

##### Share on other sites

For now, I just merge the two contact points into one point located in between them. Although this looks good, I don't think it is correct...

What is the correct solution for this collision response?

Yeah, that averaging solution won't work correctly on anything other than a plane... To solve this correctly you'll need to use a solution that takes both contacts into account and solves for the global solution, rather than solving individually... You can use Erin Catto's sequential impulses as an easy way to solve this. There are other solutions but they're much more mathsy and more tricky to understand

Cheers, Paul.

##### Share on other sites

Yeah, that averaging solution won't work correctly on anything other than a plane... To solve this correctly you'll need to use a solution that takes both contacts into account and solves for the global solution, rather than solving individually... You can use Erin Catto's sequential impulses as an easy way to solve this. There are other solutions but they're much more mathsy and more tricky to understand

Cheers, Paul.

I read the powerpoint, but i still don't see how to use that for this case....maybe i'm missing something...
I'm pretty new to all this physics engine stuff...

##### Share on other sites
As I remember, oliii in his tutorial also reduces contact points to 1 (he takes middle between several points) and it looks good. Sequential impulses looks good too, but I don't know - is it possible to make objects bounce with it (in Box2D demos I mention that bounce is missing).

##### Share on other sites

I read the powerpoint, but i still don't see how to use that for this case....maybe i'm missing something...
I'm pretty new to all this physics engine stuff...

Are you solving using impulses? If so you might have something like this (this is linear only, no rotation, for simplicities sake):

 double impulseMag = relV / (invMassA + invMassB) Vector2 impulse = impulseMag * contact.N; contact.ApplyImpulses(impulse); 

The version using sequential impulses would look like this:

 double impulseMag = relV / (invMassA + invMassB); double newImpulse = Math.Min(impulseMag + contact.m_impulse, 0); double change = newImpulse - contact.m_impulseN; Vector2 impulse = contact.m_normal * change; contact.ApplyImpulses(impulse); // store for next iteration contact.m_impulseN = impulse; 

Hope that helps,

Cheers, Paul.