Skip to content

Support compound shapes in sweeps and ignore self-hits#41

Open
OJuergen wants to merge 1 commit intouberpixel:developfrom
OJuergen:feature/compoundSweepAndSelfIgnore
Open

Support compound shapes in sweeps and ignore self-hits#41
OJuergen wants to merge 1 commit intouberpixel:developfrom
OJuergen:feature/compoundSweepAndSelfIgnore

Conversation

@OJuergen
Copy link

No description provided.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates PhysX scene queries to better support sweep-casting with compound shapes and to avoid returning immediate “self-hit” results when the sweep shape is already attached to a scene actor.

Changes:

  • Add an ignoreActor mechanism to PhysXQueryFilterCallback and use it during sweeps to filter out self-hits.
  • Update PhysXWorld::CastSweep to iterate over compound shape children and keep the closest blocking hit.
  • Add an early-return guard for near-zero sweep distance to avoid invalid normalization.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
Modules/PhysX/RNPhysXWorld.cpp Refactors CastSweep to handle compound shapes by sweeping child shapes and to ignore self-hits via query filtering.
Modules/PhysX/RNPhysXInternals.h Adds ignoreActor state to the query filter callback.
Modules/PhysX/RNPhysXInternals.cpp Implements ignoring the specified actor in preFilter.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +424 to +429
for(size_t i = 0; i < compound->GetNumberOfShapes(); i++)
{
PhysXShape *child = compound->GetShape(i);
sweep(child);
}

Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When sweeping a PhysXCompoundShape, each child is swept using the same pose (derived only from from/rotation). This ignores the per-child transform stored on the compound (GetPosition(i) / GetRotation(i)), so compound children that are offset/rotated will be swept in the wrong place and the returned hit distance/normal can be incorrect. Consider composing a per-child sweep pose (e.g., pose * childLocalTransform) for each child, consistent with how compound transforms are represented elsewhere (and how Jolt compound shapes behave).

Suggested change
for(size_t i = 0; i < compound->GetNumberOfShapes(); i++)
{
PhysXShape *child = compound->GetShape(i);
sweep(child);
}
// For compound shapes, sweep each child using the child's world-space transform.
PhysXContactInfo bestHit;
bestHit.distance = -1.0f;
bestHit.node = nullptr;
bestHit.collisionObject = nullptr;
bestHit.shapeSelf = nullptr;
bestHit.shapeOther = nullptr;
// World-space sweep displacement.
Vector3 delta = to - from;
for(size_t i = 0; i < compound->GetNumberOfShapes(); i++)
{
PhysXShape *child = compound->GetShape(i);
// Compose the child's local transform with the compound's world transform.
const Vector3 childLocalPosition = compound->GetPosition(i);
const Quaternion childLocalRotation = compound->GetRotation(i);
const Vector3 childFrom = from + rotation * childLocalPosition;
const Quaternion childWorldRotation = rotation * childLocalRotation;
const Vector3 childTo = childFrom + delta;
PhysXContactInfo childHit = CastSweep(child, childFrom, childWorldRotation, childTo, inflation, filterGroup, filterMask);
if(childHit.distance >= 0.0f)
{
if(bestHit.distance < 0.0f || childHit.distance < bestHit.distance)
{
bestHit = childHit;
}
}
}
if(bestHit.distance >= 0.0f)
{
// Optionally, we could assign the compound as the "self" shape here.
// For now, keep the child shape that actually hit.
hit = bestHit;
}

Copilot uses AI. Check for mistakes.
sweep(child);
}

// todo(OJ) or return compound shape? if(bestHit.distance >= 0.0f) bestHit.shapeSelf = shape;
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid leaving ambiguous inline TODOs in production code. Either resolve the decision about whether shapeSelf should be the compound or the child shape (and document the chosen behavior), or track this with an issue/ticket and remove the inline TODO comment here.

Suggested change
// todo(OJ) or return compound shape? if(bestHit.distance >= 0.0f) bestHit.shapeSelf = shape;
// For compound shapes, hit.shapeSelf is intentionally set to the specific child shape that produced the hit.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants