I need three callbacks. A callback when objects initially contact, regardless of whether they overlap, and begin/end overlap callbacks.
Ghost objects won't work because they are only for broadphase collision. Also, they seem really inefficient when used with rigid bodies. There are more collisions to track and the ghost object must be continually synced with the rigid body.
One solution is to maintain a cache of currently overlapping objects and do before-after comparisons of the cache each time it is updated. A collision point with lifetime < 1 (is 0 or 1 a 'new' point?) triggers the initial contact event. If the same point's distance is < 0 (penetration) it also triggers the begin overlap event and is added to the object's overlap cache. An object only present in the old cache triggers the end overlap event. The events can be called on objects through btCollisionObject's userptr when iterating over all pairs of colliding objects during a simulation tick callback, as described near the top here: http://www.bulletphysics.org/mediawiki-1.5.8/index.php
Does this sound workable?
A few concerns:
1. Comparing the previous cache with the updated cache after every step simulation may really hurt performance.
2. Using a point's lifetime to determine whether it is an initial contact is problematic if lifetime is incremented multiple times during a step simulation, for example each substep. Is this the case?
3. The simulation callback is triggered once per step, not every substep. Is this correct? If so, then I will miss some fast collisions. For example, a rapidly moving object that ricochets off a wall but is no longer making contact when the simulation callback is fired. I would be unable to trigger a sound effect on impact with the wall.
Another possibility is a combination of gContactProcessedCallback and gContactDestroyedCallback. I can't find a lot of documentation on either. Scanning the forum hasn't helped. It isn't clear whether gContactProcessedCallback can be triggered multiple times by the same contact point during a simulation step like gContactAddedCallback.
Even if a single point can only trigger gContactProcessedCallback once per simulation, checks need to be in place to prevent multiple collision points each triggering the callback. Also problematic is that a contact point gets re-processed every simulation. So it's possible a slow moving object that ricochets off a wall may trigger an impact sound effect more than once.
Checking point lifetimes and which has triggered gContactProcessedCallback might work but this could have an even greater impact on performance than comparing caches during a step simulation callback.