Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions BepuPhysics/Collidables/BigCompound.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public unsafe BigCompound(Buffer<CompoundChild> children, Shapes shapes, BufferP
pool.Return(ref subtrees);
}

public void ComputeBounds(Quaternion orientation, Shapes shapeBatches, out Vector3 min, out Vector3 max)
public readonly void ComputeBounds(Quaternion orientation, Shapes shapeBatches, out Vector3 min, out Vector3 max)
{
Compound.ComputeChildBounds(Children[0], orientation, shapeBatches, out min, out max);
for (int i = 1; i < Children.Length; ++i)
Expand All @@ -125,9 +125,9 @@ public void ComputeBounds(Quaternion orientation, Shapes shapeBatches, out Vecto
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddChildBoundsToBatcher(ref BoundingBoxBatcher batcher, in RigidPose pose, in BodyVelocity velocity, int bodyIndex)
public readonly void AddChildBoundsToBatcher(ref BoundingBoxBatcher batcher, in RigidPose pose, in BodyVelocity velocity, int bodyIndex)
{
Compound.AddChildBoundsToBatcher(ref Children, ref batcher, pose, velocity, bodyIndex);
Compound.AddChildBoundsToBatcher(Children, ref batcher, pose, velocity, bodyIndex);
}

unsafe struct LeafTester<TRayHitHandler> : IRayLeafTester where TRayHitHandler : struct, IShapeRayHitHandler
Expand All @@ -152,15 +152,15 @@ public LeafTester(in Buffer<CompoundChild> children, Shapes shapes, in TRayHitHa


[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TestLeaf(int leafIndex, RayData* rayData, float* maximumT)
public void TestLeaf(int leafIndex, RayData* rayData, float* maximumT, BufferPool pool)
{
if (Handler.AllowTest(leafIndex))
{
ref var child = ref Children[leafIndex];
CompoundChildShapeTester tester;
tester.T = -1;
tester.Normal = default;
Shapes[child.ShapeIndex.Type].RayTest(child.ShapeIndex.Index, child.AsPose(), *rayData, ref *maximumT, ref tester);
Shapes[child.ShapeIndex.Type].RayTest(child.ShapeIndex.Index, child.AsPose(), *rayData, ref *maximumT, pool, ref tester);
if (tester.T >= 0)
{
Debug.Assert(*maximumT >= tester.T, "Whatever generated this ray hit should have obeyed the current maximumT value.");
Expand All @@ -171,18 +171,18 @@ public void TestLeaf(int leafIndex, RayData* rayData, float* maximumT)
}
}

public void RayTest<TRayHitHandler>(in RigidPose pose, in RayData ray, ref float maximumT, Shapes shapes, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler
public readonly void RayTest<TRayHitHandler>(in RigidPose pose, in RayData ray, ref float maximumT, Shapes shapes, BufferPool pool, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler
{
Matrix3x3.CreateFromQuaternion(pose.Orientation, out var orientation);
Matrix3x3.TransformTranspose(ray.Origin - pose.Position, orientation, out var localOrigin);
Matrix3x3.TransformTranspose(ray.Direction, orientation, out var localDirection);
var leafTester = new LeafTester<TRayHitHandler>(Children, shapes, hitHandler, orientation, ray);
Tree.RayCast(localOrigin, localDirection, ref maximumT, ref leafTester);
Tree.RayCast(localOrigin, localDirection, ref maximumT, pool, ref leafTester);
//Copy the hitHandler to preserve any mutation.
hitHandler = leafTester.Handler;
}

public unsafe void RayTest<TRayHitHandler>(in RigidPose pose, ref RaySource rays, Shapes shapes, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler
public readonly unsafe void RayTest<TRayHitHandler>(in RigidPose pose, ref RaySource rays, Shapes shapes, BufferPool pool, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler
{
//TODO: Note that we dispatch a bunch of scalar tests here. You could be more clever than this- batched tests are possible.
//May be worth creating a different traversal designed for low ray counts- might be able to get some benefit out of a semidynamic packet or something.
Expand All @@ -195,7 +195,7 @@ public unsafe void RayTest<TRayHitHandler>(in RigidPose pose, ref RaySource rays
leafTester.OriginalRay = *ray;
Matrix3x3.Transform(ray->Origin - pose.Position, inverseOrientation, out var localOrigin);
Matrix3x3.Transform(ray->Direction, inverseOrientation, out var localDirection);
Tree.RayCast(localOrigin, localDirection, ref *maximumT, ref leafTester);
Tree.RayCast(localOrigin, localDirection, ref *maximumT, pool, ref leafTester);
}
//Preserve any mutations.
hitHandler = leafTester.Handler;
Expand All @@ -207,14 +207,14 @@ public static ShapeBatch CreateShapeBatch(BufferPool pool, int initialCapacity,
return new CompoundShapeBatch<BigCompound>(pool, initialCapacity, shapes);
}

public int ChildCount
public readonly int ChildCount
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return Children.Length; }
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref CompoundChild GetChild(int compoundChildIndex)
public readonly ref CompoundChild GetChild(int compoundChildIndex)
{
return ref Children[compoundChildIndex];
}
Expand Down Expand Up @@ -282,7 +282,7 @@ public unsafe void FindLocalOverlaps<TOverlaps, TSubpairOverlaps>(ref Buffer<Ove
{
ref var pair = ref pairs[i];
enumerator.Overlaps = Unsafe.AsPointer(ref overlaps.GetOverlapsForPair(i));
Unsafe.AsRef<BigCompound>(pair.Container).Tree.GetOverlaps(pair.Min, pair.Max, ref enumerator);
Unsafe.AsRef<BigCompound>(pair.Container).Tree.GetOverlaps(pair.Min, pair.Max, pool, ref enumerator);
}
}

Expand All @@ -296,13 +296,13 @@ public void TestLeaf(int leafIndex, ref float maximumT)
Unsafe.AsRef<TOverlaps>(Overlaps).Allocate(Pool) = leafIndex;
}
}
public unsafe void FindLocalOverlaps<TOverlaps>(Vector3 min, Vector3 max, Vector3 sweep, float maximumT, BufferPool pool, Shapes shapes, void* overlaps)
public readonly unsafe void FindLocalOverlaps<TOverlaps>(Vector3 min, Vector3 max, Vector3 sweep, float maximumT, BufferPool pool, Shapes shapes, void* overlaps)
where TOverlaps : ICollisionTaskSubpairOverlaps
{
SweepLeafTester<TOverlaps> enumerator;
enumerator.Pool = pool;
enumerator.Overlaps = overlaps;
Tree.Sweep(min, max, sweep, maximumT, ref enumerator);
Tree.Sweep(min, max, sweep, maximumT, pool, ref enumerator);
}

/// <summary>
Expand All @@ -311,7 +311,7 @@ public unsafe void FindLocalOverlaps<TOverlaps>(Vector3 min, Vector3 max, Vector
/// <param name="childMasses">Masses of the children.</param>
/// <param name="shapes">Shapes collection containing the data for the compound child shapes.</param>
/// <returns>Inertia of the compound.</returns>
public BodyInertia ComputeInertia(Span<float> childMasses, Shapes shapes)
public readonly BodyInertia ComputeInertia(Span<float> childMasses, Shapes shapes)
{
return CompoundBuilder.ComputeInertia(Children, childMasses, shapes);
}
Expand All @@ -323,7 +323,7 @@ public BodyInertia ComputeInertia(Span<float> childMasses, Shapes shapes)
/// <param name="childMasses">Masses of the children.</param>
/// <param name="centerOfMass">Calculated center of mass of the compound. Subtracted from all the compound child poses.</param>
/// <returns>Inertia of the compound.</returns>
public BodyInertia ComputeInertia(Span<float> childMasses, Shapes shapes, out Vector3 centerOfMass)
public readonly BodyInertia ComputeInertia(Span<float> childMasses, Shapes shapes, out Vector3 centerOfMass)
{
var bodyInertia = CompoundBuilder.ComputeInertia(Children, childMasses, shapes, out centerOfMass);
//Recentering moves the children around, so the tree needs to be updated.
Expand Down
12 changes: 6 additions & 6 deletions BepuPhysics/Collidables/Compound.cs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ public void ComputeBounds(Quaternion orientation, Shapes shapeBatches, out Vecto
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void AddChildBoundsToBatcher(ref Buffer<CompoundChild> children, ref BoundingBoxBatcher batcher, in RigidPose pose, in BodyVelocity velocity, int bodyIndex)
public static void AddChildBoundsToBatcher(Buffer<CompoundChild> children, ref BoundingBoxBatcher batcher, in RigidPose pose, in BodyVelocity velocity, int bodyIndex)
{
//Note that this approximates the velocity of the child using a piecewise extrapolation using the parent's angular velocity.
//For significant angular velocities, this is actually wrong, but this is how v1 worked forever and it's cheap.
Expand Down Expand Up @@ -223,10 +223,10 @@ public static void AddChildBoundsToBatcher(ref Buffer<CompoundChild> children, r
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddChildBoundsToBatcher(ref BoundingBoxBatcher batcher, in RigidPose pose, in BodyVelocity velocity, int bodyIndex)
{
AddChildBoundsToBatcher(ref Children, ref batcher, pose, velocity, bodyIndex);
AddChildBoundsToBatcher(Children, ref batcher, pose, velocity, bodyIndex);
}

public void RayTest<TRayHitHandler>(in RigidPose pose, in RayData ray, ref float maximumT, Shapes shapeBatches, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler
public void RayTest<TRayHitHandler>(in RigidPose pose, in RayData ray, ref float maximumT, Shapes shapeBatches, BufferPool pool, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler
{
Matrix3x3.CreateFromQuaternion(pose.Orientation, out var orientation);
RayData localRay;
Expand All @@ -242,7 +242,7 @@ public void RayTest<TRayHitHandler>(in RigidPose pose, in RayData ray, ref float
CompoundChildShapeTester tester;
tester.T = -1;
tester.Normal = default;
shapeBatches[child.ShapeIndex.Type].RayTest(child.ShapeIndex.Index, child.AsPose(), localRay, ref maximumT, ref tester);
shapeBatches[child.ShapeIndex.Type].RayTest(child.ShapeIndex.Index, child.AsPose(), localRay, ref maximumT, pool, ref tester);
if (tester.T >= 0)
{
Debug.Assert(maximumT >= tester.T, "Whatever generated this ray hit should have obeyed the current maximumT value.");
Expand All @@ -253,15 +253,15 @@ public void RayTest<TRayHitHandler>(in RigidPose pose, in RayData ray, ref float
}
}

public unsafe void RayTest<TRayHitHandler>(in RigidPose pose, ref RaySource rays, Shapes shapeBatches, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler
public unsafe void RayTest<TRayHitHandler>(in RigidPose pose, ref RaySource rays, Shapes shapeBatches, BufferPool pool, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler
{
//TODO: Note that we dispatch a bunch of scalar tests here. You could be more clever than this- batched tests are possible.
//It's relatively easy to do batching for this compound type since there is no hierarchy traversal, but we refactored things to avoid an infinite generic expansion issue in AOT compilation.
//There are plenty of ways to work around that, but right now our batched raytracing implementation is bad enough that spending extra work here is questionable. We'll avoid breaking it for now, but that's all.
for (int i = 0; i < rays.RayCount; ++i)
{
rays.GetRay(i, out var ray, out var maximumT);
RayTest(pose, *ray, ref *maximumT, shapeBatches, ref hitHandler);
RayTest(pose, *ray, ref *maximumT, shapeBatches, pool, ref hitHandler);
}
}

Expand Down
15 changes: 8 additions & 7 deletions BepuPhysics/Collidables/IShape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,18 +104,16 @@ public interface ICompoundShape : IDisposableShape, IBoundsQueryableCompound
/// <param name="bodyIndex">Index of the body in the active body set; used to accumulate child bounds results.</param>
void AddChildBoundsToBatcher(ref BoundingBoxBatcher batcher, in RigidPose pose, in BodyVelocity velocity, int bodyIndex);

//Compound shapes may require indirections into other shape batches. This isn't wonderfully fast, but this scalar path is designed more for convenience than performance anyway.
//For performance, a batched and vectorized codepath should be used.

/// <summary>
/// Tests a ray against the shape.
/// </summary>
/// <param name="pose">Pose of the shape during the ray test.</param>
/// <param name="ray">Ray to test against the shape.</param>
/// <param name="maximumT">Maximum distance along the ray, in units of the ray direction's length, that the ray will test.</param>
/// <param name="shapeBatches">Shape batches to look up child shapes in if necessary.</param>
/// <param name="pool">Buffer pool used for any temporary allocations required by the test.</param>
/// <param name="hitHandler">Callbacks called when the ray interacts with a test candidate.</param>
void RayTest<TRayHitHandler>(in RigidPose pose, in RayData ray, ref float maximumT, Shapes shapeBatches, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler;
void RayTest<TRayHitHandler>(in RigidPose pose, in RayData ray, ref float maximumT, Shapes shapeBatches, BufferPool pool, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler;

/// <summary>
/// Tests multiple rays against the shape.
Expand All @@ -124,7 +122,8 @@ public interface ICompoundShape : IDisposableShape, IBoundsQueryableCompound
/// <param name="rays">Rays to test against the shape.</param>
/// <param name="shapeBatches">Shape batches to look up child shapes in if necessary.</param>
/// <param name="hitHandler">Callbacks called when the ray interacts with a test candidate.</param>
void RayTest<TRayHitHandler>(in RigidPose pose, ref RaySource rays, Shapes shapeBatches, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler;
/// <param name="pool">Buffer pool used for any temporary allocations required by the test.</param>
void RayTest<TRayHitHandler>(in RigidPose pose, ref RaySource rays, Shapes shapeBatches, BufferPool pool, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler;
/// <summary>
/// Gets the number of children in the compound shape.
/// </summary>
Expand Down Expand Up @@ -160,16 +159,18 @@ public interface IHomogeneousCompoundShape<TChildShape, TChildShapeWide> : IDisp
/// <param name="pose">Pose of the shape during the ray test.</param>
/// <param name="ray">Ray to test against the shape.</param>
/// <param name="maximumT">Maximum distance along the ray, in units of the ray direction's length, that the ray will test.</param>
/// <param name="pool">Buffer pool used for any temporary allocations required by the test.</param>
/// <param name="hitHandler">Callbacks called when the ray interacts with a test candidate.</param>
void RayTest<TRayHitHandler>(in RigidPose pose, in RayData ray, ref float maximumT, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler;
void RayTest<TRayHitHandler>(in RigidPose pose, in RayData ray, ref float maximumT, BufferPool pool, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler;

/// <summary>
/// Tests multiple rays against the shape.
/// </summary>
/// <param name="pose">Pose of the shape during the ray test.</param>
/// <param name="rays">Rays to test against the shape.</param>
/// <param name="pool">Buffer pool used for any temporary allocations required by the test.</param>
/// <param name="hitHandler">Callbacks called when the ray interacts with a test candidate.</param>
void RayTest<TRayHitHandler>(in RigidPose pose, ref RaySource rays, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler;
void RayTest<TRayHitHandler>(in RigidPose pose, ref RaySource rays, BufferPool pool, ref TRayHitHandler hitHandler) where TRayHitHandler : struct, IShapeRayHitHandler;
/// <summary>
/// Gets the number of children in the compound shape.
/// </summary>
Expand Down
Loading
Loading