Proper way to clean up contacts?

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Telanor
Posts: 57
Joined: Sun May 06, 2012 10:49 pm

Proper way to clean up contacts?

Post by Telanor »

When I modify one of my StaticMeshes, I use the following code to make sure any physics objects touching it don't end up floating in mid-air:

Code: Select all

foreach(var pair in mesh.Pairs)
{
	if(pair.EntityA != null)
		pair.EntityA.ActivityInformation.Activate();

	if(pair.EntityB != null)
		pair.EntityB.ActivityInformation.Activate();

	pair.ClearContacts();
}
This code runs on a different thread than the physics update though and it seems to be causing a null reference exception:

Code: Select all

Object reference not set to an instance of an object.
   at BEPUphysics.Constraints.Collision.ContactPenetrationConstraint.SolveIteration()
   at BEPUphysics.Constraints.SolverGroups.SolverGroup.SolveUpdateable(EntitySolverUpdateable item, Int32& activeConstraints)
   at BEPUphysics.Constraints.Collision.NonConvexContactManifoldConstraint.SolveIteration()
   at BEPUphysics.SolverSystems.Solver.UnsafeSolveIteration(SolverUpdateable updateable)
   at BEPUphysics.SolverSystems.Solver.UpdateSingleThreaded()
   at BEPUphysics.MultithreadedProcessingStage.Update()
   at BEPUphysics.Space.DoTimeStep()
   at BEPUphysics.Space.Update(Single dt)
   at Craft.Physics.Update(GameTime gameTime)
   at Craft.World.Update(GameTime gameTime)
   at Craft.GameScreen.Update(GameTime gameTime)
   at Craft.ScreenManager.Update(GameTime gameTime)
   at Craft.Engine.GameLoop()
   at SlimDX.Windows.MessagePump.IdleHandler.OnIdle(Object sender, EventArgs e)
   at System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(Int32 grfidlef)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(Form mainForm)
   at SlimDX.Windows.MessagePump.Run(Form form, MainLoop mainLoop)
   at Craft.Program.Main(String[] args)
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()
I assume the physics engine really doesn't like me messing with the contacts during an update. Is there a better way to go about this?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Proper way to clean up contacts?

Post by Norbo »

This is one of many reasons why I generally advise against performing asynchronous updating unless it's required by some other game architecture detail. It complicates every single interaction.

Contacts cannot be force-modified from a separate thread unless the physics thread is not executing. You could insert a lock which surrounds the whole physics update and any modifications like this, but then your non-physics thread will stall waiting for the physics thread to finish the latest update.

A better way is to pass a message to the physics thread telling it to perform the operation itself. A single piece of communication can be put into a thread-safe queue with very little overhead compared to waiting for a physics update to finish.

The preferred way, if at all possible, is to set up the threading model such that the problem isn't even a problem. Threading is one of the most error-prone and difficult to debug parts of programming, so it's always nice to isolate it as much as possible. Logic executing in sequence with the physics is much easier to manage. If a separate thread is doing some heavy lifting modifying or loading something, its interaction with the physics would ideally be through passing the completed chunk of information back to the main/physics thread and letting that main/physics thread do the physics interaction. This isolates the interactions more than allowing the load thread to interact both with game logic and the physics through separate channels.
Telanor
Posts: 57
Joined: Sun May 06, 2012 10:49 pm

Re: Proper way to clean up contacts?

Post by Telanor »

I figured the solution would be something like that. I've made it so that the update data is passed to the main thread where it can apply all the updates right before it runs the physics update. The errors seem to be gone now. Thanks for the help.
Post Reply