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).
Correctly misusing Box2d to get time of impact
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
-
- Prole
- Posts: 11
- Joined: Sat Jul 19, 2014 2:57 am
Re: Correctly misusing Box2d to get time of impact
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.
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.
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.
What happens in this case is, the new body is inserted in the scene,creating and destroying bodies for a single frame to try and determine if they actually collide
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.
-
- Prole
- Posts: 11
- Joined: Sat Jul 19, 2014 2:57 am
Re: Correctly misusing Box2d to get time of impact
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.
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.
Re: Correctly misusing Box2d to get time of impact
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.To make sure we read the same thing about the speedlimit, it's 2.0 distance units per world:update, right?
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 do that too when I'm using a constant time step.I call world:update multiple times in a frame
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.
-
- Prole
- Posts: 11
- Joined: Sat Jul 19, 2014 2:57 am
Re: Correctly misusing Box2d to get time of impact
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.
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.
-
- Prole
- Posts: 11
- Joined: Sat Jul 19, 2014 2:57 am
Re: Correctly misusing Box2d to get time of impact
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.
Re: Correctly misusing Box2d to get time of impact
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.
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.
Who is online
Users browsing this forum: Ahrefs [Bot], Bing [Bot], Google [Bot], zingo and 4 guests