Havok collision callbacks: body-specific vs world-wide

Playground: https://playground.babylonjs.com/#Z8HTUN#1257 You can set “doBodySpecificCallbacks” to true or false to switch between body-specific and world-wide collision callbacks

I’m trying to get my physics collision as performant as possible, so according to the docs ( Babylon.js docs ) I should use the world-wide collision callback. But I noticed it doesn’t report the entire situation. It only reports one sphere hitting the other, instead of reporting both spheres hitting each other. And in that case, I can obtain the point of collision and the normal on the colliding body, but I cannot seem to obtain the normal at the collision point on the other body.

If I turn on body-specific callbacks, it does report both sides of the collision, including normals on both bodies, which is information I need. So I guess my question is, if I just go ahead and use body-specific callbacks, how big is the performance difference between body-specific and world-wide collision callbacks?

Secondary question: When world-wide collisions are requested and it only reports the one collision, what determines which body is the “collider” and which is the “collidee”? Because in this playground, the right-hand sphere is moving with more energy, but it’s the left-hand sphere that gets reported as the collider. Is it reported deterministically?

1 Like

To be fair, there really is only one collision.

Looking at the Babyon code that calls into the Havok engine, you can see the collision handling, including the generation of world Collision and both body collisions. Not all fields available from Havok are passed through Babylon Observables.
.

It’s true that there’s only one collision and one point of collision, but there are two normals. What would be ideal is to have the world-wide collision callback give the collision data only once, but include the normals from both the “collider” and “collidedAgainst” in the result. I see the data is available in _notifyCollisions, but it’s just not included in the result

1 Like

It depends on the number of collisions expected per frame. For a few collisions per frame, you should not see a notable difference. The difference becomes apparent when using instances and dozens collissions per frame.

Secondary question: When world-wide collisions are requested and it only reports the one collision, what determines which body is the “collider” and which is the “collidee”? Because in this playground, the right-hand sphere is moving with more energy, but it’s the left-hand sphere that gets reported as the collider. Is it reported deterministically?

This is a question for @eoin

2 Likes

@eoin will have a more expert perspective.

Havok names the colliding objects simply “A” and “B” and the Babylon wrapper assigns Havok A to Babylon .collider. I don’t know how Havok determines which physicsBody is “A”.

The collision observables are notified through the call to (private) _notifyCollisions from the (public) executeStep(). _notifyCollisions iterates on all Havok-reported collisions and notifies each enabled world and body obsevable, doing a few calculations when needed (e.g. for .distance).

I suspect it works this way to maintain some backward compatibility with V1 and among the various implemented physics engines. You may be able to hone the reported events to your needs with HavokPlugin.setEventMask(physicsBody,…). Otherwise, I can think of a few ways to implement your own observable from Havok, one is:

  1. Implement IPhysicsCollisionEventV2, or extend IPhysicsCollisionEvent in a backward compatibile way, to mirror the Havok CollisionEvent.
  2. Modify _notifyCollisions to notify CollisionV2Observable, when it exists. Use the extended IPhysicsCollisionEvent or your new IPhysicsCollisionEventV2. I’m not sure if implementing both world and body collision “V2” observables would be better.
  3. For now, implement your own _notifyCollisionsV2 called from a custom executeStep.

I hope this helps, but maybe wait for @eoin to chime in as well.

2 Likes

OK, couple of questions here, hope I don’t miss any:

I’m trying to get my physics collision as performant as possible, so according to the docs ( Babylon.js docs ) I should use the world-wide collision callback

It’s a little hard to give definitive recommendations for performance since all situations are different. It’s also probably not worth worrying about performance until you have something you can measure, lest you prematurely optimize - a difference is only going to show up at higher contact counts. However, I’d recommend choosing world-v-body callbacks based on what you think is happening in your world. If you have a world with many contacts, but you’re only interested in some of them, use the body-specific callbacks; if you’re interested in most of the contacts, use the world callback.

And in that case, I can obtain the point of collision and the normal on the colliding body, but I cannot seem to obtain the normal at the collision point on the other body.

You can obtain this info geometrically. The point on the other body is just “point + normal * distance”, and the normal on the other body is just “normal * -1”

what determines which body is the “collider” and which is the “collidee”?

This is pretty arbitrary and you can’t derive anything from it. Internally, it’s a function of the order the bodies were added to their world, their shape types, motion types, and other attributes, so you can never rely on one body always being A, for example.

3 Likes

OK that’s some good info and tips. I have enough to go on from here. Thanks everybody!