[howto] check if a Geom is NOT colliding with anything

May 13, 2009 at 12:29 PM
Edited May 27, 2009 at 8:56 AM

basically what happens here is that the absolute ticks are counted and when a collision happen the current ticks are stored. at every seperation event it is checked if there was a collision during the last update event (note: OnCollision is called everytime as long as two Geoms collide). if there was no collision the Geom is no colliding with anything.

class MyObject
{
    private ulong        Ticks             = 0;
    private ulong     TicksCollision    = 0;
    private bool    HasCollision     = false;

    ...

    public void Update( GameTime time )
    {
        ++Ticks;
    }
   
    private bool OnCollision( Geom g1, Geom g2, ContactList contactList )
    {
        TicksCollision    = Ticks;
        HasCollision    = true;
    }
   
    private void OnSeparation( Geom g1, Geom g2 )
    {
        if( TicksCollision < Ticks )
        {
            HasCollision = false;
        }
    }
}

NOTE: if you are using "detection zones" (Geoms with no collisions but collision handling), set geom.CollisionResponseEnabled = false or you will get OnSeparation events as lon as the other Geom is within the "detection zone".

May 15, 2009 at 2:45 PM

you would probably be bettor off making Ticks and TicksCollision of type 'long' instead of 'double' no point slowing down the cpu to do floating point arethmetic.

May 16, 2009 at 7:01 PM

sure, thx. was using absolute time before.

May 27, 2009 at 4:56 AM

Thanks for doing this, its really quick and clean - I am having trouble putting all the pieces together in my head though. I think I just don't really understand the 2 events well enough yet. Does OnSeparation fire all the time? - so if you didn't do the Ticks check, HasCollision would always be false? Also in your update you would have the ++Ticks, followed by a call to OnCollision, followed by a call to OnSeparation?

This is how I think the logic works based on your description, correct me if im wrong though! OnCollision only fires when a collision occurs, OnSeparation fires all the time. When a collision occurs HasCollision = true and TicksCollision = Ticks. TicksCollision will always be = Ticks in the OnSeparation call unless OnCollision didn't fire - when OnCollision doesn't fire there is no more collision and therefore TicksCollision = last updates Ticks value (less then the current Ticks value) and HasCollision should be false?

I hope that post wasn't too confusing lol. I really like this method but I'd like to understand it a bit better before I try and implement it :)

May 27, 2009 at 8:55 AM

from the original post: "OnCollision is called everytime as long as two Geoms collide" :)

OnSeperation is called when the engine applies forces to the Geoms to separate them from their interpenetrating penalty state, that is in most cases only once.

Coordinator
May 27, 2009 at 2:51 PM
Edited May 27, 2009 at 2:52 PM

I know this is not excatly information for new users of physics engines, but I'll try to explain the science behind the engine it as simple as I can.

Farseer Physics Engine is based on a physics engine design developed by the Box2D creator Erin Catto. It's called Sequential Impulses (with warm starting). Sequential Impulses mean that on each update of the physics engine, the engine finds a collision in this manner:

1. Find geometries close to each other. When a pair of geometries is close, create an Arbiter (A pair of geometries) - This is called the broadphase.
2. Iterate each Arbiter and check the two geometries for intersection. The points of intersection is marked with a Contact - This is called the narrowphase.
3. Iterate each Contact and calculate the force required to separate the two geometries (using their normals and restitution coefficient).
4. Here is some stuff to optimize performance and stability. - Mostly involving sorting and removing of contacts. (Controlled by MaxContactsToDetect and MaxContactsToResolve on the PhysicsSimulator object)

Now. here is where the Sequential Impulse stuff happens:

5. Iterate the Arbiters 5 times (the default is 5, controlled by Iterations on the PhysicsSimualtor object) and apply impulse to each of the geometry pairs, to make them seperate. This involves something Erin Catto invenved where you clamp the acumelated impulse - this is done to improve stability.

