Exemple #1
0
        /// <summary>
        /// Applies buoyancy forces to appropriate objects.
        /// Called automatically when needed by the owning Space.
        /// </summary>
        /// <param name="dt">Time since last frame in physical logic.</param>
        void IDuringForcesUpdateable.Update(float dt)
        {
            QueryAccelerator.GetEntries(boundingBox, broadPhaseEntries);
            //TODO: Could integrate the entire thing into the collision detection pipeline.  Applying forces
            //in the collision detection pipeline isn't allowed, so there'd still need to be an Updateable involved.
            //However, the broadphase query would be eliminated and the raycasting work would be automatically multithreaded.

            this.dt = dt;

            //Don't always multithread.  For small numbers of objects, the overhead of using multithreading isn't worth it.
            //Could tune this value depending on platform for better performance.
            if (broadPhaseEntries.Count > 30 && ParallelLooper != null && ParallelLooper.ThreadCount > 1)
            {
                ParallelLooper.ForLoop(0, broadPhaseEntries.Count, analyzeCollisionEntryDelegate);
            }
            else
            {
                for (int i = 0; i < broadPhaseEntries.Count; i++)
                {
                    AnalyzeEntry(i);
                }
            }

            broadPhaseEntries.Clear();
        }
        /// <summary>
        /// Updates the listing of contained entities and their states after the end of a space update.
        /// </summary>
        /// <param name="dt">Time since last frame in simulation seconds.</param>
        void IEndOfTimeStepUpdateable.Update(float dt)
        {
            //Get rid of any entities that are no longer nearby.
            foreach (Entity e in nearbyEntities.Keys)
            {
                if (!(e.CollisionInformation.BoundingBox.Intersects(TriangleMesh.Tree.BoundingBox)))
                {
                    entities.Add(e);
                }
            }

            for (int i = 0; i < entities.count; i++)
            {
                var e = entities.Elements[i];
                if (nearbyEntities[e].IsContained)
                {
                    //STOPS CONTAINED event
                    if (VolumeStopsContainingEntity != null)
                    {
                        VolumeStopsContainingEntity(this, e);
                    }
                }
                if (nearbyEntities[e].IsTouching)
                {
                    //STOPS TOUCHING event
                    if (EntityStopsTouching != null)
                    {
                        EntityStopsTouching(e, this);
                    }
                }

                nearbyEntities.Remove(e);
            }
            entities.Clear();

            //Get an updated look at all included entities.
            QueryAccelerator.GetEntries(TriangleMesh.Tree.BoundingBox, entries);
            for (int i = 0; i < entries.count; i++)
            {
                var e = entries.Elements[i] as EntityCollidable;
                if (e != null && CollisionRules.collisionRuleCalculator(e.collisionRules, collisionRules) <= CollisionRule.NoSolver)
                {
                    entities.Add(e.Entity);
                }
            }
            entries.Clear();
            ContainmentState containmentState;

            for (int i = 0; i < entities.count; i++)
            {
                var  e = entities.Elements[i];
                bool isContained;
                bool isTouching = IsEntityIntersectingVolume(e, out isContained);
                if (nearbyEntities.TryGetValue(e, out containmentState))
                {
                    if (!containmentState.IsTouching && isTouching)
                    {
                        //BEGIN TOUCHING event
                        if (EntityBeginsTouching != null)
                        {
                            EntityBeginsTouching(e, this);
                        }
                    }
                    else if (containmentState.IsTouching && !isTouching)
                    {
                        //END TOUCHING event
                        if (EntityStopsTouching != null)
                        {
                            EntityStopsTouching(e, this);
                        }
                    }
                    if (!containmentState.IsContained && isContained)
                    {
                        //BEGIN CONTAINED event
                        if (VolumeBeginsContainingEntity != null)
                        {
                            VolumeBeginsContainingEntity(this, e);
                        }
                    }
                    else if (containmentState.IsContained && !isContained)
                    {
                        //END CONTAINED event
                        if (VolumeStopsContainingEntity != null)
                        {
                            VolumeStopsContainingEntity(this, e);
                        }
                    }
                    nearbyEntities[e] = new ContainmentState(isTouching, isContained);
                }
                else
                {
                    //Add new entry for the new entity.
                    nearbyEntities.Add(e, new ContainmentState(isTouching, isContained));
                    if (isTouching)
                    {
                        //BEGIN TOUCHING event
                        if (EntityBeginsTouching != null)
                        {
                            EntityBeginsTouching(e, this);
                        }
                    }
                    if (isContained)
                    {
                        //BEGIN CONTAINED event
                        if (VolumeBeginsContainingEntity != null)
                        {
                            VolumeBeginsContainingEntity(this, e);
                        }
                    }
                }
            }

            entities.Clear();
        }