Adding DetectorVolume capabilities to Entity class

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
chris24k
Posts: 1
Joined: Thu Apr 05, 2012 9:10 pm

Adding DetectorVolume capabilities to Entity class

Post by chris24k »

Hi Norbo,
first of all, thanks for the great engine.

Now to my question:
I'd like to be able to subscribe to some collision events to update my logic. An Entity's CollisionInformation gives me InitialCollisionDetected and CollisionEnded (which, to my understanding, should be equal to DetectorVolume's EntityBeginsTouching and EntityStopsTouching). How could the Entity fire events like DetectorVolume's VolumeBeginsContainingEntity and VolumeStopsContainingEntity?
My first guess was to use both, an Entity and a DetectorVolume for the same game object. In that case, after what I've read here in the forums, I'd have to update the DetectorVolume's position through its TransformableMeshData and call TriangleMesh.Tree.Refit. But I wonder if this is really the best approach.
Would it be better to subclass my Entity/MobileMesh and extend it with the DetectorVolume capabilities in some way? Is the Entity's CollisionInformation sufficient to provide me with everything I need to mimic VolumeBeginsContainingEntity and VolumeStopsContainingEntity and write custom methods like "EntityBeginsContainingEntity" and "VolumeStopsContainingEntity"?

Using only DetectorVolumes might not be an option, since I want to be able to apply impulses to my game objects (and still get notificatons if one is completely contained in another one).

Thanks in advance.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Adding DetectorVolume capabilities to Entity class

Post by Norbo »

How could the Entity fire events like DetectorVolume's VolumeBeginsContainingEntity and VolumeStopsContainingEntity?
Unfortunately, there is no built-in general support for this as the collision detection systems have no concept of containment.

It could be approximated, however, by checking the greatest penetration depth within its entity.CollisionInformation.Pairs[j].Contacts list. If the depth is sufficient, you can at least be sure that the objects are significantly overlapping. Using a shape's minimum radius as the threshold would work for some shapes. Spheres checked for containment with some convex object would work well with this approach (almost perfectly, within the allowances of persistent manifold approximations).
Would it be better to subclass my Entity/MobileMesh and extend it with the DetectorVolume capabilities in some way? Is the Entity's CollisionInformation sufficient to provide me with everything I need to mimic VolumeBeginsContainingEntity and VolumeStopsContainingEntity and write custom methods like "EntityBeginsContainingEntity" and "VolumeStopsContainingEntity"?
I would not recommend jumping into the depths of the engine if it can be avoided. I usually recommend against extending entities/collidables unless the collision behavior is being modified. This approach would also likely run into necessary modifications to the pair handlers.

A mobile mesh could be encouraged to cough up the information you need, though. The mobile mesh shape associated with a mobile mesh (accessible in the mobileMeshEntity.CollisionInformation.Shape) has a IsLocalRayOriginInMesh method which returns whether or not a ray starts within the mobile mesh.

You can construct a ray from the position of entity being tested for containment, plus any direction (Vector3.Up would be fine; you don't really care about the final ray intersection here- just the ray origin). Note that it checks the ray against the local space representation of the mobile mesh. Apply the inverse rigid transform of the entity (position and orientation) to pull the ray into local space.

So, if that test returns true, the checked entity's center is known to be within the mobile mesh. To determine total containment, we must also test to see if the checked entity is touching the surface of the mesh at all. Set the mobile mesh's sidedness to double sided (assuming that the collision rules are such that collision response is disabled but contacts are still generated by the narrow phase). If there exist any contacts with nonnegative penetration depth, we know that the checked entity is touching the surface of the mobile mesh.

If the checked entity is known to be inside by the IsLocalRayOriginInMesh method and there are no contacts with nonnegative depth, then the checked entity's center is inside and it is not touching the surface, meaning it is fully contained.

You could also decide to have a bit of slop on the depth check to allow 'mostly contained' entities.

Note that the IsLocalRayOriginInMesh is not a particularly cheap method; it's on the same order of magnitude as regular collision detection between a mobile mesh and a convex object. Be sure to only run it when the entity and the containment zone are known to have overlapping bounding boxes (i.e. they share a CollidablePairHandler in their entity.CollisionInformation.Pairs list).
Post Reply