void UpdatePhysics(float deltaTime)
        {
            LastProcessedBoundingBoxes.Clear();

            foreach (IPhysicsEngineExtension ext in extensions)
            {
                if (ext.IsActive)
                {
                    ext.RecyclePhysicsObjects();
                }
            }

            Step(deltaTime);
            BroadphaseMulti(IntersectionType.Soft, deltaTime);
            CollisionResponse(deltaTime);
            BroadphaseMulti(IntersectionType.Rigid, deltaTime);
            CollisionResponse(deltaTime);
            ApplyDeltaSnapshots(deltaTime);
        }
        void Broadphase(IntersectionType forType, PhysicsBodyComponent p1, float deltaTime, int start)
        {
            if (!p1.IsEnabled || !p1.GameObject.IsEnabled)
            {
                return;
            }
            if (!p1.CanCollide)
            {
                return;
            }

            // For every object, check if it CAN intersect with any other object
            AxisAlignedBoundingBox p1Collider     = p1.GetCollider();
            AxisAlignedBoundingBox p1Broad        = p1.GetBroadphase();
            AxisAlignedBoundingBox?p1StepCollider = null;

            if (p1.CanStep)
            {
                p1StepCollider = p1.GetColliderAt(p1.Delta.StepPosition);
            }

            if (RecordProcessedBoundingBoxes)
            {
                LastProcessedBoundingBoxes.Add(p1Collider);
                LastProcessedBoundingBoxes.Add(p1Broad);
            }

            for (int k = start; k < physicsBodies.Count; k++)
            {
                PhysicsBodyComponent p2 = physicsBodies[k];
                if (!p2.IsEnabled || !p2.GameObject.IsEnabled)
                {
                    continue;
                }
                if (p2 == p1)
                {
                    continue;
                }
                if (!p2.CanCollide)
                {
                    continue;
                }

                // Get the type of intersection to determine how it should be handled
                IntersectionType type = GetIntersectionType(p1.IsStatic, p2.IsStatic);
                if (type != forType)
                {
                    continue;
                }
                if (forType == IntersectionType.Soft && (!p2.CanCollideWithSoft || !p1.CanCollideWithSoft))
                {
                    continue;
                }

                AxisAlignedBoundingBox p2Collider     = p2.GetCollider();
                AxisAlignedBoundingBox p2Broad        = p2.GetBroadphase();
                AxisAlignedBoundingBox?p2StepCollider = null;
                if (p2.CanStep)
                {
                    p2StepCollider = p2.GetColliderAt(p2.Delta.StepPosition);
                }

                if (RecordProcessedBoundingBoxes)
                {
                    LastProcessedBoundingBoxes.Add(p2Collider);
                    LastProcessedBoundingBoxes.Add(p2Broad);
                }

                // Check if the objects CAN intersect
                if (CanIntersect(p1.IsStatic, p1Collider, p1Broad, p2.IsStatic, p2Collider, p2Broad))
                {
                    // Calculate max step
                    if (type == IntersectionType.Rigid)
                    {
                        CalculateMaxStep(p1, p2, p1Collider, p1StepCollider, p2Collider, p2StepCollider);
                    }

                    // Add the possible intersection
                    Intersection intersect = new Intersection(p1, p2, sweepResolver, deltaTime, type);
                    broadIntersections.Add(intersect);
                }
            }

            // Let extensions run
            foreach (IPhysicsEngineExtension ext in extensions)
            {
                if (!ext.IsActive || !ext.CanCheck(forType, p1.IsStatic))
                {
                    continue;
                }

                // Get intersections from extensions
                IEnumerable <PhysicsBodyComponent> intersections = ext.GetBroadphaseIntersections(p1Broad);

                foreach (PhysicsBodyComponent physOb in intersections)
                {
                    AxisAlignedBoundingBox?physObStepCollider = null;
                    if (physOb.CanStep)
                    {
                        physObStepCollider = physOb.GetColliderAt(physOb.Delta.StepPosition);
                    }

                    IntersectionType type = GetIntersectionType(p1.IsStatic, physOb.IsStatic);

                    // Calculate max step
                    if (type == IntersectionType.Rigid)
                    {
                        CalculateMaxStep(p1, physOb, p1Collider, p1StepCollider, physOb.GetCollider(), physObStepCollider);
                    }

                    // Add the possible intersection
                    Intersection intersection = new Intersection(p1, physOb, sweepResolver, deltaTime, IntersectionType.Rigid);
                    broadIntersections.Add(intersection);
                }
            }
        }