Collision events between shapes

JarkkoL
Posts: 7
Joined: Thu Aug 19, 2010 10:50 am

Collision events between shapes

Post by JarkkoL »

Hi,

I'm currently in the process of integrating Bullet physics into my game engine and got basic rigid body physics working already. Now I'm trying to figure out what would be the best way to get trigger events for shapes of a rigid body, i.e. when a trigger shape enters or leaves another shape I would like to have callback function called for the event. I have PhysX already integrated and for that I'm using NxUserTriggerReport which reports events for a pair of shapes for those events and was wondering does Bullet have something similar I could use or how this should be implemented?


Thanks, Jarkko
JarkkoL
Posts: 7
Joined: Thu Aug 19, 2010 10:50 am

Re: Collision events between shapes

Post by JarkkoL »

So, there's no one who knows how to implement triggers with Bullet? :(

Btw, I tried gContactAddedCallback & gContactDestroyedCallback but in my example case I get 9 added followed by 2 removed calls for a sphere falling through a box. I'm a bit puzzled how this thing should be done.
User avatar
Dragonlord
Posts: 198
Joined: Mon Sep 04, 2006 5:31 pm
Location: Switzerland

Re: Collision events between shapes

Post by Dragonlord »

Shapes can have more than one contact point which is required to achieve some stability of objects resting on other objects. Hence you get called there whenever a new contact point between two shapes is detected. Since your sphere falls through the box the contact points are quite arbitrary since every point on the surface of the sphere protruding the box is a valid contact point and can be added. Bullet keeps a list of at max N contact points as far as I know. So that's quite volatile. These callbacks are most useful for stuff like impact sounds and such. What you might want to look into is creating a subclass of the collision dispatcher. Use then this class instead of the default class. I'm using this for example to do more fine grained collision filtering than bullet can do with the simple flag system. Problem there is just that it is not fully defined how often these calls happen. That has to do with how many steps are done and other internal properties. Another possibility would be using ghost shapes and volume casting, hence manual collision detection each frame. It's though more involved. I think your best bet would be a subclass of collision dispatcher.
JarkkoL
Posts: 7
Joined: Thu Aug 19, 2010 10:50 am

Re: Collision events between shapes

Post by JarkkoL »

I could try sub-classing the dispatcher. I checked the btCollisionDispatcher interface but it's not clear which function gets called when a shape enters / exits another shape. Ideas?

Is there any documentation somewhere which demonstrates proper implementation for trigger events? That's very basic thing after all.


Cheers, Jarkko
User avatar
Dragonlord
Posts: 198
Joined: Mon Sep 04, 2006 5:31 pm
Location: Switzerland

Re: Collision events between shapes

Post by Dragonlord »

I would try setNearCallback. This callback is called for each overlapping pair found during collision detection. defaultNearCallback is used by default so yours would look similar just that you can do something in addition to the actions taken there.
JarkkoL
Posts: 7
Joined: Thu Aug 19, 2010 10:50 am

Re: Collision events between shapes

Post by JarkkoL »

Okay, but if the function set by setNearCallback() is called for each overlapping pair it's not called then only upon enter/exit events of shapes. I debugged this a bit and it seems that btCollisionDispatcher::getNewManifold() and releaseManifold() gets called when a shape enters/exits another shape, which seems more like the right thing. The problem is though that getNewManifold() gets two pointers to collision objects and not shapes. How can I know which shapes cause these event?

Edit: Just to clarify, this isn't obviously an issue if there's only a single shape in an object, but for more complex objects there may be multiple shapes in an object stored using btCompoundShape. So I would need to know which shape within compound shape issues the event. Each shape within compound shape seems to issue separate calls to getNewManifold() and releaseManifold().

Edit2: Ah, further debugging and seems that the btCollisionObject that's passed to these functions isn't the actual collision object I created which has the btCompoundObject as the shape, but something Bullet created internally for each shape within btCompoundShape. I think that kind of solves it.
User avatar
Dragonlord
Posts: 198
Joined: Mon Sep 04, 2006 5:31 pm
Location: Switzerland

Re: Collision events between shapes

Post by Dragonlord »

I don't know if bullet tracks which shape causes the collision as I think they use a GJK and that doesn't really work with individual shapes per se. Why exactly you need collisions with individual shapes inside a collision object? You can use multiple objects and attach them using static contraints if required. But that depends on what the goal is in the end.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Collision events between shapes

Post by Erwin Coumans »

There are various ways to implement triggers, see also http://bulletphysics.org/mediawiki-1.5. ... d_Triggers

The best way is to iterate over all contact manifolds after each simulation substep (use internal tick callback).

An alternative is to use the btGhostObject.

It is not recommended to use contact callbacks for triggers, but if you insist and want to know the child shape of a btCompoundShape or btBvhTriangleMeshShape: the contact point has a index/partid.

Thanks,
Erwin
JarkkoL
Posts: 7
Joined: Thu Aug 19, 2010 10:50 am

Re: Collision events between shapes

Post by JarkkoL »

The problem is that I (and I'm sure I can speak for vast majority of game developer out there as well :)) want to get the event if shape enters/exits another shape, and not the current state (i.e. if it's overlapping another shape) what those methods in the trigger wiki page propose. If my only option is to check the overlapping state, I would have to poll the state each frame and maintain the current state of all overlapping shapes (or shapes that are overlapping trigger shapes) to check if the state changes, and then trigger an event. It's much more cumbersome and more performance and memory heavy when the physics engine can provide these trigger events when its internal state changes. For example in a game I can have automatic door and trigger volume for opening the door. If player character enters the trigger volume, you trigger "open door" event and if player character leaves the volume you trigger "close door". This is a very common thing to have in games to trigger events, thus it's strange if Bullet doesn't feature such a basic mechanism.

