Support compound shapes in sweeps and ignore self-hits#41
Support compound shapes in sweeps and ignore self-hits#41OJuergen wants to merge 1 commit intouberpixel:developfrom
Conversation
There was a problem hiding this comment.
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
ignoreActormechanism toPhysXQueryFilterCallbackand use it during sweeps to filter out self-hits. - Update
PhysXWorld::CastSweepto 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.
| for(size_t i = 0; i < compound->GetNumberOfShapes(); i++) | ||
| { | ||
| PhysXShape *child = compound->GetShape(i); | ||
| sweep(child); | ||
| } | ||
|
|
There was a problem hiding this comment.
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).
| 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; | |
| } |
| sweep(child); | ||
| } | ||
|
|
||
| // todo(OJ) or return compound shape? if(bestHit.distance >= 0.0f) bestHit.shapeSelf = shape; |
There was a problem hiding this comment.
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.
| // 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. |
No description provided.