Fixed bug where reduced manifold would attempt to grab an invalid contact

This commit is contained in:
Diren D Bharwani 2023-03-02 07:09:14 +08:00
parent 199a9aa025
commit 991912f7b4
4 changed files with 26 additions and 21 deletions

View File

@ -1,4 +1,4 @@
Start Maximized: true
Working Scene ID: 92914350
Working Scene ID: 97402985
Window Size: {x: 2000, y: 1518}
Style: 0

View File

@ -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

View File

@ -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<SHContact> reducedContacts;
const int32_t NUM_REDUCED = static_cast<int32_t>(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<int, const SHContact*> contactMap;
const int32_t NUM_CONTACTS = static_cast<int32_t>(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<float>::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<float>::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.

View File

@ -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. <br/>
* 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.<br/>
* 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;
}