I don't know how reliable and accurate this getNewManifold() / releaseManifold() method is. It seems to provide exactly the functionality I need (i.e. fire the events only when shape enters/exits another shape), but I haven't yet had time to investigate it further.


Cheers, Jarkko
User avatar
Dragonlord
Posts: 198
Joined: Mon Sep 04, 2006 5:31 pm
Location: Switzerland

Re: Collision events between shapes

Post by Dragonlord »

Personally in my project I use manual collision detection for triggering. I would though like to get it done by Bullet too. Looks though like only the tracking of contact points is a solution but so far I did not have the time to build an entire framework around this.
JarkkoL
Posts: 7
Joined: Thu Aug 19, 2010 10:50 am

Re: Collision events between shapes

Post by JarkkoL »

Okay, getNewManifold() / releaseManifold() seems to have issues with kinematic actors, so I binned it. I tried btGhostObject instead, but it doesn't work either, i.e. when I add kinematic ghost actor to world and set its position with setWorldTransform(), I get no calls to addOverlappingObjectInternal() when it overlaps a static shape in the scene. So what's up?

Manual collision detection (i.e. iterating through all objects in the scene for a trigger volume and test for overlap) isn't definitely an option for anything but trivially tiny scenes.

Edit: Okay, now I got addOverlappingObjectInternal() called but it seems like only a broad phase check, duhhuh! Haven't had such a frustrating experience working with an external lib for ages.
User avatar
dphil
Posts: 237
Joined: Tue Jun 29, 2010 10:27 pm

Re: Collision events between shapes

Post by dphil »

Hi JarkkoL, I'm also currently trying to figure out the best way to receive enter/exit events only (not continuously overlapping objects). Basically I have a growing cluster of replicating spheres, forming a tight-knit but dynamic blob. I want each object to track the number of others it is in contact with. At first I was just iterating through all manifolds at each time step (or less frequently, for efficiency sake), but my problem is that, given the high degree of contact between all of the objects, the list of manifolds becomes very large. For example, in a cluster of crowded spheres, objects not on the periphery will generally be in contact with 6 (give or take) other objects, so for 500 objects I can easily have 2000-3000 manifolds to go through. Furthermore, given the low dynamic nature of the objects, the large majority of those manifolds (contacts) will persist for a long time, and only a small fraction of them will ever be *new* events. Hence why I'd like to try an enter/exit response strategy now to compare performance.

I have had some similar issues as you. At first I tried gContactAddedCallback and got a ton of calls to it just by causing 2 spheres to overlap. I'm going to try dispatcher sub-classing now with overriding the getNewManifold()/releaseManifold() as you have mentioned.

On a side note, you mention not getting an addOverlappingObjectInternal() call when causing a kinematic and static object to overlap... It is my understanding that kinematic and static objects are not supposed to collide with each other anyway. I believe collisions are only registered between dynamic and static and between dynamic and kinematic (though I could be wrong).
VicariousEnt
Posts: 50
Joined: Fri Oct 29, 2010 1:37 am

Re: Collision events between shapes

Post by VicariousEnt »

The example posted by Irwin (the first one on that page) is the best way to handle contact triggers. I've written physics\collisoin engines myself and I think its better to get a callback every frame that 2 objects are in contact then just when they first contact and then seperate. It can also be hard and expensive for a collision engine to track the seperation event as every object would have to maintain a list of every other object its touching at all times. In the games I've worked on, both using my collision engines and others, its always been the game objects responsibility to track which callback is the first and which is the last and to ignore all of the other ones in between. This is easily done with flags\states\bits etc. You also need that callback everyframe for many cases, like when a wheel on car drives over geometry, transitioning between different triangles with different surface normals on the same triangle mesh.

In my current engine that uses bullet I will be providing a post simulation tick callback that iterates over all contacts and dispatches the appropriate callback calls to my game objects via the m_userPointer in all btCollisionShapes (which points to my own base game object class of course).
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: Collision events between shapes

Post by Flix »

You may want to try the attachment I posted some time ago:
http://bulletphysics.org/Bullet/phpBB3/ ... php?id=343

(the post was here: http://bulletphysics.org/Bullet/phpBB3/ ... t=callback).

That was done by subclassing btRigidBody, and adding the setMonitorCollisions(...) method, that makes three callbacks (that are actually virtual methods) available for start/continue/end collision events.

Internally it iterates over all pairs of objects in the entire collision/dynamics world, reduces the contact points to one before calling the "callback", and keeps two lists of colliding bodies to detect start/end collision events.

It's very easy to integrate it into existing projects, but the main problem is that it does not forward info about partID/indexID in the callback, so I don't know if it's useful in your scenario.
hyyou
Posts: 96
Joined: Wed Mar 16, 2016 10:11 am

Re: Collision events between shapes

Post by hyyou »

I know this thread is already 6-years old, but I just faced the same problem.
I really want to the callback - same as the OP (JarkkoL).

Here is the solution in more detail:

Code: Select all

use cp->m_index0 (index of first shape) and cp->m_index1 (index of second shape)
I tested it a little bit, and it works.

Code: Select all

index=0 means that it is the first shape that you added to compound.
Copied from https://www.bulletphysics.org/Bullet/ph ... =9&t=10617
(answered by drleviathan, thank!)

Actually, it is same as Erwin said. :D

I hope this post will be useful for someone for another 6 years.