Ghost collisions with speculative contacts in 2D

Started by
5 comments, last by Finalspace 8 years, 6 months ago

Hi there,

i am building up a platformer using a technique called speculative contacts.

Everything was going so smoothly, i get pretty fast really good results - but i now have encountered that nasty ghost collisions issue :-(

I dont want this to happen anymore:

- Player stands directly besides the side of a block which is small enough so that the player can jump over.

- Player jumps upwards - without any x-motion at all

- Gravity pulls player down until it reaches the edge of the block

- Player stops due to internal edge collisions - even there are no x-motion at all :-(

Made a short video to show this problem:

This behavior is normal in a speculative context, because it creates an edge vs edge contact with a "near" zero separation.

Also this can happen on the x-direction as well, when the player stands on boxes and collides with their internal edge :-(

What is a good reasonable way to solve this problem? I have just a bunch of rigid bodies without any relation at all.

Please help me to tackle this problem.

Advertisement

I would not call this an internal edge issue. Obviously there are no *internal* edges involved in the problem I see in your video. I understand what you mean, but this looks more like a ghost collision problem.

It is really difficult to tell what is going wrong there without seeing the code and debug it. I would render the collision margin in red around your box shapes and then also the closest points once you compute the witness points for the speculative contacts. You should not get an upwards normal in your case. Maybe your margins are wrong or too tight.

You can always disable speculative contacts if things are not fast.

I would not call this an internal edge issue. Obviously there are no *internal* edges involved in the problem I see in your video. I understand what you mean, but this looks more like a ghost collision problem.

It is really difficult to tell what is going wrong there without seeing the code and debug it. I would render the collision margin in red around your box shapes and then also the closest points once you compute the witness points for the speculative contacts. You should not get an upwards normal in your case. Maybe your margins are wrong or too tight.

You can always disable speculative contacts if things are not fast.

Yay you are right, its indeed a ghost collision - wrong term i used. I corrected the title.

But what do you mean by "disable speculative contacts"?

Do mean the same approach bullet use? Using speculative contacts when there is a separation (d > 0) only and use another solver like "sequential impulse" for the normal penetration/touching case?

Speculative contacts is a cheap version to prevent tunneling. If objects are too slow to tunnel you don't need speculative contacts, right? So how to we know if an object might potentially tunnel. Given the velocities of two rigid bodies, v1, v2, w1, and w2. And also the maximum leverarm r_max (this is the length of the aabb extent in your example) and the the min thickness (this is the minimum element of your aabb) r_min.

if ( ( v2 - v1 ) * n - |w1| * r1_max - |w2| * r2_max < - ( r1_min + r2_min ) / dt ) -> no tunnel

In other words, if the worst case relative velocity along the contact normal is less than the sum of the minimum thickness divided by the timestep the objects cannot tunnel. This is just an example to give you the idea and you can of course use any variation of this. The trick for the angular velocity is simply to take the length of the angular velocity times the maximum lever arm.

In general I advice against speculative contacts. It appears to be a simple solution for a very hard problem, but in reality it creates more problems then it solves. If I look at your example I don't see any need for speculative contacts or CCD. So my suggestion would be to use simple sequential impulses (e.g. maybe learning from Box2D light).

HTH,

-Dirk

PS: I edited the formula. I am assuming that the relative velocity is penetrating along the normal if less than zero (assuming the normal points from 1 -> 2)

Speculative contacts is a cheap version to prevent tunneling. If objects are too slow to tunnel you don't need speculative contacts, right? So how to we know if an object might potentially tunnel. Given the velocities of two rigid bodies, v1, v2, w1, and w2. And also the maximum leverarm r_max (this is the length of the aabb extent in your example) and the the min thickness (this is the minimum element of your aabb) r_min.

if ( ( v2 - v1 ) * n - |w1| * r1_max - |w2| * r2_max < - ( r1_min + r2_min ) / dt ) -> no tunnel

In other words, if the worst case relative velocity along the contact normal is less than the sum of the minimum thickness divided by the timestep the objects cannot tunnel. This is just an example to give you the idea and you can of course use any variation of this. The trick for the angular velocity is simply to take the length of the angular velocity times the maximum lever arm.

In general I advice against speculative contacts. It appears to be a simple solution for a very hard problem, but in reality it creates more problems then it solves. If I look at your example I don't see any need for speculative contacts or CCD. So my suggestion would be to use simple sequential impulses (e.g. maybe learning from Box2D light).

HTH,

-Dirk

PS: I edited the formula. I am assuming that the relative velocity is penetrating along the normal if less than zero (assuming the normal points from 1 -> 2)

I was using speculative contacts because it gives me a extremely stable simulation even with small number of iterations without any warmstarting at all.

But i am not that fixed on that technique, so i will give sequential impulse a try - contacts are already remembered so that warmstarting is no problem at all.

Also i fixed the ghost collisions in the contact generator a bit - so that i get the ghost collision only once and the player will eventually fall down due to gravity.

You can use SI with small number of iterations and have stable results without warmstarting (obviously not really tall stacks, but pretty good).

Here's something even more naive than SI (very similar though) that still stable enough for a lot of games: link

You can use SI with small number of iterations and have stable results without warmstarting (obviously not really tall stacks, but pretty good).

Here's something even more naive than SI (very similar though) that still stable enough for a lot of games: link

Yeah i know that already, as a matter of fact - this has gets me started into physics programming since 2013.

So good job on that ;-)

See results on that time:

This topic is closed to new replies.

Advertisement