Broad phase that incrementally updates the internal tree acceleration structure.
This is a good all-around broad phase; its performance is consistent and all queries are supported and speedy. The memory usage is higher than simple one-axis sort and sweep, but a bit lower than the Grid2DSortAndSweep option.
Inheritance: BroadPhase
Example #1
0
        ///<summary>
        /// Constructs a new space for things to live in.
        ///</summary>
        ///<param name="parallelLooper">Used by the space to perform multithreaded updates. Pass null if multithreading is not required.</param>
        public Space(IParallelLooper parallelLooper)
        {
            timeStepSettings = new TimeStepSettings();

            this.parallelLooper = parallelLooper;

            SpaceObjectBuffer = new SpaceObjectBuffer(this);
            EntityStateWriteBuffer = new EntityStateWriteBuffer();
            DeactivationManager = new DeactivationManager(TimeStepSettings, ParallelLooper);
            ForceUpdater = new ForceUpdater(TimeStepSettings, ParallelLooper);
            BoundingBoxUpdater = new BoundingBoxUpdater(TimeStepSettings, ParallelLooper);
            BroadPhase = new DynamicHierarchy(ParallelLooper);
            NarrowPhase = new NarrowPhase(TimeStepSettings, BroadPhase.Overlaps, ParallelLooper);
            Solver = new Solver(TimeStepSettings, DeactivationManager, ParallelLooper);
            NarrowPhase.Solver = Solver;
            PositionUpdater = new ContinuousPositionUpdater(TimeStepSettings, ParallelLooper);
            BufferedStates = new BufferedStatesManager(ParallelLooper);
            DeferredEventDispatcher = new DeferredEventDispatcher();

            DuringForcesUpdateables = new DuringForcesUpdateableManager(timeStepSettings, ParallelLooper);
            BeforeNarrowPhaseUpdateables = new BeforeNarrowPhaseUpdateableManager(timeStepSettings, ParallelLooper);
            BeforeSolverUpdateables = new BeforeSolverUpdateableManager(timeStepSettings, ParallelLooper);
            BeforePositionUpdateUpdateables = new BeforePositionUpdateUpdateableManager(timeStepSettings, ParallelLooper);
            EndOfTimeStepUpdateables = new EndOfTimeStepUpdateableManager(timeStepSettings, ParallelLooper);
            EndOfFrameUpdateables = new EndOfFrameUpdateableManager(timeStepSettings, ParallelLooper);
        }
Example #2
0
        internal override void GetOverlaps(Node opposingNode, DynamicHierarchy owner)
        {
            bool intersects;

            //note: This is never executed when the opposing node is the current node.
            if (opposingNode.IsLeaf)
            {
                //We're both leaves!  Our parents have already done the testing for us, so we know we're overlapping.
                owner.TryToAddOverlap(element, opposingNode.Element);
            }
            else
            {
                var opposingChildA = opposingNode.ChildA;
                var opposingChildB = opposingNode.ChildB;
                //If it's not a leaf, try to go deeper in the opposing hierarchy.
                BoundingBox.Intersects(ref opposingChildA.BoundingBox, out intersects);
                if (intersects)
                {
                    GetOverlaps(opposingChildA, owner);
                }
                BoundingBox.Intersects(ref opposingChildB.BoundingBox, out intersects);
                if (intersects)
                {
                    GetOverlaps(opposingChildB, owner);
                }
            }
        }
        /// <summary>
        /// Constructs a new demo.
        /// </summary>
        /// <param name="game">Game owning this demo.</param>
        public BroadPhaseRemovalTestDemo(DemosGame game)
            : base(game)
        {
            Entity toAdd;
            //BoundingBox box = new BoundingBox(new Vector3(-5, 1, 1), new Vector3(5, 7, 7));
            BoundingBox box = new BoundingBox(new Vector3(-500, -500, -500), new Vector3(500, 500, 500));

            DynamicHierarchy dh = new DynamicHierarchy();

            Random rand = new Random(0);

            RawList<Entity> entities = new RawList<Entity>();
            for (int k = 0; k < 1000; k++)
            {
                Vector3 position = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X),
                                               (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y),
                                               (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z));
                toAdd = new Box(MathConverter.Convert(position), 1, 1, 1, 1);

                entities.Add(toAdd);

            }

            testResults = new double[2];
            int runCount = 10;
            for (int k = 0; k < runCount; k++)
            {

                for (int i = 0; i < entities.Count; i++)
                {
                    dh.Add(entities[i].CollisionInformation);
                }

                long start = Stopwatch.GetTimestamp();
                for (int i = 0; i < entities.Count; i++)
                {
                    //dh.RemoveFast(entities[i].CollisionInformation);
                }
                long end = Stopwatch.GetTimestamp();
                testResults[0] += (end - start) / (double)Stopwatch.Frequency;

                for (int i = 0; i < entities.Count; i++)
                {
                    dh.Add(entities[i].CollisionInformation);
                }

                start = Stopwatch.GetTimestamp();
                for (int i = 0; i < entities.Count; i++)
                {
                    //dh.RemoveBrute(entities[i].CollisionInformation);
                }
                end = Stopwatch.GetTimestamp();
                testResults[1] += (end - start) / (double)Stopwatch.Frequency;

            }
            testResults[0] /= runCount;
            testResults[1] /= runCount;
        }
