private void RunPhysicsSimulation(float time) { //read skinned meshes bone positions for (int i = 0; i < scenes.Count; i++) { var physicsScene = scenes[i]; if (physicsScene.Simulation != null) { //first process any needed cleanup physicsScene.Processor.UpdateRemovals(); // after we took care of cleanup, are we disabled? if (Simulation.DisableSimulation == false) { //read skinned meshes bone positions and write them to the physics engine physicsScene.Processor.UpdateBones(); //simulate physics physicsScene.Simulation.Simulate(time); //update character bound entity's transforms from physics engine simulation physicsScene.Processor.UpdateCharacters(); //Perform clean ups before test contacts in this frame physicsScene.Simulation.BeginContactTesting(); //handle frame contacts physicsScene.Processor.UpdateContacts(); //This is the heavy contact logic physicsScene.Simulation.EndContactTesting(); //send contact events physicsScene.Simulation.SendEvents(); } } if (physicsScene.BepuSimulation != null) { // do anything before simulation (which might modify ToBeAdded or ToBeRemoved) while (physicsScene.BepuSimulation.ActionsBeforeSimulationStep.TryDequeue(out Action <float> a)) { a(time); } lock (physicsScene.BepuSimulation.ToBeAdded) { // remove all bodies set to be removed physicsScene.BepuSimulation.ProcessRemovals(); // did we request a clear? int clearMode = physicsScene.BepuSimulation.clearRequested; if (clearMode > 0) { physicsScene.BepuSimulation.Clear(clearMode == 2, true); } // add everyone waiting (which could have been something just removed) physicsScene.BepuSimulation.ProcessAdds(); } if (Simulation.DisableSimulation == false) { // simulate! float totalTime = time; for (int k = 0; k < MaxSubSteps && totalTime > 0f; k++) { float simtime = Math.Min(MaximumSimulationTime, totalTime); physicsScene.BepuSimulation.Simulate(simtime); totalTime -= simtime; } // update all rigidbodies Xenko.Core.Threading.Dispatcher.For(0, physicsScene.BepuSimulation.AllRigidbodies.Count, (j) => { BepuRigidbodyComponent rb = physicsScene.BepuSimulation.AllRigidbodies[j]; rb.resetProcessingContactsList(); rb.UpdateCachedPoseAndVelocity(); // per-rigidbody update if (rb.ActionPerSimulationTick != null) { rb.ActionPerSimulationTick(rb, time); } rb.UpdateTransformationComponent(); }); } } } }
private void RunPhysicsSimulation(float time) { //read skinned meshes bone positions for (int i = 0; i < scenes.Count; i++) { var physicsScene = scenes[i]; if (physicsScene.Simulation != null) { //first process any needed cleanup physicsScene.Processor.UpdateRemovals(); // after we took care of cleanup, are we disabled? if (Simulation.DisableSimulation == false) { //read skinned meshes bone positions and write them to the physics engine physicsScene.Processor.UpdateBones(); //simulate physics physicsScene.Simulation.Simulate(time); //update character bound entity's transforms from physics engine simulation physicsScene.Processor.UpdateCharacters(); //Perform clean ups before test contacts in this frame physicsScene.Simulation.BeginContactTesting(); //handle frame contacts physicsScene.Processor.UpdateContacts(); //This is the heavy contact logic physicsScene.Simulation.EndContactTesting(); //send contact events physicsScene.Simulation.SendEvents(); } } if (physicsScene.BepuSimulation != null) { // do anything before simulation (which might modify ToBeAdded or ToBeRemoved) while (physicsScene.BepuSimulation.ActionsBeforeSimulationStep.TryDequeue(out Action <float> a)) { a(time); } // any static objects need to be moved? while (BepuStaticColliderComponent.NeedsRepositioning.TryDequeue(out var scc)) { // might need a writelock here because ApplyDescription can wake bodies (which can move them around) using (physicsScene.BepuSimulation.simulationLocker.WriteLock()) { scc.InternalStatic.ApplyDescription(scc.staticDescription); } } lock (physicsScene.BepuSimulation.ToBeAdded) { // remove all bodies set to be removed physicsScene.BepuSimulation.ProcessRemovals(); // did we request a clear? int clearMode = physicsScene.BepuSimulation.clearRequested; if (clearMode > 0) { physicsScene.BepuSimulation.Clear(clearMode == 2, true); } // add everyone waiting (which could have been something just removed) physicsScene.BepuSimulation.ProcessAdds(); } // critical actions for rigidbodies while (physicsScene.BepuSimulation.CriticalActions.TryDequeue(out var a)) { // don't worry about this if we are to be removed (or have been removed) if (a.Body.InternalBody.Handle.Value == -1 || BepuSimulation.instance.ToBeRemoved.Contains(a.Body)) { continue; } switch (a.Action) { case BepuRigidbodyComponent.RB_ACTION.IsActive: using (physicsScene.BepuSimulation.simulationLocker.WriteLock()) { a.Body.InternalBody.Awake = a.Body.wasAwake; } break; case BepuRigidbodyComponent.RB_ACTION.ColliderShape: a.Body.InternalColliderShapeReadd(); break; } } if (Simulation.DisableSimulation == false) { // don't make changes to rigidbodies while simulating BepuRigidbodyComponent.safeRun = false; // simulate! float totalTime = time; for (int k = 0; k < MaxSubSteps && totalTime > 0f; k++) { float simtime = Math.Min(MaximumSimulationTime, totalTime); physicsScene.BepuSimulation.Simulate(simtime); totalTime -= simtime; } BepuRigidbodyComponent.safeRun = true; // update all rigidbodies Xenko.Core.Threading.Dispatcher.For(0, physicsScene.BepuSimulation.AllRigidbodies.Count, (j) => { BepuRigidbodyComponent rb = physicsScene.BepuSimulation.AllRigidbodies[j]; // if we lost the entity, just return Entity e = rb.Entity; if (e == null) { return; } rb.resetProcessingContactsList(); // pre-sync while (rb.queuedActions.TryDequeue(out var action)) { action(rb); } rb.UpdateCachedPoseAndVelocity(); // per-rigidbody update if (rb.ActionPerSimulationTick != null) { rb.ActionPerSimulationTick(rb, time); } rb.UpdateTransformationComponent(e); });