Correctly misusing Box2d to get time of impact

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
TomatoSoup
Prole
Posts: 11
Joined: Sat Jul 19, 2014 2:57 am

Correctly misusing Box2d to get time of impact

Post by TomatoSoup »

Given two physics objects that collide, how can I determine at what point in the frame they actually collided?

For instance, two polygon shapes are headed at each other such that, during the 1/60 second timestep, they collide. How can I use the callbacks and the various position/velocity getters before and after the world:update to determine the exact time of collision? For instance, if they hit at 0.01 seconds.

The reason I'm trying this is because I am working on a game that involves multi kilometer long entities traveling double digit kilometers per second billions of meters from the origin. I have written code that can coarsely determine if they're likely to collide using bounding-sphere-based continuous collision detection, but I'd like to use Box2d to compute if the bound polygons actually collide and what their rough change in velocity will be as a result of the collision.

So I'm creating and destroying bodies for a single frame to try and determine if they actually collide. There will only ever be 2 objects in the world at any time. After I compute the results of all of these collisions, I want to sort them by time of impact so that I can call the object callbacks in the correct order.

Like I said, misusing. But I understand what the consequences are and I find them to be acceptable. Most important is detecting the actual collision, which I am confident that box2d will provide with great precision. I just want a rough idea of the results of the physics (and I don't care about stacking stability).
User avatar
ivan
Party member
Posts: 1915
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Correctly misusing Box2d to get time of impact

Post by ivan »

Hello. Let me start by saying that Box2D has a max-velocity cap.
Keeping that in mind, there is no real way to determine the precise time of the collision.
Simply because the library solves all collisions during the timestep and moves on.
Imagine that you have 3 spheres (a,b,c) moving towards a single point at a constant speed.
Box2D handles collisions in pairs so the spheres will not collide simultaneously.
What I mean is Box2D will FIRST solve collision a-b and depending on the result will then solve a-c and b-c.
So the idea of 'simulations collisions' or a 'precise time of impact' doesn't make sense in this case.
However, if you use a reasonable timestep (which should be constant btw)
you can store the position (at the beginning of the time step)
and compare it with the position during the "PreSolve" callback.

max distance = initial velocity * time step
time of impact / time step = (initial position - position at impact)/max distance

time of impact = (initial position - position at impact)/initial velocity

If you use linear damping, joints or friction is acting on the body,
then the formulas get more complicated but I hope this helps.
creating and destroying bodies for a single frame to try and determine if they actually collide
What happens in this case is, the new body is inserted in the scene,
and if it overlaps with other bodies during the insertion,
it instantly 'pushes' them away so they don't overlap.
This is called 'positional correction' and happens in sub-steps, so
again, the notion of 'time of impact' is a little bit blurred in this case.
TomatoSoup
Prole
Posts: 11
Joined: Sat Jul 19, 2014 2:57 am

Re: Correctly misusing Box2d to get time of impact

Post by TomatoSoup »

To make sure we read the same thing about the speedlimit, it's 2.0 distance units per world:update, right? I was not aware of this but I think I can see how to work around it. So an object moving 10m/s given a .1s timestep will move 1, but an object moving 30m/s given a 0.1s timestep will only move 2, right? And an object moving 10m/s given a 0.3s timestep will also only move 2, right?

Thanks for pointing me to the preSolve callback. I tried whipping up a quick test .love to see which callback would give the most sensible results but I couldn't make much sense of them. To be totally explicit, preSolve gives me fixtures a and b, which give me bodies a and b, and their exact position at the time of impact?

But yeah, your formulas are exactly what I was aiming for.

To be more explicit on how I'm misusing Box2d, I call world:update multiple times in a frame, and sometimes not at all. For every candidate collision pair, I create two objects, tick the world one dt, record the results, then destroy the objects. Then I do that for the next pair.
User avatar
ivan
Party member
Posts: 1915
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Correctly misusing Box2d to get time of impact

Post by ivan »

To make sure we read the same thing about the speedlimit, it's 2.0 distance units per world:update, right?
The velocity limit is around 200-400 m/s which is quite high, but keep in mind that if you're working with very large objects (kilometers in radius) then the limit becomes more apparent.
Also, the velocity is clamped so you can't set it very large values like: body:SetVelocity(2^32)

"preSolve" happens before the collision is solved, at that point you can tell Box2D to ignore the collision or respond.
"postSolve" happens after the collision at which point Box2D reports what impulses were applied.
I call world:update multiple times in a frame
I do that too when I'm using a constant time step.

Generally speaking, the strength of Box2D is real-time physics so
if you find yourself creating/destroying a lot of objects or
setting the positions of bodies then there may be a simpler way.
TomatoSoup
Prole
Posts: 11
Joined: Sat Jul 19, 2014 2:57 am

Re: Correctly misusing Box2d to get time of impact

Post by TomatoSoup »

My reading is that the velocity limit is 2 units per update, so at 60hz that's 120u/s. Do you know what the velocity is clamped to?

And, I don't think you call world:update like I do. I call it a dynamic number of times depending on if objects are likely to collide or not. In all likelihood, most frames it won't be called.

There probably is something simpler, but I'm confident it's not available in Love2d.
TomatoSoup
Prole
Posts: 11
Joined: Sat Jul 19, 2014 2:57 am

Re: Correctly misusing Box2d to get time of impact

Post by TomatoSoup »

Also, I can tell you for a fact that you're wrong about velocity clamping. I just had an object move 2^32, and retain that velocity after update, by setting the timestep to 1/1000000000. So, as I read, velocity limits are purely a function of timestep.
User avatar
ivan
Party member
Posts: 1915
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Correctly misusing Box2d to get time of impact

Post by ivan »

Hey TomatoSoup, yes in previous versions the velocity cap was a constant value but it's been changed since 2.3.
Still, if you set a very large number for the velocity and you perform an update step the value would be clamped accordingly.
There are a number of other constraints too.
I could give you more suggestions if you post your .love file on here.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot], Google [Bot], zingo and 4 guests