Пример #1
0
        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);
        }
Пример #2
0
        public GcProfiling()
        {
            collectionCountState = Profiler.New(GcCollectionCountKey);
            gen0Count            = GC.CollectionCount(0);
            gen1Count            = GC.CollectionCount(1);
            gen2Count            = GC.CollectionCount(2);
            collectionCountState.Begin(gen0Count, gen1Count, gen2Count);

            gcMemoryState = Profiler.New(GcMemoryKey);
            memoryPeak    = lastFrameMemory = GC.GetTotalMemory(false);
            gcMemoryState.Begin(lastFrameMemory, lastFrameMemory, memoryPeak);
        }
Пример #3
0
        /*
         * 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();
        }
Пример #4
0
        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();
        }