![]() |
|
Separating Axis Theorem - Point of Collision |
Fishcake
Member #8,704
June 2007
![]() |
I'm using the Separating Axis Theorem (SAT) for collision detection in my physics engine. It's working perfectly, but now I need to know the point of collision between the two rigid bodies. Is there a way to find it?
|
Paul whoknows
Member #5,081
September 2004
![]() |
You could calculate the center of mass of both bodies and then calculate the collision between them. ____ "The unlimited potential has been replaced by the concrete reality of what I programmed today." - Jordan Mechner. |
Stas B.
Member #9,615
March 2008
|
Umm... You take your axis of minimal overlap, project the first polygon on it, find the point(s) with the biggest dot product results, then do the same with the second but find the points with the smallest dot product results. Those are the points you're looking for, more or less. |
Thomas Harte
Member #33
April 2000
![]() |
As you're almost certainly aware, if two rigid bodies are overlapping then there is no single point of collision — there's an entire patch. First of all, are you in 2d or 3d? For SAT to work you have to use convex bodies, so presumably that's exactly what you're doing? My solution (as used by the little physics demonstration on my members.allegro.cc page, linked in my sig; check out the top entry on 'Directionless Pointers') was to calculate the minimum separation vector of the two bodies (i.e. the smallest amount that they can both be moved so as to no longer overlap), apply that and then use the final point at which the two are touching as a contact point. If the end result was that there was an edges of contact, I handled that by doing the calculations for a single contact point, located in the centre of the line. The easiest way to get minimum separation is to work out the Minkowski sum of the two objects and find the quickest escape route. That's pretty trivial for convex shapes in 2d (as in my little physics thing), but relatively hard for non-convex and 3d shapes. So, the exact solution from here depends on the type of shape you're dealing with. Any hints? [My site] [Tetrominoes] |
Stas B.
Member #9,615
March 2008
|
Now that I think of it, I was wrong... What I suggested would result in a whole bunch of points, some of which are useless. I'll need to think about it for a few minutes. |
Fishcake
Member #8,704
June 2007
![]() |
Quote: First of all, are you in 2d or 3d? For SAT to work you have to use convex bodies, so presumably that's exactly what you're doing? Yes, I'm in 2D and all my shapes are going to be convex. Quote: My solution (as used by the little physics demonstration on my members.allegro.cc page, linked in my sig; check out the top entry on 'Directionless Pointers') was to calculate the minimum separation vector of the two bodies (i.e. the smallest amount that they can both be moved so as to no longer overlap), apply that and then use the final point at which the two are touching as a contact point. If the end result was that there was an edges of contact, I handled that by doing the calculations for a single contact point, located in the centre of the line. The easiest way to get minimum separation is to work out the Minkowski sum of the two objects and find the quickest escape route. That's pretty trivial for convex shapes in 2d (as in my little physics thing), but relatively hard for non-convex and 3d shapes.
Wow, that's a lot of stuff. My brain is too tired to read it.
|
Stas B.
Member #9,615
March 2008
|
So, Thomas, you used the final point at which the two polygons are touching as a contact point? No way, that's brilliant. |
Thomas Harte
Member #33
April 2000
![]() |
Oh, I explicitly used the Minkowski Sum. The Minkowski Sum is the shape that would be formed if you took a stamp in the shape of one of the objects and printed it at every point contained in the other object. So, e.g. the Minkowski Sum of a rectangle and a circle is a bigger rectangle with rounded corners. If you want to be formal then suppose A is made up of the collection of points {(x, y) s.t. (x, y) is inside object A} and B is made up of {(u, v) s.t. (u, v) is inside object B} then their Minkowski sum is made up of {(x+u, y+v} s.t. (x, y) is inside object A and (u, v) is inside object B}. For objects A and B, what I actually use is the Minkowski Sum of A and -B. -B is the shape formed when you take every point (x, y) in B and reposition it at (-x, -y). Which, because of the way that basis vectors work, is the same thing as rotating B by a half circle. But thinking of it as (-x, -y) is more instructive. If you calculate the sum of A and -B then you can use it to do an overlap test on A and B. Just check if the point (0, 0) is inside the sum. If it is then obviously there is at least one (x, y) that has the same value as at least one (u, v). So there is at least one place where the both the objects lie on top of each other. If you move object A by (m, n) then the points (x+u, y+v) turn into (x+m+u, y+m+v). So movements on A directly move the sum by the same amount. Movements on B mov the sum of A and -B by the opposite amount. Therefore, the shortest amount that you can move A to separate it from B is whatever the shortest vector is from (0, 0) to a point on the outside of the Minkowski Sum. Or you can move A by half the vector and B by half the vector in the other direction. Or whatever you want along those lines. The "Convex Minkowski Sum Demo" on my page is possibly worth checking out here. It lets you manipulate the shape of two objects, shows you their sum and keeps them separated. Also, I think it's Allegro-based. It uses a really simple winding algorithm. For each face of A, find the point of -B that is furthest in front of it when B is positioned on either endpoint of the face. Then move that face out by that much. That'll leave gaps where the corners of A were. Fill them in by using faces from B, with B positioned on the corner. Specifically, if face 1 connects to face 2 at vertex q on object A, vertex n of object B is furthest in front of face 1 and vertem m is furthest in front of face 2 then add to the sum:
It's maybe easier to think of graphically. Imagine taking object B and tracing round the outside of object A. Obviously the bit that sticks out furthest when going round the edges will print of the top of all the bits that are further inside. And at the corners you'll be left with whatever part of the outline of B normally falls between the sticky out bits. Obviously if the shapes weren't convex then the answer would be more complicated. Anyway, that gives you the sum without any difficult arithmetic — it's really just a sorting problem. Assuming the objects overlap then from that you can find the quickest escape vector from (0, 0) using normal 'distance to plane' stuff. Then you can push the objects apart. A neat side effect is that when you're building the sum, each side is effectively the combination of a point from one object and a face from the other. When the objects are separted, that point will be in contact with that face. Testing for face to face rubbing just means detecting when the sum has two faces in a row with the same normal. It's definitely not worth worrying about at first and can probably be ignored indefinitely. EDIT: or use Stas B's approach for a pretty good approximation. This stuff gets harder in 3d, because it's harder to figure out what geometry to fill in at the corners. The best solution I've yet come up with is to duplicate lots of geometry at vertices and do a quickhull (minimum convex hull algorithm) on all that. This is partly related to the way that I've never managed to think of a better way to determine which faces of a convex 3d object are visible from a certain angle without testing every single one of them. Probably some people who are smarter, have read more or have thought about it for longer have some solutions to that sort of thing. I'm pretty sure it boils down to the fact that the faces of a convex 2d object are trivial to sort 'by normal', but the faces of a convex 3d object aren't. At least to me. So, waffle over, key point: approximations that map well to 3d are worth thinking about too. [My site] [Tetrominoes] |
Stas B.
Member #9,615
March 2008
|
Hmm... That's actually quite interesting. |
Thomas Harte
Member #33
April 2000
![]() |
Quote:
Hmm... That's actually quite interesting. I was confused by your suggestion to take points from both objects and idiotically incorporated the need to find a collision normal into my thoughts, because I'd started thinking about rigid body dynamics and not what the original author was asking. I think our suggestions end up being pretty much the same thing if you add the fact that the axis of minimum overlap is actually a plane normal for one of the objects. Then the point you're looking for is the one from the other object that penetrates most deeply into that. I'm not sure why you'd collect points from both objects. Probably I've misunderstood? EDIT: oh, if you want to test for point to point collisions separately to point to edge collisions with the Minkowski Sum solution, just test whether the escape vector exists through a vertex of the sum. And then obviously use the escape vector itself as a collision normal, if you need one. [My site] [Tetrominoes] |
Stas B.
Member #9,615
March 2008
|
I need points from both polygons because I don't know which polygon has the point and which has the edge (in the point vs. edge case). In some edge vs. edge cases, you'd get two contact points, one from the first object, one from the second. I don't see any way around finding the closest features on both polygons and filtering the needed ones. [EDIT] This is slightly off-topic, but I was wondering if... |
Thomas Harte
Member #33
April 2000
![]() |
Quote: I need points from both polygons because I don't know which polygon has the point and which has the edge (in the point vs. edge case) Surely whichever polygon owns the edge with the normal that provides the axis of minimum overlap is the one that supplies an edge, and specifically it supplies that edge? EDIT: Quote: I don't see any way around finding the closest features on both polygons and filtering the needed ones. Obviously you mean other than through the Minkowski Sum? [My site] [Tetrominoes] |
Stas B.
Member #9,615
March 2008
|
HAHAHAH. Oh my god. Of course. I'm so dumb. [EDIT] Never mind... [EDIT 2] You DO have to find points on the 2nd object in edge vs. edge cases where one of the shapes has parallel edges (like a box) because sometimes you'd end up with one contact point on one object and another one on the other, but the point on the 2nd object won't be essentially one of the points you used to generate the normal. |
Fishcake
Member #8,704
June 2007
![]() |
Hmm...I think I'm going to try using the Minkowski Sum. It seems interesting.
|
Stas B.
Member #9,615
March 2008
|
That's crazy. |
Fishcake
Member #8,704
June 2007
![]() |
I've finally finished the demo, which I have already posted in the depot. I had problem understanding Thomas Harte's algorithm of calculating the minkowski sum polygon, so I just used the Monotone Chain algorithm to produce a convex polygon from the set of points produced from the minkowski sum of two polygons.
|
|