Example #4
0
        internal override void GetMultithreadedOverlaps(Node opposingNode, int splitDepth, int currentDepth, DynamicHierarchy owner, RawList <DynamicHierarchy.NodePair> multithreadingSourceOverlaps)
        {
            bool intersects;

            //note: This is never executed when the opposing node is the current node.
            if (opposingNode.IsLeaf)
            {
                //We're both leaves!  Our parents have already done the testing for us, so we know we're overlapping.
                owner.TryToAddOverlap(element, opposingNode.Element);
            }
            else
            {
                var opposingChildA = opposingNode.ChildA;
                var opposingChildB = opposingNode.ChildB;
                if (splitDepth == currentDepth)
                {
                    //Time to add the child overlaps to the multithreading set!
                    BoundingBox.Intersects(ref opposingChildA.BoundingBox, out intersects);
                    if (intersects)
                    {
                        multithreadingSourceOverlaps.Add(new DynamicHierarchy.NodePair()
                        {
                            a = this, b = opposingChildA
                        });
                    }
                    BoundingBox.Intersects(ref opposingChildB.BoundingBox, out intersects);
                    if (intersects)
                    {
                        multithreadingSourceOverlaps.Add(new DynamicHierarchy.NodePair()
                        {
                            a = this, b = opposingChildB
                        });
                    }

                    return;
                }
                //If it's not a leaf, try to go deeper in the opposing hierarchy.
                BoundingBox.Intersects(ref opposingChildA.BoundingBox, out intersects);
                if (intersects)
                {
                    GetOverlaps(opposingChildA, owner);
                }
                BoundingBox.Intersects(ref opposingChildB.BoundingBox, out intersects);
                if (intersects)
                {
                    GetOverlaps(opposingChildB, owner);
                }
            }
        }
