Collision Mask Support

Sep 9, 2009 at 2:53 AM

First off, thanks for all the hard work you've put into this project.  The code is easy to understand and well constructed.  So much so that I don't even feel compelled to rip through it and reconstruct it like I do with most of the XNA example code out there.  I admire how you were able to optimize things without abandoning a clean OO approach (this has seemed to be the first thing to go in other physics engines I've seen).  I'm currently working on adopting the physics component into a game I'm working on, and have a feature request.  The use case is a game that uses dead reckoning (based on the "Network Prediction" sample on the XNA Creator's Club page), so it often simulates two copies of the same entity.  The problem being that there will be two RigidBodies representing different states of the same object and the two RigidBodies would collide with eachother.  

I think this case could be handled by the addition of support for what ODE calls "categoryMasks" and "collideMasks."  CategoryMask is a bit field that marks which sets the RigidBody is a member of, CollideMask is a bit field that marks which sets the RigidBidy can interact with.  So, objects would be able to collide with eachother if (Obj1.CollideMask & Obj2.CategoryMask != 0 || Obj2.CollideMask & obj1.CategoryMask != 0).

So, the use case would work something like this:

Static/infinite mass Objects not using dead reckoning are members of group A

Massless objects not using dead reckoning (particle systems/bullets) are members of group B

The most up to date version of an object using network prediction is in group C

The previous version (used for blending with the next version coming down the wire, so that updates don't cause jumps) of an object using network prediction is in group D


Group A collides with,  B, C, and D. It is ok that A collides with both C and D (different versions of the same entities) because C and D cannot affect A.

Group B collides with A, and C

Group C collides with A, and B

Group D collides with A


One tricky part is that as a new update comes across the wire the object's previous latest network state (group C) is moved to it's previous state (group D) and a new latest state is established.  I don't think this causes any issues, as long as there's not some sort of caching going on that I'm not aware of.  Is there any type of caching that would cause directly updating the properties of a RigidBody like this to break the simulation?

Thanks again for all the effort you've put into this project!




Sep 9, 2009 at 4:45 AM

Wow.  Looks like you already have that, I just overlooked it.  I guess I was thinking it would be in RigidBody, but it's in CollisionGroup under CategoryFlags and CollisionFlags.  


I guess I still just have the question about if you have an idea of how gracefully the physics engine would handle the case where I'm manually updating a RigidBody with information from a net update, that might place two objects overlapping eachother pretty deeply.  I'm hoping for the system to separate the bodies, but to maintain reasonable velocities, should I be able to depend on that?




Sep 9, 2009 at 5:17 AM

Thanks for the comments!  I appreciate it.

You first wish is my command!  there's already a CategoryFlags and CollisionFlags property on the CollisionGroup and CollisionShape classes that do what ODE does.  Just set your bit mask on the RigidBody.CollisionGroup.CategoryFlags/CollisionFlags.

There is no caching happening in the physics, but  make sure that you modify the Position and Orientation of the RigidBody using the RigidBody.UpdateTransform method(s) so the changes cascade to the CollisionGroup and CollisionShapes and the inertia gets correctly calculated.  Also, make sure any updates occur in a "thread-safe" way.  The easiest way to guarantee this to only read and modify the RigidBody information when in between the PhysicsComponent.EndUpdate and PhysicsComponent.BeginUpdate in the "Update" method.

Also, Velocity and Rotation may be important to send over the wire as well as these values are very important when dealing with collision response. 

The only other stateful values of the RigidBody are Force/Torque and it's inactiveTime/Flags.  Force/Torque get cleared after each simulation, so you shouldn't need these synchronized.  inactiveTime/Flags is used to auto-deactivate inactive objects.  I doubt you would need these two values synchronized but I could see it causing wierd issues potentially if the RigidBody.Flags includes AutoDisable.

Good luck!  Let me know how it turns out!

Sep 9, 2009 at 5:23 AM

Thanks!  That's a huge help.  I'll keep you updated.