internal void Simulate(float deltaTime) { if (collisionWorld == null) { return; } simulationArgs.DeltaTime = deltaTime; UpdatedRigidbodies = 0; OnSimulationBegin(simulationArgs); SimulationProfiler = Profiler.Begin(PhysicsProfilingKeys.SimulationProfilingKey); if (discreteDynamicsWorld != null) { discreteDynamicsWorld.StepSimulation(deltaTime, MaxSubSteps, FixedTimeStep); } else { collisionWorld.PerformDiscreteCollisionDetection(); } SimulationProfiler.End("Alive rigidbodies: {0}", UpdatedRigidbodies); OnSimulationEnd(simulationArgs); }
internal void Simulate(float deltaTime) { if (collisionWorld == null) { return; } simulationArgs.DeltaTime = deltaTime; OnSimulationBegin(simulationArgs); simulationProfilingState.Begin(); if (discreteDynamicsWorld != null) { discreteDynamicsWorld.StepSimulation(deltaTime, MaxSubSteps, FixedTimeStep); } else { collisionWorld.PerformDiscreteCollisionDetection(); } simulationProfilingState.End(); OnSimulationEnd(simulationArgs); }
public void Dispose() { //memory var totalMem = GC.GetTotalMemory(false); memoryPeak = Math.Max(totalMem, memoryPeak); gcMemoryState.End(totalMem, totalMem - lastFrameMemory, memoryPeak); //gens count gen0Count = GC.CollectionCount(0); gen1Count = GC.CollectionCount(1); gen2Count = GC.CollectionCount(2); collectionCountState.End(gen0Count, gen1Count, gen2Count); }
/* * private static void DrawDebugCompound(ref Matrix viewProj, CompoundColliderShape compound, PhysicsElement element) * { * for (var i = 0; i < compound.Count; i++) * { * var subShape = compound[i]; * switch (subShape.Type) * { * case ColliderShapeTypes.StaticPlane: * continue; * case ColliderShapeTypes.Compound: * DrawDebugCompound(ref viewProj, (CompoundColliderShape)compound[i], element); * break; * * default: * { * var physTrans = Matrix.Multiply(subShape.PositiveCenterMatrix, element.Collider.PhysicsWorldTransform); * * //must account collider shape scaling * Matrix worldTrans; * Matrix.Multiply(ref subShape.DebugPrimitiveScaling, ref physTrans, out worldTrans); * * Simulation.DebugEffect.WorldViewProj = worldTrans * viewProj; * Simulation.DebugEffect.Color = element.Collider.IsActive ? Color.Green : Color.Red; * Simulation.DebugEffect.UseUv = subShape.Type != ColliderShapeTypes.ConvexHull; * * Simulation.DebugEffect.Apply(); * * subShape.DebugPrimitive.Draw(); * } * break; * } * } * } * * private void DebugShapesDraw(RenderContext context) * { * if ( !Simulation.CreateDebugPrimitives || * !Simulation.RenderDebugPrimitives || * Simulation.DebugGraphicsDevice == null || * Simulation.DebugEffect == null) * return; * * Matrix viewProj; * if (context.Parameters.ContainsKey(TransformationKeys.View) && context.Parameters.ContainsKey(TransformationKeys.Projection)) * { * viewProj = context.Parameters.Get(TransformationKeys.View) * context.Parameters.Get(TransformationKeys.Projection); * } * else * { * return; * } * * var rasterizers = Simulation.DebugGraphicsDevice.RasterizerStates; * Simulation.DebugGraphicsDevice.SetRasterizerState(rasterizers.CullNone); * * foreach (var element in elements) * { * var shape = element.Shape.Shape; * * if (shape.Type == ColliderShapeTypes.Compound) //multiple shapes * { * DrawDebugCompound(ref viewProj, (CompoundColliderShape)shape, element); * } * else if (shape.Type != ColliderShapeTypes.StaticPlane) //a single shape * { * var physTrans = element.Collider.PhysicsWorldTransform; * * //must account collider shape scaling * Matrix worldTrans; * Matrix.Multiply(ref element.Shape.Shape.DebugPrimitiveScaling, ref physTrans, out worldTrans); * * Simulation.DebugEffect.WorldViewProj = worldTrans * viewProj; * Simulation.DebugEffect.Color = element.Collider.IsActive ? Color.Green : Color.Red; * Simulation.DebugEffect.UseUv = shape.Type != ColliderShapeTypes.ConvexHull; * * Simulation.DebugEffect.Apply(); * * shape.DebugPrimitive.Draw(); * } * } * * Simulation.DebugGraphicsDevice.SetRasterizerState(rasterizers.CullBack); * } */ internal void UpdateCharacters() { charactersProfilingState.Begin(); //characters need manual updating foreach (var element in characters) { if (!element.Collider.Enabled) { continue; } var worldTransform = element.Collider.PhysicsWorldTransform; element.UpdateTransformationComponent(ref worldTransform); charactersProfilingState.Mark(); } charactersProfilingState.End(); }
internal void SendEvents() { ++eventFrame; foreach (var collision in newCollisionsCache) { while (collision.ColliderA.NewPairChannel.Balance < 0) { collision.ColliderA.NewPairChannel.Send(collision); } while (collision.ColliderB.NewPairChannel.Balance < 0) { collision.ColliderB.NewPairChannel.Send(collision); } } foreach (var collision in removedCollisionsCache) { while (collision.ColliderA.PairEndedChannel.Balance < 0) { collision.ColliderA.PairEndedChannel.Send(collision); } while (collision.ColliderB.PairEndedChannel.Balance < 0) { collision.ColliderB.PairEndedChannel.Send(collision); } } foreach (var contactPoint in newContactsFastCache) { while (contactPoint.Collision.NewContactChannel.Balance < 0) { contactPoint.Collision.NewContactChannel.Send(contactPoint); } } foreach (var contactPoint in updatedContactsCache) { while (contactPoint.Collision.ContactUpdateChannel.Balance < 0) { contactPoint.Collision.ContactUpdateChannel.Send(contactPoint); } } foreach (var contactPoint in removedContactsCache) { while (contactPoint.Collision.ContactEndedChannel.Balance < 0) { contactPoint.Collision.ContactEndedChannel.Send(contactPoint); } } newCollisionsCache.Clear(); removedCollisionsCache.Clear(); newContactsFastCache.Clear(); updatedContactsCache.Clear(); removedContactsCache.Clear(); contactsProfilingState.End("Contacts: {0}", frameContacts.Count); }
internal void ProcessContacts() { contactsProfilingState.Begin(); processedPairsFastCache.Clear(); var numManifolds = collisionWorld.Dispatcher.NumManifolds; for (var i = 0; i < numManifolds; i++) { var manifold = collisionWorld.Dispatcher.GetManifoldByIndexInternal(i); var bodyA = manifold.Body0; var bodyB = manifold.Body1; var colA = (Collider)bodyA?.UserObject; var colB = (Collider)bodyB?.UserObject; if (colA == null || colB == null) { continue; } if (!colA.ContactsAlwaysValid && !colB.ContactsAlwaysValid) { continue; } //Pairs management Collision pair = null; var newPair = true; foreach (var pair1 in colA.Collisions) { if ((pair1.ColliderA != colA || pair1.ColliderB != colB) && (pair1.ColliderA != colB || pair1.ColliderB != colA)) { continue; } pair = pair1; newPair = false; break; } var numContacts = manifold.NumContacts; if (numContacts == 0 && newPair) { continue; } newContactsFastCache.Clear(); updatedContactsFastCache.Clear(); deletedContactsFastCache.Clear(); if (newPair) { if (collisionsQueue.Count > 0) { pair = collisionsQueue.Dequeue(); } else { pair = new Collision { Contacts = new List <ContactPoint>() }; } pair.ColliderA = colA; pair.ColliderB = colB; pair.Contacts.Clear(); colA.Collisions.Add(pair); colB.Collisions.Add(pair); alivePairsFastCache.Add(pair); } else { foreach (var contact in pair.Contacts) { deletedContactsFastCache.Add(contact); } } processedPairsFastCache.Add(pair); for (var y = 0; y < numContacts; y++) { var cp = manifold.GetContactPoint(y); ContactPoint contact = null; var newContact = true; foreach (var contact1 in pair.Contacts) { if (contact1.Handle.IsAllocated && cp.UserPersistentPtr != IntPtr.Zero && contact1.Handle.Target != GCHandle.FromIntPtr(cp.UserPersistentPtr).Target) { continue; } contact = contact1; newContact = false; break; } contactsProfilingState.Mark(); if (newContact) { contact = contactsQueue.Count > 0 ? contactsQueue.Dequeue() : new ContactPoint(); contact.Distance = cp.Distance; contact.PositionOnA = new Vector3(cp.PositionWorldOnA.X, cp.PositionWorldOnA.Y, cp.PositionWorldOnA.Z); contact.PositionOnB = new Vector3(cp.PositionWorldOnB.X, cp.PositionWorldOnB.Y, cp.PositionWorldOnB.Z); contact.Normal = new Vector3(cp.NormalWorldOnB.X, cp.NormalWorldOnB.Y, cp.NormalWorldOnB.Z); contact.Pair = pair; contact.Handle = GCHandle.Alloc(contact); cp.UserPersistentPtr = GCHandle.ToIntPtr(contact.Handle); pair.Contacts.Add(contact); } else { deletedContactsFastCache.Remove(contact); } if (newContact) { newContactsFastCache.Add(contact); } else { updatedContactsFastCache.Add(contact); } } //deliver async events if (newPair) { //are we the first pair we detect? if (colA.Collisions.Count == 1) { while (colA.FirstCollisionChannel.Balance < 0) { colA.FirstCollisionChannel.Send(pair); } } //are we the first pair we detect? if (colB.Collisions.Count == 1) { while (colB.FirstCollisionChannel.Balance < 0) { colB.FirstCollisionChannel.Send(pair); } } while (colA.NewPairChannel.Balance < 0) { colA.NewPairChannel.Send(pair); } while (colB.NewPairChannel.Balance < 0) { colB.NewPairChannel.Send(pair); } } foreach (var contact in newContactsFastCache) { while (contact.Pair.NewContactChannel.Balance < 0) { contact.Pair.NewContactChannel.Send(contact); } } foreach (var contact in updatedContactsFastCache) { while (contact.Pair.ContactUpdateChannel.Balance < 0) { contact.Pair.ContactUpdateChannel.Send(contact); } } foreach (var contact in deletedContactsFastCache) { while (contact.Pair.ContactEndedChannel.Balance < 0) { contact.Pair.ContactEndedChannel.Send(contact); } pair.Contacts.Remove(contact); contact.Handle.Free(); contactsQueue.Enqueue(contact); } if (pair.Contacts.Count == 0) { colA.Collisions.Remove(pair); colB.Collisions.Remove(pair); alivePairsFastCache.Remove(pair); collisionsQueue.Enqueue(pair); while (colA.PairEndedChannel.Balance < 0) { colA.PairEndedChannel.Send(pair); } while (colB.PairEndedChannel.Balance < 0) { colB.PairEndedChannel.Send(pair); } if (colA.Collisions.Count == 0) { while (colA.AllPairsEndedChannel.Balance < 0) { colA.AllPairsEndedChannel.Send(pair); } } if (colB.Collisions.Count == 0) { while (colB.AllPairsEndedChannel.Balance < 0) { colB.AllPairsEndedChannel.Send(pair); } } } } //Sometimes narrowphase is skipped it seems and we might get some stuck pair! foreach (var pair in alivePairsFastCache) { if (!processedPairsFastCache.Contains(pair)) { removedPairsFastCache.Enqueue(pair); } } while (removedPairsFastCache.Count > 0) { var pair = removedPairsFastCache.Dequeue(); alivePairsFastCache.Remove(pair); //this pair got removed! foreach (var contactPoint in pair.Contacts) { while (contactPoint.Pair.ContactEndedChannel.Balance < 0) { contactPoint.Pair.ContactEndedChannel.Send(contactPoint); } contactPoint.Handle.Free(); contactsQueue.Enqueue(contactPoint); } var colA = pair.ColliderA; var colB = pair.ColliderB; colA.Collisions.Remove(pair); colB.Collisions.Remove(pair); collisionsQueue.Enqueue(pair); while (colA.PairEndedChannel.Balance < 0) { colA.PairEndedChannel.Send(pair); } while (colB.PairEndedChannel.Balance < 0) { colB.PairEndedChannel.Send(pair); } if (colA.Collisions.Count == 0) { while (colA.AllPairsEndedChannel.Balance < 0) { colA.AllPairsEndedChannel.Send(pair); } } if (colB.Collisions.Count == 0) { while (colB.AllPairsEndedChannel.Balance < 0) { colB.AllPairsEndedChannel.Send(pair); } } } contactsProfilingState.End(); }