public void BuildTree([Values(2, 10, 100, 1000)] int elementCount) { int numNodes = elementCount / 3 * 2 + 4; var points = new NativeArray <PointAndIndex>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var aabbs = new NativeArray <Aabb>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var filters = new NativeArray <CollisionFilter>(elementCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); InitInputArrays(points, aabbs, filters); var nodes = new NativeArray <Node>(numNodes, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var bvh = new BoundingVolumeHierarchy(nodes); bvh.Build(points, aabbs, out int numNodesOut); bvh.CheckIntegrity(); points.Dispose(); filters.Dispose(); aabbs.Dispose(); nodes.Dispose(); }
public unsafe void BuildTreeAndOverlap([Values(2, 10, 33, 100)] int elementCount) { elementCount *= 2; int numNodes = elementCount / 3 * 2 + 4; var points = new NativeArray <PointAndIndex>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var aabbs = new NativeArray <Aabb>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var filters = new NativeArray <CollisionFilter>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var respondsToCollision = new NativeArray <bool>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); InitInputWithCopyArrays(points, aabbs, filters, respondsToCollision); var nodes = new NativeArray <Node>(numNodes, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var bvh = new BoundingVolumeHierarchy(nodes); bvh.Build(points, aabbs, out int numNodesOut); bvh.CheckIntegrity(); var buffer = new PairBuffer { Pairs = new List <BodyIndexPair>() }; buffer.MaxId = elementCount - 1; Node *nodesPtr = (Node *)nodes.GetUnsafePtr(); BoundingVolumeHierarchy.TreeOverlap(ref buffer, nodesPtr, nodesPtr); int numCollidingPairs = buffer.Pairs.Count; //Debug.Log($"Num colliding pairs: {buffer.Pairs.Count}"); Assert.AreEqual(elementCount / 2, numCollidingPairs); filters.Dispose(); respondsToCollision.Dispose(); points.Dispose(); aabbs.Dispose(); nodes.Dispose(); }
public unsafe void BuildTreeAndOverlap([Values(2, 10, 33, 100)] int elementCount) { elementCount *= 2; int numNodes = elementCount / 3 * 2 + 4; var points = new NativeArray <BoundingVolumeHierarchy.PointAndIndex>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var aabbs = new NativeArray <Aabb>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var filters = new NativeArray <CollisionFilter>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); InitializeInputWithCopyArrays(points, aabbs, filters); var nodes = new NativeArray <BoundingVolumeHierarchy.Node>(numNodes, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var bvh = new BoundingVolumeHierarchy(nodes); bvh.Build(points, aabbs, out int numNodesOut); bvh.CheckIntegrity(); var buffer = new PairBuffer { Pairs = new NativeList <PhysicsBody.IndexPair>(0, Allocator.Temp) }; buffer.MaxId = elementCount - 1; BoundingVolumeHierarchy.Node *nodesPtr = (BoundingVolumeHierarchy.Node *)nodes.GetUnsafePtr(); BoundingVolumeHierarchy.TreeOverlap(ref buffer, nodesPtr, nodesPtr); int numCollidingPairs = buffer.Pairs.Length; Assert.AreEqual(elementCount / 2, numCollidingPairs); buffer.Dispose(); filters.Dispose(); points.Dispose(); aabbs.Dispose(); nodes.Dispose(); }
public void TreeOverlapPerfTest(int elementCount, bool newOverlap) { // Execute dummy job just to get Burst compilation out of the way. { var dummyBlockStream = new BlockStream(1, 0, Allocator.TempJob); var dummyNodes = new NativeArray <Node>(0, Allocator.TempJob); var dummyFilters = new NativeArray <CollisionFilter>(0, Allocator.TempJob); new TestTreeOverlapJob { CollisionPairWriter = dummyBlockStream, Nodes = dummyNodes, Filter = dummyFilters, NumObjects = 0, DummyRun = true }.Run(); dummyBlockStream.Dispose(); dummyNodes.Dispose(); dummyFilters.Dispose(); } elementCount *= 2; int numNodes = elementCount / 3 * 2 + 4; var points = new NativeArray <PointAndIndex>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var aabbs = new NativeArray <Aabb>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var filters = new NativeArray <CollisionFilter>(elementCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); // Override filter data with default filters. for (int i = 0; i < filters.Length; i++) { filters[i] = CollisionFilter.Default; } InitInputWithCopyArrays(points, aabbs, filters); var nodes = new NativeArray <Node>(numNodes, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var bvh = new BoundingVolumeHierarchy(nodes); bvh.Build(points, aabbs, out int numNodesOut); bvh.CheckIntegrity(); var collisionPairs = new BlockStream(1, 0xd586fc6e); var job = new TestTreeOverlapJob { Nodes = nodes, Filter = filters, NumObjects = elementCount, CollisionPairWriter = collisionPairs, DummyRun = false }; Measure.Method(() => { job.Run(); }).Definition(sampleUnit: SampleUnit.Millisecond) .MeasurementCount(1) .Run(); points.Dispose(); aabbs.Dispose(); nodes.Dispose(); collisionPairs.Dispose(); filters.Dispose(); }
public unsafe void OverlapTaskFilteringTest([Values(2, 10, 33, 100)] int elementCount) { elementCount *= 2; int numNodes = elementCount + Constants.MaxNumTreeBranches; var points = new NativeArray <PointAndIndex>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var aabbs = new NativeArray <Aabb>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var bodyFilters = new NativeArray <CollisionFilter>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); InitInputWithCopyArrays(points, aabbs, bodyFilters); var nodes = new NativeArray <Node>(numNodes, Allocator.Temp, NativeArrayOptions.UninitializedMemory); Node *nodesPtr = (Node *)nodes.GetUnsafePtr(); var seenUnfiltered = new HashSet <BodyIndexPair>(); { var bvhUnfiltered = new BoundingVolumeHierarchy(nodes); bvhUnfiltered.Build(points, aabbs, out int numNodesOut); bvhUnfiltered.CheckIntegrity(); EverythingWriter pairWriter = new EverythingWriter { SeenPairs = seenUnfiltered }; BoundingVolumeHierarchy.TreeOverlap(ref pairWriter, nodesPtr, nodesPtr); } var nodeFilters = new NativeArray <CollisionFilter>(numNodes, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var bvhFiltered = new BoundingVolumeHierarchy(nodes, nodeFilters); int numNodesFilteredTree; bvhFiltered.Build(points, aabbs, out numNodesFilteredTree); bvhFiltered.BuildCombinedCollisionFilter(bodyFilters, 0, numNodesFilteredTree - 1); var filteredCollisionPairs = new BlockStream(1, 0xec87b613); BlockStream.Writer filteredPairWriter = filteredCollisionPairs; filteredPairWriter.BeginForEachIndex(0); CollisionFilter *bodyFiltersPtr = (CollisionFilter *)bodyFilters.GetUnsafePtr(); var bufferedPairs = new Broadphase.BodyPairWriter(&filteredPairWriter, bodyFiltersPtr); CollisionFilter *nodeFiltersPtr = (CollisionFilter *)nodeFilters.GetUnsafePtr(); BoundingVolumeHierarchy.TreeOverlap(ref bufferedPairs, nodesPtr, nodesPtr, nodeFiltersPtr, nodeFiltersPtr); bufferedPairs.Close(); filteredPairWriter.EndForEachIndex(); BlockStream.Reader filteredPairReader = filteredCollisionPairs; filteredPairReader.BeginForEachIndex(0); // Check that every pair in our filtered set also appears in the unfiltered set while (filteredPairReader.RemainingItemCount > 0) { var pair = filteredPairReader.Read <BodyIndexPair>(); Assert.IsTrue(seenUnfiltered.Contains(pair)); seenUnfiltered.Remove(pair); // Remove the pair } // Pairs were removed, so the only remaining ones should be filtered foreach (BodyIndexPair pair in seenUnfiltered) { bool shouldCollide = CollisionFilter.IsCollisionEnabled(bodyFilters[pair.BodyAIndex], bodyFilters[pair.BodyBIndex]); Assert.IsFalse(shouldCollide); } nodeFilters.Dispose(); nodes.Dispose(); bodyFilters.Dispose(); aabbs.Dispose(); points.Dispose(); filteredCollisionPairs.Dispose(); }