Trigger on Impact

oddrose

02-06-2009 18:47:53

Hi,

I'm wondering how to detect the collision of two objects, but just the impact really. I'll explain.

Imagine that you have a ball dropping down on a flat surface. At the the time of impact I want to trigger a function, e.g. a counter for how many times the ball has bounced on the ground.

My problem is that if for instance the ball stops at the surface the ContactCallback functions keep getting called. (I guess it is bouncing with very low height).
I want to make sure that I only call the functions that should be called on impact once and not more. Again, with the ball example, imagine that every bounce in a tennis game counts as two. Not very fun to play.

I guess in the case of the ball you could just set a threshold on the velocity or altitude of the ball so that when small enough, the bounces doesn't count. Do you think that this would work in the general case? Am I guaranteed low velocity in the collision if the ball is lying (seemingly still) on the surface?

I hope you can help me!

PJani

03-06-2009 00:24:28

try with impact force when is greater than gravity pull then count impact... :P just idea

oddrose

03-06-2009 08:52:09

well, I tried using a threshold for the normal velocity, so it only registers the impact. The only problem now is that it does this up to 4 times per frame with almost identical normal velocity. I guess you could limit it in some way but the problem is that if you're using several bodies for the same contact callback you can't put a "lastframecollided" as a member and see if it has triggered this frame already. (Because then it just triggers for the first body of the callback). So either you have to do the sorting elsewhere (which I don't like from an event-based point of view) or you do some map of which bodie's has collided in the current frame. I don't like the map idea cause it seems unnecessarily slow to fill and clear a map every frame.

About the 4 times per frame. I have a higher FPS for my app than I have for the physics. So basically...how does contactcallback functions get called 4 times in one frame?

oddrose

03-06-2009 20:07:12

I saw that someone else has posted on a similar topic and for anyone interested, this is what I have come up with so far:

I check that ContactCallback::getContactNormalSpeed() is positive, negative values are not interesting since they represent a collision from inside the objects. (They overlap).

Second, I check that the norm of ContactCallback::getContactForce() equals 0. This vector is only non-zero for objects that lie on eachother, that we aren't interested in.

Last, I check that the difference between last contactSpeed and current is large. This makes sure that I don't get multiple calls per frame to trigger functions. I just put some threshold value, it might be possible to have it even smaller but I haven't run into any problems this far. This however becomes a problem if two different bodies collide with something at the exact same time. To take care of this, I make sure that the last bodies handled in the callback aren't the same as the last time the function was called. This would be a problem if the callback was done several times for a body during a frame but with other callbacks in between. This far I haven't noticed any problems with that.

So basically:


normalSpeedDiff = (lastNormalSpeed - normalSpeed)/lastNormalSpeed;
if(normalSpeed > 0 && getContactForce().squaredLength() == 0)
{
if(abs(normalSpeedDiff) > 0.001)
{
trigger = true;
}
else if(mLastBody0 != m_body0 || mLastBody1 != m_body1)
{
trigger = true;
}
}


As you may notice, the normalSpeedDiff may be calculated between different sets of bodies but this doesn't matter because of the "else if".