Example #5
0
        internal override void GetMultithreadedOverlaps(Node opposingNode, int splitDepth, int currentDepth, DynamicHierarchy owner, RawList <DynamicHierarchy.NodePair> multithreadingSourceOverlaps)
        {
            bool intersects;

            if (currentDepth == splitDepth)
            {
                //We've reached the depth where our child comparisons will be multithreaded.
                if (this == opposingNode)
                {
                    //We are being compared against ourselves!
                    //Obviously we're an internal node, so spawn three children:
                    //A versus A:
                    if (!childA.IsLeaf) //This is performed in the child method usually by convention, but this saves some time.
                    {
                        multithreadingSourceOverlaps.Add(new DynamicHierarchy.NodePair()
                        {
                            a = childA, b = childA
                        });
                    }
                    //B versus B:
                    if (!childB.IsLeaf) //This is performed in the child method usually by convention, but this saves some time.
                    {
                        multithreadingSourceOverlaps.Add(new DynamicHierarchy.NodePair()
                        {
                            a = childB, b = childB
                        });
                    }
                    //A versus B (if they intersect):
                    childA.BoundingBox.Intersects(ref childB.BoundingBox, out intersects);
                    if (intersects)
                    {
                        multithreadingSourceOverlaps.Add(new DynamicHierarchy.NodePair()
                        {
                            a = childA, b = childB
                        });
                    }
                }
                else
                {
                    //Two different nodes.  The other one may be a leaf.
                    if (opposingNode.IsLeaf)
                    {
                        //If it's a leaf, go deeper in our hierarchy, but not the opposition.
                        childA.BoundingBox.Intersects(ref opposingNode.BoundingBox, out intersects);
                        if (intersects)
                        {
                            multithreadingSourceOverlaps.Add(new DynamicHierarchy.NodePair()
                            {
                                a = childA, b = opposingNode
                            });
                        }
                        childB.BoundingBox.Intersects(ref opposingNode.BoundingBox, out intersects);
                        if (intersects)
                        {
                            multithreadingSourceOverlaps.Add(new DynamicHierarchy.NodePair()
                            {
                                a = childB, b = opposingNode
                            });
                        }
                    }
                    else
                    {
                        var opposingChildA = opposingNode.ChildA;
                        var opposingChildB = opposingNode.ChildB;
                        //If it's not a leaf, try to go deeper in both hierarchies.
                        childA.BoundingBox.Intersects(ref opposingChildA.BoundingBox, out intersects);
                        if (intersects)
                        {
                            multithreadingSourceOverlaps.Add(new DynamicHierarchy.NodePair()
                            {
                                a = childA, b = opposingChildA
                            });
                        }
                        childA.BoundingBox.Intersects(ref opposingChildB.BoundingBox, out intersects);
                        if (intersects)
                        {
                            multithreadingSourceOverlaps.Add(new DynamicHierarchy.NodePair()
                            {
                                a = childA, b = opposingChildB
                            });
                        }
                        childB.BoundingBox.Intersects(ref opposingChildA.BoundingBox, out intersects);
                        if (intersects)
                        {
                            multithreadingSourceOverlaps.Add(new DynamicHierarchy.NodePair()
                            {
                                a = childB, b = opposingChildA
                            });
                        }
                        childB.BoundingBox.Intersects(ref opposingChildB.BoundingBox, out intersects);
                        if (intersects)
                        {
                            multithreadingSourceOverlaps.Add(new DynamicHierarchy.NodePair()
                            {
                                a = childB, b = opposingChildB
                            });
                        }
                    }
                }
                return;
            }
            if (this == opposingNode)
            {
                //We are being compared against ourselves!
                //Obviously we're an internal node, so spawn three children:
                //A versus A:
                if (!childA.IsLeaf) //This is performed in the child method usually by convention, but this saves some time.
                {
                    childA.GetMultithreadedOverlaps(childA, splitDepth, currentDepth + 1, owner, multithreadingSourceOverlaps);
                }
                //B versus B:
                if (!childB.IsLeaf) //This is performed in the child method usually by convention, but this saves some time.
                {
                    childB.GetMultithreadedOverlaps(childB, splitDepth, currentDepth + 1, owner, multithreadingSourceOverlaps);
                }
                //A versus B (if they intersect):
                childA.BoundingBox.Intersects(ref childB.BoundingBox, out intersects);
                if (intersects)
                {
                    childA.GetMultithreadedOverlaps(childB, splitDepth, currentDepth + 1, owner, multithreadingSourceOverlaps);
                }
            }
            else
            {
                //Two different nodes.  The other one may be a leaf.
                if (opposingNode.IsLeaf)
                {
                    //If it's a leaf, go deeper in our hierarchy, but not the opposition.
                    childA.BoundingBox.Intersects(ref opposingNode.BoundingBox, out intersects);
                    if (intersects)
                    {
                        childA.GetMultithreadedOverlaps(opposingNode, splitDepth, currentDepth + 1, owner, multithreadingSourceOverlaps);
                    }
                    childB.BoundingBox.Intersects(ref opposingNode.BoundingBox, out intersects);
                    if (intersects)
                    {
                        childB.GetMultithreadedOverlaps(opposingNode, splitDepth, currentDepth + 1, owner, multithreadingSourceOverlaps);
                    }
                }
                else
                {
                    var opposingChildA = opposingNode.ChildA;
                    var opposingChildB = opposingNode.ChildB;
                    //If it's not a leaf, try to go deeper in both hierarchies.
                    childA.BoundingBox.Intersects(ref opposingChildA.BoundingBox, out intersects);
                    if (intersects)
                    {
                        childA.GetMultithreadedOverlaps(opposingChildA, splitDepth, currentDepth + 1, owner, multithreadingSourceOverlaps);
                    }
                    childA.BoundingBox.Intersects(ref opposingChildB.BoundingBox, out intersects);
                    if (intersects)
                    {
                        childA.GetMultithreadedOverlaps(opposingChildB, splitDepth, currentDepth + 1, owner, multithreadingSourceOverlaps);
                    }
                    childB.BoundingBox.Intersects(ref opposingChildA.BoundingBox, out intersects);
                    if (intersects)
                    {
                        childB.GetMultithreadedOverlaps(opposingChildA, splitDepth, currentDepth + 1, owner, multithreadingSourceOverlaps);
                    }
                    childB.BoundingBox.Intersects(ref opposingChildB.BoundingBox, out intersects);
                    if (intersects)
                    {
                        childB.GetMultithreadedOverlaps(opposingChildB, splitDepth, currentDepth + 1, owner, multithreadingSourceOverlaps);
                    }
                }
            }
        }
Example #6
0
 internal abstract void GetMultithreadedOverlaps(Node opposingNode, int splitDepth, int currentDepth, DynamicHierarchy owner, RawList <DynamicHierarchy.NodePair> multithreadingSourceOverlaps);
Example #7
0
 internal abstract void GetOverlaps(Node node, DynamicHierarchy owner);
