static TestCollidableBEPU[] GetLeavesBEPU(int width, int height, int length, float size, float gap) { var leaves = new TestCollidableBEPU[width * height * length]; var offset = size + gap; for (int i = 0; i < width; ++i) { for (int j = 0; j < height; ++j) { for (int k = 0; k < length; ++k) { var collidable = new TestCollidableBEPU(); BEPUutilities.BoundingBox boundingBox; boundingBox.Min = new BEPUutilities.Vector3(i * offset, j * offset, k * offset); boundingBox.Max = boundingBox.Min + new BEPUutilities.Vector3(size, size, size); collidable.BoundingBox = boundingBox; leaves[height * length * i + length * j + k] = collidable; } } } return(leaves); }
static TestCollidableBEPU[] GetRandomLeavesBEPU(int leafCount, BoundingBox bounds, Vector3 minimumSize, Vector3 maximumSize, float sizePower, VelocityDescription velocityDescription) { var leaves = new TestCollidableBEPU[leafCount]; Random random = new Random(5); var range = bounds.Max - bounds.Min; var sizeRange = maximumSize - minimumSize; for (int i = 0; i < leafCount; ++i) { var halfLeafSize = 0.5f * (minimumSize + new Vector3((float)Math.Pow(random.NextDouble(), sizePower), (float)Math.Pow(random.NextDouble(), sizePower), (float)Math.Pow(random.NextDouble(), sizePower)) * sizeRange); var position = bounds.Min + new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()) * range; leaves[i] = new TestCollidableBEPU(); leaves[i].Position = new BEPUutilities.Vector3(position.X, position.Y, position.Z); leaves[i].HalfSize = new BEPUutilities.Vector3(halfLeafSize.X, halfLeafSize.Y, halfLeafSize.Z); leaves[i].UpdateBoundingBox(); } for (int i = 0; i < leaves.Length * velocityDescription.PortionOfMovingLeaves; ++i) { var speed = (float)(velocityDescription.MinVelocity + (velocityDescription.MaxVelocity - velocityDescription.MinVelocity) * Math.Pow(random.NextDouble(), velocityDescription.VelocityDistributionPower)); var direction = new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()) * 2 - Vector3.One; var lengthSquared = direction.LengthSquared(); if (lengthSquared < 1e-9f) { direction = new Vector3(0, 1, 0); } else { direction /= (float)Math.Sqrt(lengthSquared); } var velocity = speed * direction; leaves[i].Velocity = new BEPUutilities.Vector3(velocity.X, velocity.Y, velocity.Z); } return leaves; }
static TestCollidableBEPU[] GetRandomLeavesBEPU(int leafCount, BoundingBox bounds, Vector3 minimumSize, Vector3 maximumSize, float sizePower, VelocityDescription velocityDescription) { var leaves = new TestCollidableBEPU[leafCount]; Random random = new Random(5); var range = bounds.Max - bounds.Min; var sizeRange = maximumSize - minimumSize; for (int i = 0; i < leafCount; ++i) { var halfLeafSize = 0.5f * (minimumSize + new Vector3((float)Math.Pow(random.NextDouble(), sizePower), (float)Math.Pow(random.NextDouble(), sizePower), (float)Math.Pow(random.NextDouble(), sizePower)) * sizeRange); var position = bounds.Min + new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()) * range; leaves[i] = new TestCollidableBEPU(); leaves[i].Position = new BEPUutilities.Vector3(position.X, position.Y, position.Z); leaves[i].HalfSize = new BEPUutilities.Vector3(halfLeafSize.X, halfLeafSize.Y, halfLeafSize.Z); leaves[i].UpdateBoundingBox(); } for (int i = 0; i < leaves.Length * velocityDescription.PortionOfMovingLeaves; ++i) { var speed = (float)(velocityDescription.MinVelocity + (velocityDescription.MaxVelocity - velocityDescription.MinVelocity) * Math.Pow(random.NextDouble(), velocityDescription.VelocityDistributionPower)); var direction = new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()) * 2 - Vector3.One; var lengthSquared = direction.LengthSquared(); if (lengthSquared < 1e-9f) { direction = new Vector3(0, 1, 0); } else { direction /= (float)Math.Sqrt(lengthSquared); } var velocity = speed * direction; leaves[i].Velocity = new BEPUutilities.Vector3(velocity.X, velocity.Y, velocity.Z); } return(leaves); }
static TestCollidableBEPU[] GetLeavesBEPU(int width, int height, int length, float size, float gap) { var leaves = new TestCollidableBEPU[width * height * length]; var offset = size + gap; for (int i = 0; i < width; ++i) { for (int j = 0; j < height; ++j) { for (int k = 0; k < length; ++k) { var collidable = new TestCollidableBEPU(); BEPUutilities.BoundingBox boundingBox; boundingBox.Min = new BEPUutilities.Vector3(i * offset, j * offset, k * offset); boundingBox.Max = boundingBox.Min + new BEPUutilities.Vector3(size, size, size); collidable.BoundingBox = boundingBox; leaves[height * length * i + length * j + k] = collidable; } } } return leaves; }
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; } }
public static void TestBEPU(TestCollidableBEPU[] leaves, BEPUutilities.BoundingBox[] queries, int queryCount, int selfTestCount, int refitCount) { GC.Collect(); { var warmLeaves = GetLeavesBEPU(2, 2, 2, 10, 10); BoundingBoxTree<TestCollidableBEPU> tree = new BoundingBoxTree<TestCollidableBEPU>(warmLeaves); Console.WriteLine($"BEPU Cachewarm Build, root AABB: {tree.BoundingBox}"); tree.Refit(); RawList<TestCollidableBEPU> results = new RawList<TestCollidableBEPU>(); BEPUutilities.BoundingBox aabb = new BEPUutilities.BoundingBox { Min = new BEPUutilities.Vector3(0, 0, 0), Max = new BEPUutilities.Vector3(1, 1, 1) }; results.Count = 0; tree.GetOverlaps(aabb, results); var overlaps = new List<TreeOverlapPair<TestCollidableBEPU, TestCollidableBEPU>>(100); for (int i = 0; i < selfTestCount; ++i) { tree.GetOverlaps(tree, overlaps); } } GC.Collect(); { var startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; BoundingBoxTree<TestCollidableBEPU> tree = new BoundingBoxTree<TestCollidableBEPU>(leaves); var endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; Console.WriteLine($"BEPU Build Time: {endTime - startTime}, root AABB: {tree.BoundingBox}"); startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; for (int i = 0; i < refitCount; ++i) { tree.Refit(); } endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; Console.WriteLine($"BEPU Refit Time: {endTime - startTime}"); RawList<TestCollidableBEPU> results = new RawList<TestCollidableBEPU>(); var queryMask = queries.Length - 1; startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; for (int i = 0; i < queryCount; ++i) { results.Count = 0; tree.GetOverlaps(queries[i & queryMask], results); } endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; Console.WriteLine($"BEPU Query Time: {endTime - startTime}, overlaps: {results.Count}"); //var overlaps = new RawList<TreeOverlapPair<TestCollidableBEPU, TestCollidableBEPU>>(280000); //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //for (int i = 0; i < selfTestCount; ++i) //{ // overlaps.Count = 0; // tree.GetOverlaps(tree, overlaps); //} //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //Console.WriteLine($"BEPU SelfTree Time: {endTime - startTime}, overlaps: {overlaps.Count}"); } }