Skip to content

Commit bea387e

Browse files
committed
Node-level traversals now permit being invoked on a nodeIndex corresponding to a leaf.
1 parent 3bd72d2 commit bea387e

3 files changed

Lines changed: 48 additions & 48 deletions

File tree

‎BepuPhysics/Trees/Tree_RayCast.cs‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public unsafe static bool Intersects(Vector3 min, Vector3 max, TreeRay* ray, out
2727
internal readonly unsafe void RayCast<TLeafTester>(int nodeIndex, TreeRay* treeRay, RayData* rayData, Buffer<int> stack, BufferPool pool, ref TLeafTester leafTester) where TLeafTester : IRayLeafTester
2828
{
2929
Debug.Assert((nodeIndex >= 0 && nodeIndex < NodeCount) || (Encode(nodeIndex) >= 0 && Encode(nodeIndex) < LeafCount));
30-
Debug.Assert(LeafCount >= 2, "This implementation assumes all nodes are filled.");
30+
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.");
3131

3232
int stackEnd = 0;
3333
while (true)
@@ -55,14 +55,14 @@ internal readonly unsafe void RayCast<TLeafTester>(int nodeIndex, TreeRay* treeR
5555
//Visit the earlier AABB intersection first.
5656
if (stackEnd == stack.Length)
5757
{
58-
if (stack.Length == TraversalStackCapacity)
59-
{
60-
// First allocation is on the stack.
61-
pool.TakeAtLeast<int>(TraversalStackCapacity * 2, out var newStack);
62-
stack.CopyTo(0, newStack, 0, TraversalStackCapacity);
63-
stack = newStack;
58+
if (stack.Length == TraversalStackCapacity)
59+
{
60+
// First allocation is on the stack.
61+
pool.TakeAtLeast<int>(TraversalStackCapacity * 2, out var newStack);
62+
stack.CopyTo(0, newStack, 0, TraversalStackCapacity);
63+
stack = newStack;
6464
}
65-
else
65+
else
6666
pool.Resize(ref stack, stackEnd * 2, stackEnd);
6767
}
6868
if (tA < tB)

‎BepuPhysics/Trees/Tree_Sweep.cs‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ partial struct Tree
1515
readonly unsafe void Sweep<TLeafTester>(int nodeIndex, Vector3 expansion, Vector3 origin, Vector3 direction, TreeRay* treeRay, Buffer<int> stack, BufferPool pool, ref TLeafTester leafTester) where TLeafTester : ISweepLeafTester
1616
{
1717
Debug.Assert((nodeIndex >= 0 && nodeIndex < NodeCount) || (Encode(nodeIndex) >= 0 && Encode(nodeIndex) < LeafCount));
18-
Debug.Assert(LeafCount >= 2, "This implementation assumes all nodes are filled.");
18+
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.");
1919

2020
int stackEnd = 0;
2121
while (true)
@@ -47,14 +47,14 @@ readonly unsafe void Sweep<TLeafTester>(int nodeIndex, Vector3 expansion, Vector
4747
//Visit the earlier AABB intersection first.
4848
if (stackEnd == stack.Length)
4949
{
50-
if (stack.Length == TraversalStackCapacity)
51-
{
52-
// First allocation is on the stack.
53-
pool.TakeAtLeast<int>(TraversalStackCapacity * 2, out var newStack);
54-
stack.CopyTo(0, newStack, 0, TraversalStackCapacity);
55-
stack = newStack;
50+
if (stack.Length == TraversalStackCapacity)
51+
{
52+
// First allocation is on the stack.
53+
pool.TakeAtLeast<int>(TraversalStackCapacity * 2, out var newStack);
54+
stack.CopyTo(0, newStack, 0, TraversalStackCapacity);
55+
stack = newStack;
5656
}
57-
else
57+
else
5858
pool.Resize(ref stack, stackEnd * 2, stackEnd);
5959
}
6060
if (tA < tB)

‎BepuPhysics/Trees/Tree_VolumeQuery.cs‎

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ partial struct Tree
1111
unsafe readonly void GetOverlaps<TEnumerator>(int nodeIndex, BoundingBox boundingBox, Buffer<int> stack, BufferPool pool, ref TEnumerator leafEnumerator) where TEnumerator : IBreakableForEach<int>
1212
{
1313
Debug.Assert((nodeIndex >= 0 && nodeIndex < NodeCount) || (Encode(nodeIndex) >= 0 && Encode(nodeIndex) < LeafCount));
14-
Debug.Assert(LeafCount >= 2, "This implementation assumes all nodes are filled.");
14+
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.");
1515

1616
int stackEnd = 0;
1717
while (true)
@@ -38,17 +38,17 @@ unsafe readonly void GetOverlaps<TEnumerator>(int nodeIndex, BoundingBox boundin
3838
nodeIndex = node.A.Index;
3939
if (bIntersected)
4040
{
41-
if (stackEnd == stack.Length)
42-
{
43-
if (stack.Length == TraversalStackCapacity)
44-
{
45-
// First allocation is on the stack.
46-
pool.TakeAtLeast<int>(TraversalStackCapacity * 2, out var newStack);
47-
stack.CopyTo(0, newStack, 0, TraversalStackCapacity);
48-
stack = newStack;
41+
if (stackEnd == stack.Length)
42+
{
43+
if (stack.Length == TraversalStackCapacity)
44+
{
45+
// First allocation is on the stack.
46+
pool.TakeAtLeast<int>(TraversalStackCapacity * 2, out var newStack);
47+
stack.CopyTo(0, newStack, 0, TraversalStackCapacity);
48+
stack = newStack;
4949
}
50-
else
51-
pool.Resize(ref stack, stackEnd * 2, stackEnd);
50+
else
51+
pool.Resize(ref stack, stackEnd * 2, stackEnd);
5252
}
5353
stack[stackEnd++] = node.B.Index;
5454

@@ -67,22 +67,22 @@ unsafe readonly void GetOverlaps<TEnumerator>(int nodeIndex, BoundingBox boundin
6767
}
6868
}
6969
}
70-
if (stack.Length > TraversalStackCapacity)
71-
{
72-
// We rented a larger stack at some point. Return it.
73-
pool.Return(ref stack);
70+
if (stack.Length > TraversalStackCapacity)
71+
{
72+
// We rented a larger stack at some point. Return it.
73+
pool.Return(ref stack);
7474
}
7575
}
7676

77-
/// <summary>
78-
/// Finds and processes all leaves with bounding boxes that overlap the specified axis-aligned bounding box. The <paramref name="leafEnumerator"/> is invoked
79-
/// for each overlapping element.
80-
/// </summary>
81-
/// <typeparam name="TEnumerator">The type of the <see cref="IBreakableForEach{T}"/> enumerator used to process the overlapping elements.</typeparam>
82-
/// <param name="boundingBox">Query to test against the bounding volume hierarchy.</param>
77+
/// <summary>
78+
/// Finds and processes all leaves with bounding boxes that overlap the specified axis-aligned bounding box. The <paramref name="leafEnumerator"/> is invoked
79+
/// for each overlapping element.
80+
/// </summary>
81+
/// <typeparam name="TEnumerator">The type of the <see cref="IBreakableForEach{T}"/> enumerator used to process the overlapping elements.</typeparam>
82+
/// <param name="boundingBox">Query to test against the bounding volume hierarchy.</param>
8383
/// <param name="pool">The buffer pool used for temporary allocations during the operation. Only used if the tree is pathologically deep; stack memory is used preferentially.</param>
84-
/// <param name="leafEnumerator">A reference to the enumerator that processes the indices of overlapping elements. The enumerator can
85-
/// terminate early by returning <see langword="false"/> from its iteration.</param>
84+
/// <param name="leafEnumerator">A reference to the enumerator that processes the indices of overlapping elements. The enumerator can
85+
/// terminate early by returning <see langword="false"/> from its iteration.</param>
8686
public readonly unsafe void GetOverlaps<TEnumerator>(BoundingBox boundingBox, BufferPool pool, ref TEnumerator leafEnumerator) where TEnumerator : IBreakableForEach<int>
8787
{
8888
if (LeafCount > 1)
@@ -102,16 +102,16 @@ public readonly unsafe void GetOverlaps<TEnumerator>(BoundingBox boundingBox, Bu
102102
//If the leaf count is zero, then there's nothing to test against.
103103
}
104104

105-
/// <summary>
106-
/// Finds and processes all leaves with bounding boxes that overlap the specified axis-aligned bounding box. The <paramref name="leafEnumerator"/> is invoked
107-
/// for each overlapping element.
108-
/// </summary>
109-
/// <typeparam name="TEnumerator">The type of the <see cref="IBreakableForEach{T}"/> enumerator used to process the overlapping elements.</typeparam>
110-
/// <param name="min">The minimum corner of the axis-aligned bounding box.</param>
111-
/// <param name="max">The maximum corner of the axis-aligned bounding box.</param>
105+
/// <summary>
106+
/// Finds and processes all leaves with bounding boxes that overlap the specified axis-aligned bounding box. The <paramref name="leafEnumerator"/> is invoked
107+
/// for each overlapping element.
108+
/// </summary>
109+
/// <typeparam name="TEnumerator">The type of the <see cref="IBreakableForEach{T}"/> enumerator used to process the overlapping elements.</typeparam>
110+
/// <param name="min">The minimum corner of the axis-aligned bounding box.</param>
111+
/// <param name="max">The maximum corner of the axis-aligned bounding box.</param>
112112
/// <param name="pool">The buffer pool used for temporary allocations during the operation. Only used if the tree is pathologically deep; stack memory is used preferentially.</param>
113-
/// <param name="leafEnumerator">A reference to the enumerator that processes the indices of overlapping elements. The enumerator can
114-
/// terminate early by returning <see langword="false"/> from its iteration.</param>
113+
/// <param name="leafEnumerator">A reference to the enumerator that processes the indices of overlapping elements. The enumerator can
114+
/// terminate early by returning <see langword="false"/> from its iteration.</param>
115115
public readonly void GetOverlaps<TEnumerator>(Vector3 min, Vector3 max, BufferPool pool, ref TEnumerator leafEnumerator) where TEnumerator : IBreakableForEach<int>
116116
{
117117
GetOverlaps(new BoundingBox(min, max), pool, ref leafEnumerator);

0 commit comments

Comments
 (0)