Example #8
0
        internal override void GetOverlaps(Node opposingNode, DynamicHierarchy owner)
        {
            bool intersects;

            if (this == opposingNode)
            {
                //We are being compared against ourselves!
                //Obviously we're an internal node, so spawn three children:
                //A versus A:
                if (!childA.IsLeaf) //This is performed in the child method usually by convention, but this saves some time.
                {
                    childA.GetOverlaps(childA, owner);
                }
                //B versus B:
                if (!childB.IsLeaf) //This is performed in the child method usually by convention, but this saves some time.
                {
                    childB.GetOverlaps(childB, owner);
                }
                //A versus B (if they intersect):
                childA.BoundingBox.Intersects(ref childB.BoundingBox, out intersects);
                if (intersects)
                {
                    childA.GetOverlaps(childB, owner);
                }
            }
            else
            {
                //Two different nodes.  The other one may be a leaf.
                if (opposingNode.IsLeaf)
                {
                    //If it's a leaf, go deeper in our hierarchy, but not the opposition.
                    childA.BoundingBox.Intersects(ref opposingNode.BoundingBox, out intersects);
                    if (intersects)
                    {
                        childA.GetOverlaps(opposingNode, owner);
                    }
                    childB.BoundingBox.Intersects(ref opposingNode.BoundingBox, out intersects);
                    if (intersects)
                    {
                        childB.GetOverlaps(opposingNode, owner);
                    }
                }
                else
                {
                    var opposingChildA = opposingNode.ChildA;
                    var opposingChildB = opposingNode.ChildB;
                    //If it's not a leaf, try to go deeper in both hierarchies.
                    childA.BoundingBox.Intersects(ref opposingChildA.BoundingBox, out intersects);
                    if (intersects)
                    {
                        childA.GetOverlaps(opposingChildA, owner);
                    }
                    childA.BoundingBox.Intersects(ref opposingChildB.BoundingBox, out intersects);
                    if (intersects)
                    {
                        childA.GetOverlaps(opposingChildB, owner);
                    }
                    childB.BoundingBox.Intersects(ref opposingChildA.BoundingBox, out intersects);
                    if (intersects)
                    {
                        childB.GetOverlaps(opposingChildA, owner);
                    }
                    childB.BoundingBox.Intersects(ref opposingChildB.BoundingBox, out intersects);
                    if (intersects)
                    {
                        childB.GetOverlaps(opposingChildB, owner);
                    }
                }
            }
        }
