Clipping objects

Topics: Developer Forum, User Forum
Nov 4, 2009 at 11:00 PM

Is there a way to know when two geometries are clipping? (because of tunneling or any other reason)

I don't want to avoid it, just to know when it happens (is for identifying when an object has been crushed between other two, for example).

Coordinator
Nov 4, 2009 at 11:44 PM

It depends on the detail you want. Do you want it shape specific or just an approximation? You could test against the AABB of the geometries and then do a distance check between the centers (position) of the geometries plus the size of the geometry.

Example:

If you have 2 circles that are 5 in radius (r). You can then check if they are intersecting by doing a check on each update. The check tests if the distance of the two circles are r+r away from each other. If they are less than r+r, they must be intersecting.
Problem is that you can have a lot of different sized shapes and for that you need to use the AABB of the geometries instead. And that again creates a new problem: the range check is not always accurate because of oddly sized objects. You could partly get around this using a tolerance.

--

All techniques used to prevent tunneling can also be used to detect if tunneling exists. Like the sweeping of geometries.

Example:

At timestep 0, your geometry at position p0 and a wall is a p7. If you run an update that moves 5*p, you will arrive at p5 once it updates. All is fine so far. Tunneling happens when you run another timestep and your geometry arrives at p10. It will have passed the wall at p7, and thus you tunneled it. One solution is to sweep the object using substeps inside the timestep. You simply move the geometry p1..p2..p3..p4..p5 - then do another timestep and p6..p7 - it hits the wall and collision is detected. This process is illustrated in the FAQ: What is tunneling?

--

Don't worry, I saved the best for last. The easiest way and probably the best, is to catch when two geometries intersect (using OnCollision) and then check the distance of the intersection points (contacts) to the edge. This is actually calculated inside the contacts and is called separation (Contact.Separation). You can use this value to see if tunneling happens - granted that the geometries are big enough to detect the actual tunneling happen. See the example above.

Inside the engine, we use the separation value of the contacts to determine the amount of impulse needed to separate the two geometries. When this separation value becomes to big, we have no easy way of recovering and the geometry gets stuck inside the other geometry. Depending on the timestep used, you can find this limit and use it to determine if it is unable to recover or not. (thus tunneling happened or the geometry got squashed)

Nov 5, 2009 at 1:48 PM

Thanks Genbox! Looks like it works pretty nicely. Now I have a clean and simple method for checking when a geom has been squashed, crushed or smashed :)

Coordinator
Nov 5, 2009 at 1:50 PM

What did you end up using?

Nov 5, 2009 at 2:16 PM

The last one. I specified a threshold for considering if the geometry has been "crushed" or just had a strong collision. In each character geometry's OnCollision method, I did the following (set 4 as the threshold):

private bool OnCollision(Geom geom1, Geom geom2, ContactList contactList)
    {
        foreach (Contact contact in contactList)
        {
            if (Math.Abs(contact.Separation) >= 4f)
            {
                Die();
                break;
            }
        }
        return true;
    }
I tested this with an elevator and a character who has been crushed by it, and works pretty nice :)