I also mentioned "warm starting" before. This is also used to improve stability (of the physics simulation). It means that you save contacts from previus simulation as a startingpoint of the new impulse calculations. You basically give the engine an idea of how the collision will occur, before the collision occurs. This give a more stable result.

Now to the reason why I wrote all this :)
The OnCollision event fires whenever an Arbiter has been created and the Contact(s) associated with it has been detected (by the narrowphase). This means that the engine has determined the point of intersection (collision) between two geometries, and then fires the OnCollision event.

The OnSeparation event fires when all the contacts associated with an Arbiter has been removed. - Again, after the engine determines that the two geometries are no longer touching each other.

This is all great and world work really good - IF we had an infinite bit computer. :) Problem is that we don't.
Computers are not 100% accurate and thus we run into rounding errors that can accumulate to something that is completely wrong (error too big for a stable physics simulation). This is taken into account in the physics engine and we do our best to prevent it from affecting the engine too much. But, even tho we hop though all the hoops to make it stable, the engine still overcompensates when a collision occurs, and move the geometries too far away from each other. Thus, removing all contacts and fire the OnSeparation event. Then the whole thing happens all over again.

Conclusion is that this howto is needed to emulate the correct behavior of OnCollision and OnSeparation events. The engine fire them at the correct time, but computers are not precise enugh to make them fire only when we want.

May 27, 2009 at 5:14 PM

Wow - wasn't expecting that ahaha! thanks for the very detailed reply genbox :)

So both OnCollision and OnSeparation fire only if the physics engine thinks there is a collision or separation. And basically Ticks is just making sure that if the computer overcompensates the force required to separate the geoms after a collision and OnSeparation is called it won't set HasCollision = false unless it really should be false?

Coordinator
May 27, 2009 at 5:24 PM

What yobiv does is simply to make sure that you have a reliable HasCollision boolean to check against in your game. He is not interfering with the engine itself.

You can have multiple OnCollision calls and multiple OnSeperation calls. Imagine 3 colliding geometries in a row. If you subscribe to the one in the middle, it will fire the OnCollision event for both the colliding geometries. Also, the OnSeperation event will fire for both geometries.

Yobiv's code is to make sure that you can check if a geometry is not colliding with anything on the screen at all. I've not tested the code tho - for any information about the code, yobiv is the one to ask :)

Jul 14, 2009 at 10:22 PM

Hi.. sorry to dig this out. After I placed some debug output info into engine, I found out that OnCollision is called when geometries collide, but OnSeparation is called when AABB of geometries are separated. Is this right? I could find in description in OnSeparation that it takes AABBs into check, not exact geometries. Or do I have some old sources of project?

Coordinator
Jul 16, 2009 at 1:34 PM

The OnSeparation event is called whenever the contacts created between two geometries are removed. The contacts are removed when the geometries no longer touch (their AABB can still intersect each other, but the geometries don't touch each other).

Jul 16, 2009 at 1:55 PM

Ye.. I saw that in implementation. Then I don't get why my OnSeparation was triggered only when there was no AABB collision. Can anyone else confirm if OnSeparation is triggered when geometries no longer touch or their AABBs?

Coordinator
Jul 16, 2009 at 2:44 PM

Have you downloaded the version from the source control? It contains an unfinished version of Farseer Physics 3.0 - you should stay with 2.1.1 for the time being.

Jul 16, 2009 at 10:56 PM

Just switched from version 2.1 to 2.1.1 in my engine, but still see the same. OnSeparation is still called when inside AABB of object.

I've made a video. Player has small rectangle (I call it support ground) under circle - to detect if player is on ground. There is Separation flag in panel, that signalizes if OnSeparation for that 'support ground' was called - so true means, OnSeparation is still triggered. Evidently it's still true, while 'support ground' is still inside of AABB of rotated box. Or am I using some wrong parameter in simulator to accept AABB collision as contact.. I know it was explicit true/false for AABB collision when doing ray test.

video: http://www.youtube.com/watch?v=-RX-Z76q0J0