How to determine collision with a specific polygon face

Topics: Developer Forum
Jul 9, 2010 at 7:15 PM

Say I have a rectangle fixture/body and I want to know which of the 4 faces of the rectangle another body collided with. How would I do this? I tried using the LocalNormal of the contact manifold, but that did not seem to be the consistent result I expected. Is there some other way to do this?

Jul 11, 2010 at 9:26 PM

Here's an extension I added to the vertices class to figure out which edge is the closest to a given point:

 

public int GetClosestEdge(Vector2 point)
{
    int closest = -1;
    float lowestDistance = float.MaxValue;

    for (int i = 0; i < this.Count; i++)
    {
        var diff = point - this[i];
        var dist = diff.LengthSquared();
        if (dist < lowestDistance)
        {
            lowestDistance = dist;
            closest = i;
        }
    }

    var p = this[closest];
    var edge1 = GetEdge(closest);
    edge1.Normalize();
    edge1 = p + edge1;

    var edge2 = -GetEdge(PreviousIndex(closest));
    edge2.Normalize();
    edge2 = p + edge2;

    if ((point - edge1).LengthSquared() < (point - edge2).LengthSquared())
    {
        return closest;
    }
    else
    {
        return PreviousIndex(closest);
    }
}

Basically it works by first finding the closest vertex to the given point. Once you have that it needs to make a choice whether to take the edge leading to that vertex or the edge leading away. The way it makes a choice is to calculate the point along each edge that is one unit away from the closest vertex; whichever point is closer the given point is chosen as the closest edge.

 

This may not be the most optimal way of finding the closest edge to a point, but I gave up trying to get the contact list in OnCollision to produce any meaningful results. Sometimes it would use vertexes in one polygon, sometimes in the other; most of the time the vertex index it would return is an invalid index and doesn't belong to either of the polygons involved in the collision.

 

So basically I do this:

 

int edge = body2.WorldVertices.GetClosestEdge(contactList[0].Positon);

 

And in all my tests it seems to get the edge that the collision occurred on.

Jul 11, 2010 at 10:29 PM

Ok thanks, I'll give it a try. But where's the implementation of GetEdge(). It's not built in to the engine. Is that your function?

Jul 11, 2010 at 10:40 PM

Oh I should mention this is in FP3.0. It appears as though your implementation is for FP2.x.

Jul 12, 2010 at 4:22 AM

Ah yeah, this is 2.1.3. Sorry; I figured most people would be using that since 3.0 isn't stable yet.

 

Unfortunately I don't have any experience with 3.0. Maybe it's implementation provides useful collision data on the geometry OnCollision event?