From 9d5d80bf4a872b05bec8a2529b3c09a69b71c3e0 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 21 Feb 2025 15:07:44 +0100 Subject: [PATCH] Fix crash when using physics overlap tests with Collider outputs that catch Terrain #3221 --- .../Physics/PhysX/PhysicsBackendPhysX.cpp | 54 ------------------- Source/Engine/Physics/Physics.cpp | 53 ++++++++++++++++-- Source/Engine/Physics/PhysicsBackend.h | 4 -- 3 files changed, 49 insertions(+), 62 deletions(-) diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp index 5c5d107e8..0dce4ebe8 100644 --- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp +++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp @@ -536,15 +536,6 @@ protected: hitInfo = hit.shape ? static_cast(hit.shape->userData) : nullptr; \ } -#define SCENE_QUERY_COLLECT_OVERLAP_COLLIDER() results.Clear(); \ - results.Resize(buffer.getNbTouches(), false); \ - for (int32 i = 0; i < results.Count(); i++) \ - { \ - auto& hitInfo = results[i]; \ - const auto& hit = buffer.getTouch(i); \ - hitInfo = hit.shape ? static_cast(hit.shape->userData) : nullptr; \ - } - namespace { PxFoundation* Foundation = nullptr; @@ -2266,51 +2257,6 @@ bool PhysicsBackend::CheckConvex(void* scene, const Vector3& center, const Colli return scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter); } -bool PhysicsBackend::OverlapBox(void* scene, const Vector3& center, const Vector3& halfExtents, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers) -{ - SCENE_QUERY_SETUP_OVERLAP(); - const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation)); - const PxBoxGeometry geometry(C2P(halfExtents)); - if (!scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter)) - return false; - SCENE_QUERY_COLLECT_OVERLAP_COLLIDER(); - return true; -} - -bool PhysicsBackend::OverlapSphere(void* scene, const Vector3& center, const float radius, Array& results, uint32 layerMask, bool hitTriggers) -{ - SCENE_QUERY_SETUP_OVERLAP(); - const PxTransform pose(C2P(center - scenePhysX->Origin)); - const PxSphereGeometry geometry(radius); - if (!scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter)) - return false; - SCENE_QUERY_COLLECT_OVERLAP_COLLIDER(); - return true; -} - -bool PhysicsBackend::OverlapCapsule(void* scene, const Vector3& center, const float radius, const float height, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers) -{ - SCENE_QUERY_SETUP_OVERLAP(); - const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation)); - const PxCapsuleGeometry geometry(radius, height * 0.5f); - if (!scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter)) - return false; - SCENE_QUERY_COLLECT_OVERLAP_COLLIDER(); - return true; -} - -bool PhysicsBackend::OverlapConvex(void* scene, const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers) -{ - CHECK_RETURN(convexMesh && convexMesh->GetOptions().Type == CollisionDataType::ConvexMesh, false) - SCENE_QUERY_SETUP_OVERLAP(); - const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation)); - const PxConvexMeshGeometry geometry((PxConvexMesh*)convexMesh->GetConvex(), PxMeshScale(C2P(scale))); - if (!scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter)) - return false; - SCENE_QUERY_COLLECT_OVERLAP_COLLIDER(); - return true; -} - bool PhysicsBackend::OverlapBox(void* scene, const Vector3& center, const Vector3& halfExtents, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers) { SCENE_QUERY_SETUP_OVERLAP(); diff --git a/Source/Engine/Physics/Physics.cpp b/Source/Engine/Physics/Physics.cpp index 66d5a76bf..4c5a12e5b 100644 --- a/Source/Engine/Physics/Physics.cpp +++ b/Source/Engine/Physics/Physics.cpp @@ -6,6 +6,7 @@ #include "PhysicalMaterial.h" #include "PhysicsSettings.h" #include "PhysicsStatistics.h" +#include "Colliders/Collider.h" #include "Engine/Engine/Time.h" #include "Engine/Engine/EngineService.h" #include "Engine/Profiler/ProfilerCPU.h" @@ -630,22 +631,66 @@ bool PhysicsScene::CheckConvex(const Vector3& center, const CollisionData* conve bool PhysicsScene::OverlapBox(const Vector3& center, const Vector3& halfExtents, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers) { - return PhysicsBackend::OverlapBox(_scene, center, halfExtents, results, rotation, layerMask, hitTriggers); + Array tmp; + if (PhysicsBackend::OverlapBox(_scene, center, halfExtents, tmp, rotation, layerMask, hitTriggers)) + { + results.EnsureCapacity(tmp.Count()); + for (PhysicsColliderActor* e : tmp) + { + if (e && e->Is()) + results.Add((Collider*)e); + } + return true; + } + return false; } bool PhysicsScene::OverlapSphere(const Vector3& center, const float radius, Array& results, uint32 layerMask, bool hitTriggers) { - return PhysicsBackend::OverlapSphere(_scene, center, radius, results, layerMask, hitTriggers); + Array tmp; + if (PhysicsBackend::OverlapSphere(_scene, center, radius, tmp, layerMask, hitTriggers)) + { + results.EnsureCapacity(tmp.Count()); + for (PhysicsColliderActor* e : tmp) + { + if (e && e->Is()) + results.Add((Collider*)e); + } + return true; + } + return false; } bool PhysicsScene::OverlapCapsule(const Vector3& center, const float radius, const float height, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers) { - return PhysicsBackend::OverlapCapsule(_scene, center, radius, height, results, rotation, layerMask, hitTriggers); + Array tmp; + if (PhysicsBackend::OverlapCapsule(_scene, center, radius, height, tmp, rotation, layerMask, hitTriggers)) + { + results.EnsureCapacity(tmp.Count()); + for (PhysicsColliderActor* e : tmp) + { + if (e && e->Is()) + results.Add((Collider*)e); + } + return true; + } + return false; } bool PhysicsScene::OverlapConvex(const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers) { - return PhysicsBackend::OverlapConvex(_scene, center, convexMesh, scale, results, rotation, layerMask, hitTriggers); + Array tmp; + if (PhysicsBackend::OverlapConvex(_scene, center, convexMesh, scale, tmp, rotation, layerMask, hitTriggers)) + { + results.EnsureCapacity(tmp.Count()); + for (PhysicsColliderActor* e : tmp) + { + if (e && e->Is()) + results.Add((Collider*)e); + } + return true; + } + return false; } bool PhysicsScene::OverlapBox(const Vector3& center, const Vector3& halfExtents, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers) diff --git a/Source/Engine/Physics/PhysicsBackend.h b/Source/Engine/Physics/PhysicsBackend.h index f070a7bfb..74ec7181f 100644 --- a/Source/Engine/Physics/PhysicsBackend.h +++ b/Source/Engine/Physics/PhysicsBackend.h @@ -139,10 +139,6 @@ public: static bool CheckSphere(void* scene, const Vector3& center, float radius, uint32 layerMask, bool hitTriggers); static bool CheckCapsule(void* scene, const Vector3& center, float radius, float height, const Quaternion& rotation, uint32 layerMask, bool hitTriggers); static bool CheckConvex(void* scene, const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, const Quaternion& rotation, uint32 layerMask, bool hitTriggers); - static bool OverlapBox(void* scene, const Vector3& center, const Vector3& halfExtents, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers); - static bool OverlapSphere(void* scene, const Vector3& center, float radius, Array& results, uint32 layerMask, bool hitTriggers); - static bool OverlapCapsule(void* scene, const Vector3& center, float radius, float height, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers); - static bool OverlapConvex(void* scene, const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers); static bool OverlapBox(void* scene, const Vector3& center, const Vector3& halfExtents, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers); static bool OverlapSphere(void* scene, const Vector3& center, float radius, Array& results, uint32 layerMask, bool hitTriggers); static bool OverlapCapsule(void* scene, const Vector3& center, float radius, float height, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers);