diff --git a/BepuPhysics/Trees/Tree_RayCast.cs b/BepuPhysics/Trees/Tree_RayCast.cs index ce886bef..12167e7e 100644 --- a/BepuPhysics/Trees/Tree_RayCast.cs +++ b/BepuPhysics/Trees/Tree_RayCast.cs @@ -27,7 +27,7 @@ public unsafe static bool Intersects(Vector3 min, Vector3 max, TreeRay* ray, out internal readonly unsafe void RayCast(int nodeIndex, TreeRay* treeRay, RayData* rayData, Buffer stack, BufferPool pool, ref TLeafTester leafTester) where TLeafTester : IRayLeafTester { Debug.Assert((nodeIndex >= 0 && nodeIndex < NodeCount) || (Encode(nodeIndex) >= 0 && Encode(nodeIndex) < LeafCount)); - Debug.Assert(LeafCount >= 2, "This implementation assumes all nodes are filled."); + Debug.Assert(LeafCount >= 2 || nodeIndex < 0, "The node traversal assumes all nodes are filled; a single-leaf tree can only be entered through its encoded leaf index."); int stackEnd = 0; while (true) @@ -55,14 +55,14 @@ internal readonly unsafe void RayCast(int nodeIndex, TreeRay* treeR //Visit the earlier AABB intersection first. if (stackEnd == stack.Length) { - if (stack.Length == TraversalStackCapacity) - { - // First allocation is on the stack. - pool.TakeAtLeast(TraversalStackCapacity * 2, out var newStack); - stack.CopyTo(0, newStack, 0, TraversalStackCapacity); - stack = newStack; + if (stack.Length == TraversalStackCapacity) + { + // First allocation is on the stack. + pool.TakeAtLeast(TraversalStackCapacity * 2, out var newStack); + stack.CopyTo(0, newStack, 0, TraversalStackCapacity); + stack = newStack; } - else + else pool.Resize(ref stack, stackEnd * 2, stackEnd); } if (tA < tB) diff --git a/BepuPhysics/Trees/Tree_Sweep.cs b/BepuPhysics/Trees/Tree_Sweep.cs index a6e2bb5b..c4eec09a 100644 --- a/BepuPhysics/Trees/Tree_Sweep.cs +++ b/BepuPhysics/Trees/Tree_Sweep.cs @@ -15,7 +15,7 @@ partial struct Tree readonly unsafe void Sweep(int nodeIndex, Vector3 expansion, Vector3 origin, Vector3 direction, TreeRay* treeRay, Buffer stack, BufferPool pool, ref TLeafTester leafTester) where TLeafTester : ISweepLeafTester { Debug.Assert((nodeIndex >= 0 && nodeIndex < NodeCount) || (Encode(nodeIndex) >= 0 && Encode(nodeIndex) < LeafCount)); - Debug.Assert(LeafCount >= 2, "This implementation assumes all nodes are filled."); + Debug.Assert(LeafCount >= 2 || nodeIndex < 0, "The node traversal assumes all nodes are filled; a single-leaf tree can only be entered through its encoded leaf index."); int stackEnd = 0; while (true) @@ -47,14 +47,14 @@ readonly unsafe void Sweep(int nodeIndex, Vector3 expansion, Vector //Visit the earlier AABB intersection first. if (stackEnd == stack.Length) { - if (stack.Length == TraversalStackCapacity) - { - // First allocation is on the stack. - pool.TakeAtLeast(TraversalStackCapacity * 2, out var newStack); - stack.CopyTo(0, newStack, 0, TraversalStackCapacity); - stack = newStack; + if (stack.Length == TraversalStackCapacity) + { + // First allocation is on the stack. + pool.TakeAtLeast(TraversalStackCapacity * 2, out var newStack); + stack.CopyTo(0, newStack, 0, TraversalStackCapacity); + stack = newStack; } - else + else pool.Resize(ref stack, stackEnd * 2, stackEnd); } if (tA < tB) diff --git a/BepuPhysics/Trees/Tree_VolumeQuery.cs b/BepuPhysics/Trees/Tree_VolumeQuery.cs index 6956ba60..e9e2c17c 100644 --- a/BepuPhysics/Trees/Tree_VolumeQuery.cs +++ b/BepuPhysics/Trees/Tree_VolumeQuery.cs @@ -11,7 +11,7 @@ partial struct Tree unsafe readonly void GetOverlaps(int nodeIndex, BoundingBox boundingBox, Buffer stack, BufferPool pool, ref TEnumerator leafEnumerator) where TEnumerator : IBreakableForEach { Debug.Assert((nodeIndex >= 0 && nodeIndex < NodeCount) || (Encode(nodeIndex) >= 0 && Encode(nodeIndex) < LeafCount)); - Debug.Assert(LeafCount >= 2, "This implementation assumes all nodes are filled."); + Debug.Assert(LeafCount >= 2 || nodeIndex < 0, "The node traversal assumes all nodes are filled; a single-leaf tree can only be entered through its encoded leaf index."); int stackEnd = 0; while (true) @@ -38,17 +38,17 @@ unsafe readonly void GetOverlaps(int nodeIndex, BoundingBox boundin nodeIndex = node.A.Index; if (bIntersected) { - if (stackEnd == stack.Length) - { - if (stack.Length == TraversalStackCapacity) - { - // First allocation is on the stack. - pool.TakeAtLeast(TraversalStackCapacity * 2, out var newStack); - stack.CopyTo(0, newStack, 0, TraversalStackCapacity); - stack = newStack; + if (stackEnd == stack.Length) + { + if (stack.Length == TraversalStackCapacity) + { + // First allocation is on the stack. + pool.TakeAtLeast(TraversalStackCapacity * 2, out var newStack); + stack.CopyTo(0, newStack, 0, TraversalStackCapacity); + stack = newStack; } - else - pool.Resize(ref stack, stackEnd * 2, stackEnd); + else + pool.Resize(ref stack, stackEnd * 2, stackEnd); } stack[stackEnd++] = node.B.Index; @@ -67,22 +67,22 @@ unsafe readonly void GetOverlaps(int nodeIndex, BoundingBox boundin } } } - if (stack.Length > TraversalStackCapacity) - { - // We rented a larger stack at some point. Return it. - pool.Return(ref stack); + if (stack.Length > TraversalStackCapacity) + { + // We rented a larger stack at some point. Return it. + pool.Return(ref stack); } } - /// - /// Finds and processes all leaves with bounding boxes that overlap the specified axis-aligned bounding box. The is invoked - /// for each overlapping element. - /// - /// The type of the enumerator used to process the overlapping elements. - /// Query to test against the bounding volume hierarchy. + /// + /// Finds and processes all leaves with bounding boxes that overlap the specified axis-aligned bounding box. The is invoked + /// for each overlapping element. + /// + /// The type of the enumerator used to process the overlapping elements. + /// Query to test against the bounding volume hierarchy. /// The buffer pool used for temporary allocations during the operation. Only used if the tree is pathologically deep; stack memory is used preferentially. - /// A reference to the enumerator that processes the indices of overlapping elements. The enumerator can - /// terminate early by returning from its iteration. + /// A reference to the enumerator that processes the indices of overlapping elements. The enumerator can + /// terminate early by returning from its iteration. public readonly unsafe void GetOverlaps(BoundingBox boundingBox, BufferPool pool, ref TEnumerator leafEnumerator) where TEnumerator : IBreakableForEach { if (LeafCount > 1) @@ -102,16 +102,16 @@ public readonly unsafe void GetOverlaps(BoundingBox boundingBox, Bu //If the leaf count is zero, then there's nothing to test against. } - /// - /// Finds and processes all leaves with bounding boxes that overlap the specified axis-aligned bounding box. The is invoked - /// for each overlapping element. - /// - /// The type of the enumerator used to process the overlapping elements. - /// The minimum corner of the axis-aligned bounding box. - /// The maximum corner of the axis-aligned bounding box. + /// + /// Finds and processes all leaves with bounding boxes that overlap the specified axis-aligned bounding box. The is invoked + /// for each overlapping element. + /// + /// The type of the enumerator used to process the overlapping elements. + /// The minimum corner of the axis-aligned bounding box. + /// The maximum corner of the axis-aligned bounding box. /// The buffer pool used for temporary allocations during the operation. Only used if the tree is pathologically deep; stack memory is used preferentially. - /// A reference to the enumerator that processes the indices of overlapping elements. The enumerator can - /// terminate early by returning from its iteration. + /// A reference to the enumerator that processes the indices of overlapping elements. The enumerator can + /// terminate early by returning from its iteration. public readonly void GetOverlaps(Vector3 min, Vector3 max, BufferPool pool, ref TEnumerator leafEnumerator) where TEnumerator : IBreakableForEach { GetOverlaps(new BoundingBox(min, max), pool, ref leafEnumerator);