Example #9
0
 internal DynamicHierarchyQueryAccelerator(DynamicHierarchy hierarchy)
 {
     this.hierarchy = hierarchy;
 }
        double RunTest(int splitOffset, IParallelLooper parallelLooper)
        {
            Entity toAdd;
            //BoundingBox box = new BoundingBox(new Vector3(-5, 1, 1), new Vector3(5, 7, 7));
            BoundingBox box = new BoundingBox(new Vector3(-500, -500, -500), new Vector3(500, 500, 500));

            int splitDepth = splitOffset + (int)Math.Ceiling(Math.Log(parallelLooper.ThreadCount, 2));

            DynamicHierarchy dh = new DynamicHierarchy(parallelLooper);

            Random rand = new Random(0);

            RawList<Entity> entities = new RawList<Entity>();
            for (int k = 0; k < 10000; k++)
            {
                Vector3 position = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X),
                                               (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y),
                                               (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z));
                toAdd = new Box(position, 1, 1, 1, 1);
                toAdd.CollisionInformation.CollisionRules.Personal = CollisionRule.NoNarrowPhasePair;
                toAdd.CollisionInformation.UpdateBoundingBox(0);


                dh.Add(toAdd.CollisionInformation);
                entities.Add(toAdd);

            }


            Space.ForceUpdater.Gravity = new Vector3();

            int numRuns = 3000;
            //Prime the system.
            dh.Update();
            var testType = Test.Update;

            BroadPhaseOverlap[] overlapBasis = new BroadPhaseOverlap[dh.Overlaps.Count];
            dh.Overlaps.CopyTo(overlapBasis, 0);


            double time = 0;
            double startTime, endTime;


            switch (testType)
            {
                #region Update Timing
                case Test.Update:
                    for (int i = 0; i < numRuns; i++)
                    {
                        //DH4
                        startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        //dh.Update();
                        //lock (dh.Locker)
                        //{
                        //    dh.Overlaps.Clear();
                        //    if (dh.ROOTEXISTS)
                        //    {
                        //        dh.MultithreadedRefitPhase(splitDepth);

                        //        dh.MultithreadedOverlapPhase(splitDepth);
                        //    }
                        //}

                        //dh.Update();

                        //lock (dh.Locker)
                        //{
                        //    dh.Overlaps.Clear();
                        //    if (dh.ROOTEXISTS)
                        //    {
                        //        dh.SingleThreadedRefitPhase();
                        //        dh.SingleThreadedOverlapPhase();
                        //    }
                        //}

                        endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        time += endTime - startTime;

                        //if (dh.Overlaps.Count != overlapBasis.Length)
                        //    Debug.WriteLine("Failed Update.");
                        //for (int j = 0; j < overlapBasis.Length; j++)
                        //{
                        //    if (!dh.Overlaps.Contains(overlapBasis[j]))
                        //        Debug.WriteLine("Failed Update.");
                        //}


                        //MoveEntities(entities);
                    }
                    break;
                #endregion
                #region Refit Timing
                case Test.Refit:
                    for (int i = 0; i < numRuns; i++)
                    {

                        dh.Overlaps.Clear();

                        //DH4
                        startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        //dh.MultithreadedRefitPhase(splitDepth);
                        //dh.SingleThreadedRefitPhase();
                        endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        time += endTime - startTime;

                        //dh.SingleThreadedOverlapPhase();

                        //if (dh.Overlaps.Count != overlapBasis.Length)
                        //    Debug.WriteLine("Failed Refit.");
                        //for (int j = 0; j < overlapBasis.Length; j++)
                        //{
                        //    if (!dh.Overlaps.Contains(overlapBasis[j]))
                        //        Debug.WriteLine("Failed Refit.");
                        //}

                        //MoveEntities(entities);
                    }
                    break;
                #endregion
                #region Overlap Timing
                case Test.Overlap:
                    for (int i = 0; i < numRuns; i++)
                    {
                        dh.Overlaps.Clear();
                        //dh.MultithreadedRefitPhase(splitDepth);
                        //DH4
                        startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        //dh.MultithreadedOverlapPhase(splitDepth);
                        //dh.SingleThreadedOverlapPhase();
                        endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        time += endTime - startTime;


                        //if (dh.Overlaps.Count != overlapBasis.Length)
                        //    Debug.WriteLine("Failed Overlap.");
                        //for (int j = 0; j < overlapBasis.Length; j++)
                        //{
                        //    if (!dh.Overlaps.Contains(overlapBasis[j]))
                        //        Debug.WriteLine("Failed Overlap.");
                        //}

                        //MoveEntities(entities);
                    }
                    break;
                #endregion
                #region Ray cast timing
                case Test.RayCast:
                    float rayLength = 100;
                    RawList<Ray> rays = new RawList<Ray>();
                    for (int i = 0; i < numRuns; i++)
                    {
                        rays.Add(new Ray()
                        {
                            Position = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X),
                                               (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y),
                                               (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z)),
                            Direction = Vector3.Normalize(new Vector3((float)(rand.NextDouble() - .5), (float)(rand.NextDouble() - .5), (float)(rand.NextDouble() - .5)))
                        });
                    }
                    RawList<BroadPhaseEntry> outputIntersections = new RawList<BroadPhaseEntry>();



                    //DH4
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    for (int i = 0; i < numRuns; i++)
                    {
                        dh.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections);
                        outputIntersections.Clear();
                    }

                    endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    time = endTime - startTime;


                    break;
                #endregion
                #region Bounding box query timing
                case Test.BoundingBoxQuery:
                    float boundingBoxSize = 10;
                    var boundingBoxes = new RawList<BoundingBox>();
                    Vector3 offset = new Vector3(boundingBoxSize / 2, boundingBoxSize / 2, boundingBoxSize / 2);
                    for (int i = 0; i < numRuns; i++)
                    {
                        Vector3 center = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X),
                                                     (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y),
                                                     (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z));
                        boundingBoxes.Add(new BoundingBox()
                        {
                            Min = center - offset,
                            Max = center + offset
                        });
                    }

                    outputIntersections = new RawList<BroadPhaseEntry>();


                    //DH4
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    for (int i = 0; i < numRuns; i++)
                    {
                        dh.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections);
                        outputIntersections.Clear();
                    }

                    endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    time = endTime - startTime;


                    break;
                #endregion
            }


            return time / numRuns;
        }
        /// <summary>
        /// Constructs a new demo.
        /// </summary>
        /// <param name="game">Game owning this demo.</param>
        public BroadPhasesTestDemo(DemosGame game)
            : base(game)
        {
            Space.Solver.IterationLimit = 0;
            Entity toAdd;
            //BoundingBox box = new BoundingBox(new Vector3(-5, 1, 1), new Vector3(5, 7, 7));
            BoundingBox box = new BoundingBox(new Vector3(-50, -50, -50), new Vector3(50, 50, 50));

            //DynamicHierarchyOld dhOld = new DynamicHierarchyOld(Space.ThreadManager);
            DynamicHierarchy dh = new DynamicHierarchy(Space.ParallelLooper);
            SortAndSweep1D sas1d = new SortAndSweep1D(Space.ParallelLooper);
            Grid2DSortAndSweep grid2DSAS = new Grid2DSortAndSweep(Space.ParallelLooper);
            //DynamicHierarchy dh = new DynamicHierarchy();
            //DynamicHierarchy4 dh4 = new DynamicHierarchy4();
            //SortAndSweep1D sas1d = new SortAndSweep1D();
            //Grid2DSortAndSweep grid2DSAS = new Grid2DSortAndSweep();

            //DynamicHierarchy2 dh2 = new DynamicHierarchy2();
            //DynamicHierarchy3 dh3 = new DynamicHierarchy3();
            //SortAndSweep3D sap3d = new SortAndSweep3D();

            RawList<Entity> entities = new RawList<Entity>();
            for (int k = 0; k < 100; k++)
            {
                Vector3 position = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X),
                                               (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y),
                                               (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z));
                toAdd = new Box(position, 1, 1, 1, 1);
                toAdd.CollisionInformation.CollisionRules.Personal = CollisionRule.NoNarrowPhasePair;
                toAdd.CollisionInformation.UpdateBoundingBox(0);
                //Space.Add(toAdd);
                //dhOld.Add(toAdd.CollisionInformation);
                dh.Add(toAdd.CollisionInformation);
                sas1d.Add(toAdd.CollisionInformation);
                grid2DSAS.Add(toAdd.CollisionInformation);
                entities.Add(toAdd);

            }

            Space.ForceUpdater.Gravity = new Vector3();

            int numRuns = 10000;
            //Prime the system.
            grid2DSAS.Update();
            sas1d.Update();
            //dhOld.Update();
            dh.Update();
            var testType = Test.Update;

            double startTime, endTime;

            switch (testType)
            {
                #region Update Timing
                case Test.Update:
                    for (int i = 0; i < numRuns; i++)
                    {
                        ////DH
                        //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        //dhOld.Update();
                        //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        //DHOldTime += endTime - startTime;

                        //DH4
                        startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        dh.Update();
                        endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        DHtime += endTime - startTime;

                        //SAP1D
                        startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        sas1d.Update();
                        endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        SAS1Dtime += endTime - startTime;

                        //Grid2D SOS
                        startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        grid2DSAS.Update();
                        endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                        grid2DSAStime += endTime - startTime;

                        //if (sap1d.Overlaps.Count != dh.Overlaps.Count)
                        //    Debug.WriteLine("SAP1D Failure");
                        //if (grid2DSOS.Overlaps.Count != dh.Overlaps.Count)
                        //    Debug.WriteLine("grid2DSOS Failure");

                        //for (int j = 0; j < dh2.Overlaps.Count; j++)
                        //{
                        //    if (!grid2DSOS.Overlaps.Contains(dh2.Overlaps[j]))
                        //        Debug.WriteLine("Break.");
                        //}
                        //for (int j = 0; j < grid2DSOS.Overlaps.Count; j++)
                        //{
                        //    if (!dh2.Overlaps.Contains(grid2DSOS.Overlaps[j]))
                        //        break;
                        //}

                        //for (int j = 0; j < grid2DSOS.Overlaps.Count; j++)
                        //{
                        //    if (!dh4.Overlaps.Contains(grid2DSOS.Overlaps[j]))
                        //        break;
                        //}

                        //for (int j = 0; j < dh.Overlaps.Count; j++)
                        //{
                        //    if (!dh.Overlaps[j].EntryA.BoundingBox.Intersects(dh.Overlaps[j].EntryB.BoundingBox))
                        //        Debug.WriteLine("Break.");
                        //}

                        //for (int j = 0; j < sap1d.Overlaps.Count; j++)
                        //{
                        //    if (!sap1d.Overlaps[j].EntryA.BoundingBox.Intersects(sap1d.Overlaps[j].EntryB.BoundingBox))
                        //        Debug.WriteLine("Break.");
                        //}

                        //for (int j = 0; j < grid2DSOS.Overlaps.Count; j++)
                        //{
                        //    if (!grid2DSOS.Overlaps[j].EntryA.BoundingBox.Intersects(grid2DSOS.Overlaps[j].EntryB.BoundingBox))
                        //        Debug.WriteLine("Break.");
                        //}

                        //MoveEntities(entities);
                    }
                    break;
                #endregion
                #region Ray cast timing
                case Test.RayCast:
                    float rayLength = 100;
                    RawList<Ray> rays = new RawList<Ray>();
                    for (int i = 0; i < numRuns; i++)
                    {
                        rays.Add(new Ray()
                        {
                            Position = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X),
                                               (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y),
                                               (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z)),
                            Direction = Vector3.Normalize(new Vector3((float)(rand.NextDouble() - .5), (float)(rand.NextDouble() - .5), (float)(rand.NextDouble() - .5)))
                        });
                    }
                    RawList<BroadPhaseEntry> outputIntersections = new RawList<BroadPhaseEntry>();

                    ////DH
                    //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    //for (int i = 0; i < numRuns; i++)
                    //{
                    //    dhOld.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections);
                    //    outputIntersections.Clear();

                    //}
                    //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    //DHOldTime = endTime - startTime;

                    //DH4
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    for (int i = 0; i < numRuns; i++)
                    {
                        dh.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections);
                        outputIntersections.Clear();
                    }

                    endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    DHtime = endTime - startTime;

                    //Grid2DSAS
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    for (int i = 0; i < numRuns; i++)
                    {
                        grid2DSAS.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections);
                        outputIntersections.Clear();
                    }
                    endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    grid2DSAStime = endTime - startTime;
                    break;
                #endregion
                #region Bounding box query timing
                case Test.BoundingBoxQuery:
                    float boundingBoxSize = 10;
                    var boundingBoxes = new RawList<BoundingBox>();
                    Vector3 offset = new Vector3(boundingBoxSize / 2, boundingBoxSize / 2, boundingBoxSize / 2);
                    for (int i = 0; i < numRuns; i++)
                    {
                        Vector3 center = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X),
                                                     (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y),
                                                     (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z));
                        boundingBoxes.Add(new BoundingBox()
                        {
                            Min = center - offset,
                            Max = center + offset
                        });
                    }

                    outputIntersections = new RawList<BroadPhaseEntry>();

                    ////DH
                    //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    //for (int i = 0; i < numRuns; i++)
                    //{
                    //    dhOld.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections);
                    //    outputIntersections.Clear();

                    //}
                    //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    //DHOldTime = endTime - startTime;

                    //DH4
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    for (int i = 0; i < numRuns; i++)
                    {
                        dh.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections);
                        outputIntersections.Clear();
                    }

                    endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    DHtime = endTime - startTime;

                    //Grid2DSAS
                    startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    for (int i = 0; i < numRuns; i++)
                    {
                        grid2DSAS.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections);
                        outputIntersections.Clear();
                    }
                    endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                    grid2DSAStime = endTime - startTime;
                    break;
                #endregion
            }

            DHOldTime /= numRuns;
            DH2time /= numRuns;
            DH3time /= numRuns;
            DHtime /= numRuns;
            SAS1Dtime /= numRuns;
            grid2DSAStime /= numRuns;
        }
 internal DynamicHierarchyQueryAccelerator(DynamicHierarchy hierarchy)
 {
     this.hierarchy = hierarchy;
 }
Example #13
0
        ///<summary>
        /// Constructs a new space for things to live in.
        ///</summary>
        public Space()
        {
            NarrowPhaseHelper.CollisionManagers = NarrowPhaseHelper.CollisionManagers; //Forces the NarrowPhaseHelper to run the static constructor.  Better to do it now instead of mid-simulation.

            timeStepSettings = new TimeStepSettings();

#if !WINDOWS
            threadManager = new SpecializedThreadManager();
#else
            threadManager = new SpecializedThreadManager();
#endif

            SpaceObjectBuffer = new SpaceObjectBuffer(this);
            EntityStateWriteBuffer = new EntityStateWriteBuffer();
            DeactivationManager = new DeactivationManager(TimeStepSettings, ThreadManager);
            ForceUpdater = new ForceUpdater(TimeStepSettings, ThreadManager);
            BoundingBoxUpdater = new BoundingBoxUpdater(TimeStepSettings, ThreadManager);
            BroadPhase = new DynamicHierarchy(ThreadManager);
            NarrowPhase = new NarrowPhase(TimeStepSettings, BroadPhase.Overlaps, ThreadManager);
            Solver = new Solver(TimeStepSettings, DeactivationManager, ThreadManager);
            NarrowPhase.Solver = Solver;
            PositionUpdater = new ContinuousPositionUpdater(TimeStepSettings, ThreadManager);
            BufferedStates = new BufferedStatesManager(ThreadManager);
            DeferredEventDispatcher = new DeferredEventDispatcher();

            DuringForcesUpdateables = new DuringForcesUpdateableManager(timeStepSettings, ThreadManager);
            BeforeNarrowPhaseUpdateables = new BeforeNarrowPhaseUpdateableManager(timeStepSettings, ThreadManager);
            BeforeSolverUpdateables = new BeforeSolverUpdateableManager(timeStepSettings, ThreadManager);
            BeforePositionUpdateUpdateables = new BeforePositionUpdateUpdateableManager(timeStepSettings, ThreadManager);
            EndOfTimeStepUpdateables = new EndOfTimeStepUpdateableManager(timeStepSettings, ThreadManager);
            EndOfFrameUpdateables = new EndOfFrameUpdateableManager(timeStepSettings, ThreadManager);

        }
