///<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); }
///<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); }
/// <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)); BEPUutilities.BoundingBox box = new BEPUutilities.BoundingBox(new BEPUutilities.Vector3(-500, -500, -500), new BEPUutilities.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++) { BEPUutilities.Vector3 position = new BEPUutilities.Vector3((Fix64)rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X, (Fix64)rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y, (Fix64)rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z); toAdd = new Box(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; }
/// <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.ThreadManager); SortAndSweep1D sas1d = new SortAndSweep1D(Space.ThreadManager); Grid2DSortAndSweep grid2DSAS = new Grid2DSortAndSweep(Space.ThreadManager); //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; }
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((Fix64)rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X, (Fix64)rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y, (Fix64)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: Fix64 rayLength = 100; RawList <Ray> rays = new RawList <Ray>(); for (int i = 0; i < numRuns; i++) { rays.Add(new Ray() { Position = new Vector3((Fix64)rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X, (Fix64)rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y, (Fix64)rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z), Direction = Vector3.Normalize(new Vector3((Fix64)(rand.NextDouble() - .5), (Fix64)(rand.NextDouble() - .5), (Fix64)(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: Fix64 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((Fix64)rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X, (Fix64)rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y, (Fix64)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); }
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); } }