From 991912f7b4650f3a528141eff15571a5ebbf73e1 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 2 Mar 2023 07:09:14 +0800 Subject: [PATCH] Fixed bug where reduced manifold would attempt to grab an invalid contact --- Assets/Editor/Editor.SHConfig | 2 +- Assets/Scenes/PhysicsSandbox.shade | 8 +++---- .../Narrowphase/SHConvexVsConvex.cpp | 21 +++++++++---------- SHADE_Engine/src/Physics/SHPhysicsConstants.h | 16 +++++++++----- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/Assets/Editor/Editor.SHConfig b/Assets/Editor/Editor.SHConfig index 65fe522e..2d84f1af 100644 --- a/Assets/Editor/Editor.SHConfig +++ b/Assets/Editor/Editor.SHConfig @@ -1,4 +1,4 @@ Start Maximized: true -Working Scene ID: 92914350 +Working Scene ID: 97402985 Window Size: {x: 2000, y: 1518} Style: 0 \ No newline at end of file diff --git a/Assets/Scenes/PhysicsSandbox.shade b/Assets/Scenes/PhysicsSandbox.shade index 584a1667..7bab2e59 100644 --- a/Assets/Scenes/PhysicsSandbox.shade +++ b/Assets/Scenes/PhysicsSandbox.shade @@ -207,7 +207,7 @@ Components: Transform Component: Translate: {x: -1, y: 7, z: 0} - Rotate: {x: 0, y: 0, z: 0.785398185} + Rotate: {x: 0, y: 0, z: 0} Scale: {x: 0.999999642, y: 0.999998569, z: 0.999999642} IsActive: true RigidBody Component: @@ -223,9 +223,9 @@ Freeze Position X: false Freeze Position Y: false Freeze Position Z: false - Freeze Rotation X: false - Freeze Rotation Y: false - Freeze Rotation Z: false + Freeze Rotation X: true + Freeze Rotation Y: true + Freeze Rotation Z: true IsActive: true Collider Component: DrawColliders: false diff --git a/SHADE_Engine/src/Physics/Collision/Narrowphase/SHConvexVsConvex.cpp b/SHADE_Engine/src/Physics/Collision/Narrowphase/SHConvexVsConvex.cpp index a2c7f9f8..4d12b716 100644 --- a/SHADE_Engine/src/Physics/Collision/Narrowphase/SHConvexVsConvex.cpp +++ b/SHADE_Engine/src/Physics/Collision/Narrowphase/SHConvexVsConvex.cpp @@ -542,13 +542,12 @@ namespace SHADE } // Reduce contact manifold if more than 4 points - if (numContacts > 4) + if (numContacts > SHPHYSICS_MAX_MANIFOLD_CONTACTS) { - const auto INDICES_TO_KEEP = reduceContacts(contacts, REF_NORMAL); + const auto INDICES_TO_KEEP = reduceContacts(contacts, LOCAL_REF_NORMAL); std::vector reducedContacts; - const int32_t NUM_REDUCED = static_cast(INDICES_TO_KEEP.size()); - for (int32_t i = 0; i < NUM_REDUCED; ++i) + for (int32_t i = 0; i < SHPHYSICS_MAX_MANIFOLD_CONTACTS; ++i) reducedContacts.emplace_back(contacts[INDICES_TO_KEEP[i]]); contacts.clear(); @@ -638,7 +637,7 @@ namespace SHADE // In case the edge is parallel, the intersection is just the end point const float DOT = SHVec3::Dot(v2Pos - v1Pos, PLANE_NORMAL); const bool IS_PARALLEL = SHMath::CompareFloat(DOT, 0.0f); - const float ALPHA = IS_PARALLEL ? 1.0f : (-plane.GetDistance() - SHVec3::Dot(v1Pos, PLANE_NORMAL)) / DOT; + const float ALPHA = IS_PARALLEL ? 0.0f : (-plane.GetDistance() - SHVec3::Dot(v1Pos, PLANE_NORMAL)) / DOT; intersection.position = SHVec3::ClampedLerp(v1Pos, v2Pos, ALPHA); intersection.featurePair.inI = 0; @@ -670,12 +669,13 @@ namespace SHADE // Use a map to temporarily store and track the contacts we want std::unordered_map contactMap; + const int32_t NUM_CONTACTS = static_cast(in.size()); for (int32_t i = 0; i < NUM_CONTACTS; ++i) contactMap.emplace(i, &in[i]); // Find the furthest point in a given direction - int32_t indexToKeep = -1; + int32_t indexToKeep = 0; float bestDistance = std::numeric_limits::lowest(); for (const auto& [index, contact] : contactMap) @@ -691,8 +691,7 @@ namespace SHADE indicesToKeep.emplace_back(indexToKeep); contactMap.erase(indexToKeep); - - indexToKeep = -1; + indexToKeep = 0; bestDistance = std::numeric_limits::lowest(); // Find point furthest away from the first index @@ -710,7 +709,7 @@ namespace SHADE indicesToKeep.emplace_back(indexToKeep); contactMap.erase(indexToKeep); - indexToKeep = -1; + indexToKeep = 0; // We compute the triangle with the largest area. // The area can be positive or negative depending on the winding order. @@ -745,7 +744,7 @@ namespace SHADE // Compare which triangle creates the largest area bool isAreaPositive = false; - if (maxArea > (-minArea)) + if (maxArea > std::fabs(minArea)) { isAreaPositive = true; indexToKeep = maxAreaIndex; @@ -759,7 +758,7 @@ namespace SHADE indicesToKeep.emplace_back(indexToKeep); contactMap.erase(indexToKeep); - indexToKeep = -1; + indexToKeep = 0; // For the last point, we want the point which forms the largest area that is winded opposite to the first triangle // The areas should be inverted: If area was -ve, we want a +ve. Otherwise, vice versa. diff --git a/SHADE_Engine/src/Physics/SHPhysicsConstants.h b/SHADE_Engine/src/Physics/SHPhysicsConstants.h index b680515e..3cbf52bf 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsConstants.h +++ b/SHADE_Engine/src/Physics/SHPhysicsConstants.h @@ -15,36 +15,42 @@ namespace SHADE { + /** + * @brief + * The number of contacts required to build a stable manifold. + */ + static constexpr int SHPHYSICS_MAX_MANIFOLD_CONTACTS = 4; + /** * @brief * The number of simulations length for every real world unit meter.
* Modify this to change the global scale of the simulation. */ - static constexpr float SHPHYSICS_LENGTHS_PER_UNIT_METER = 1.0f; + static constexpr float SHPHYSICS_LENGTHS_PER_UNIT_METER = 1.0f; /** * @brief * Linear Collision & Constraint tolerance. */ - static constexpr float SHPHYSICS_LINEAR_SLOP = 0.01f * SHPHYSICS_LENGTHS_PER_UNIT_METER; + static constexpr float SHPHYSICS_LINEAR_SLOP = 0.01f * SHPHYSICS_LENGTHS_PER_UNIT_METER; /** * @brief * Velocity threshold for restitution to be applied. */ - static constexpr float SHPHYSICS_RESTITUTION_THRESHOLD = 1.0f; + static constexpr float SHPHYSICS_RESTITUTION_THRESHOLD = 1.0f; /** * @brief * Scaling factor to control how fast overlaps are resolved.
* 1 is ideal for instant correction, but values close to 1 can lead to overshoot. */ - static constexpr float SHPHYSICS_BAUMGARTE = 0.2f; + static constexpr float SHPHYSICS_BAUMGARTE = 0.2f; /** * @brief * Distance threshold to consider two contacts as the same. */ - static constexpr float SHPHYSICS_SAME_CONTACT_DISTANCE = 0.01; + static constexpr float SHPHYSICS_SAME_CONTACT_DISTANCE = 0.01; }