Example #14
0
        public static TestResults TestDH(TestCollidableBEPU[] leaves, BEPUutilities.BoundingBox[] queries, ref BoundingBox positionBounds,
            int queryCount, int selfTestCount, int refitCount, int frameCount, float dt, IParallelLooper looper)
        {
            GC.Collect();
            {

                DynamicHierarchy tree = new DynamicHierarchy(looper);
                for (int i = 0; i < leaves.Length; ++i)
                {
                    tree.Add(leaves[i]);
                }

                if (looper.ThreadCount > 1)
                    tree.MultithreadedRefitPhase(tree.GetSplitDepth());
                else
                    tree.SingleThreadedRefitPhase();

                tree.Overlaps.Count = 0;
                if (looper.ThreadCount > 1)
                    tree.MultithreadedOverlapPhase(tree.GetSplitDepth());
                else
                    tree.SingleThreadedOverlapPhase();

                for (int i = 0; i < leaves.Length; ++i)
                {
                    tree.Remove(leaves[i]);
                }

            }
            GC.Collect();

            {

                var startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                DynamicHierarchy tree = new DynamicHierarchy(looper);
                for (int i = 0; i < leaves.Length; ++i)
                {
                    tree.Add(leaves[i]);
                }

                var endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"DH Build Time: {endTime - startTime}");
                Console.WriteLine($"Cost metric: {tree.MeasureCostMetric()}");

                //tree.SingleThreadedRefitPhase();
                //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                //for (int i = 0; i < refitCount; ++i)
                //{
                //    tree.SingleThreadedRefitPhase();
                //    //Console.WriteLine($"Cost metric: {tree.MeasureCostMetric()}");
                //}
                //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                //Console.WriteLine($"DH Refit Time: {endTime - startTime}");
                //Console.WriteLine($"Cost metric: {tree.MeasureCostMetric()}");

                //tree.SingleThreadedOverlapPhase();
                //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                //for (int i = 0; i < selfTestCount; ++i)
                //{
                //    tree.Overlaps.Clear();
                //    tree.SingleThreadedOverlapPhase();
                //}
                //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                //Console.WriteLine($"DH selftest Time: {endTime - startTime}, overlaps: {tree.Overlaps.Count}");

                //**************** Dynamic Testing
                Random random = new Random(5);
                TestResults results = new TestResults("Old", frameCount);

                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int t = 0; t < frameCount; ++t)
                {
                    //Update the positions of objects.
                    for (int i = 0; i < leaves.Length; ++i)
                    {
                        var leaf = leaves[i];

                        //Bounce off the walls.
                        if (leaf.Position.X < positionBounds.Min.X && leaf.Velocity.X < 0)
                            leaf.Velocity.X = -leaf.Velocity.X;
                        if (leaf.Position.Y < positionBounds.Min.Y && leaf.Velocity.Y < 0)
                            leaf.Velocity.Y = -leaf.Velocity.Y;
                        if (leaf.Position.Z < positionBounds.Min.Z && leaf.Velocity.Z < 0)
                            leaf.Velocity.Z = -leaf.Velocity.Z;

                        if (leaf.Position.X > positionBounds.Max.X && leaf.Velocity.X > 0)
                            leaf.Velocity.X = -leaf.Velocity.X;
                        if (leaf.Position.Y > positionBounds.Max.Y && leaf.Velocity.Y > 0)
                            leaf.Velocity.Y = -leaf.Velocity.Y;
                        if (leaf.Position.Z > positionBounds.Max.Z && leaf.Velocity.Z > 0)
                            leaf.Velocity.Z = -leaf.Velocity.Z;

                        leaf.Position += leaf.Velocity * dt;
                        leaf.UpdateBoundingBox();
                    }
                    var refineStartTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;

                    if (looper.ThreadCount > 1)
                        tree.MultithreadedRefitPhase(tree.GetSplitDepth());
                    else
                        tree.SingleThreadedRefitPhase();

                    //tree.Refit();
                    //for (int i = 0; i < 1; ++i)
                    //{

                    //    subtreeReferences.Count = 0;
                    //    treeletInternalNodes.Count = 0;
                    //    tree.BinnedRefine(0, ref subtreeReferences, maximumSubtrees, ref treeletInternalNodes, ref spareNodes, ref resources, out nodesInvalidated);
                    //}
                    //tree.RemoveUnusedInternalNodes(ref spareNodes);

                    var refineEndTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;

                    tree.Overlaps.Count = 0;
                    if (looper.ThreadCount > 1)
                        tree.MultithreadedOverlapPhase(tree.GetSplitDepth());
                    else
                        tree.SingleThreadedOverlapPhase();

                    var testEndTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;

                    results.Refine[t] = 1000 * (refineEndTime - refineStartTime);
                    results.SelfTest[t] = 1000 * (testEndTime - refineEndTime);
                    results.Total[t] = 1000 * (testEndTime - refineStartTime);
                    results.OverlapCounts[t] = tree.Overlaps.Count;
                    results.TreeCosts[t] = tree.MeasureCostMetric();

                    if (t % 16 == 0)
                    {
                        Console.WriteLine($"_________________{t}_________________");
                        Console.WriteLine($"Refine time:      {results.Refine[t]}");
                        Console.WriteLine($"Test time:        {results.SelfTest[t]}");
                        Console.WriteLine($"TIME:             {results.Total[t]}");
                        Console.WriteLine($"Cost metric:      {results.TreeCosts[t]}");
                        Console.WriteLine($"Overlaps:         {results.OverlapCounts[t]}");
                        GC.Collect();
                    }
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"Cost metric: {tree.MeasureCostMetric()}");

                tree.Overlaps.Clear();
                tree.SingleThreadedOverlapPhase();
                startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                for (int i = 0; i < selfTestCount; ++i)
                {
                    tree.Overlaps.Clear();
                    tree.SingleThreadedOverlapPhase();
                }
                endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
                Console.WriteLine($"DH selftest Time2: {endTime - startTime}, overlaps: {tree.Overlaps.Count}");

                return results;
            }
        }