Fixed bug where reduced manifold would attempt to grab an invalid contact
This commit is contained in:
parent
199a9aa025
commit
991912f7b4
|
@ -1,4 +1,4 @@
|
||||||
Start Maximized: true
|
Start Maximized: true
|
||||||
Working Scene ID: 92914350
|
Working Scene ID: 97402985
|
||||||
Window Size: {x: 2000, y: 1518}
|
Window Size: {x: 2000, y: 1518}
|
||||||
Style: 0
|
Style: 0
|
|
@ -207,7 +207,7 @@
|
||||||
Components:
|
Components:
|
||||||
Transform Component:
|
Transform Component:
|
||||||
Translate: {x: -1, y: 7, z: 0}
|
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}
|
Scale: {x: 0.999999642, y: 0.999998569, z: 0.999999642}
|
||||||
IsActive: true
|
IsActive: true
|
||||||
RigidBody Component:
|
RigidBody Component:
|
||||||
|
@ -223,9 +223,9 @@
|
||||||
Freeze Position X: false
|
Freeze Position X: false
|
||||||
Freeze Position Y: false
|
Freeze Position Y: false
|
||||||
Freeze Position Z: false
|
Freeze Position Z: false
|
||||||
Freeze Rotation X: false
|
Freeze Rotation X: true
|
||||||
Freeze Rotation Y: false
|
Freeze Rotation Y: true
|
||||||
Freeze Rotation Z: false
|
Freeze Rotation Z: true
|
||||||
IsActive: true
|
IsActive: true
|
||||||
Collider Component:
|
Collider Component:
|
||||||
DrawColliders: false
|
DrawColliders: false
|
||||||
|
|
|
@ -542,13 +542,12 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reduce contact manifold if more than 4 points
|
// 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;
|
std::vector<SHContact> reducedContacts;
|
||||||
|
|
||||||
const int32_t NUM_REDUCED = static_cast<int32_t>(INDICES_TO_KEEP.size());
|
for (int32_t i = 0; i < SHPHYSICS_MAX_MANIFOLD_CONTACTS; ++i)
|
||||||
for (int32_t i = 0; i < NUM_REDUCED; ++i)
|
|
||||||
reducedContacts.emplace_back(contacts[INDICES_TO_KEEP[i]]);
|
reducedContacts.emplace_back(contacts[INDICES_TO_KEEP[i]]);
|
||||||
|
|
||||||
contacts.clear();
|
contacts.clear();
|
||||||
|
@ -638,7 +637,7 @@ namespace SHADE
|
||||||
// In case the edge is parallel, the intersection is just the end point
|
// In case the edge is parallel, the intersection is just the end point
|
||||||
const float DOT = SHVec3::Dot(v2Pos - v1Pos, PLANE_NORMAL);
|
const float DOT = SHVec3::Dot(v2Pos - v1Pos, PLANE_NORMAL);
|
||||||
const bool IS_PARALLEL = SHMath::CompareFloat(DOT, 0.0f);
|
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.position = SHVec3::ClampedLerp(v1Pos, v2Pos, ALPHA);
|
||||||
intersection.featurePair.inI = 0;
|
intersection.featurePair.inI = 0;
|
||||||
|
@ -670,12 +669,13 @@ namespace SHADE
|
||||||
|
|
||||||
// Use a map to temporarily store and track the contacts we want
|
// Use a map to temporarily store and track the contacts we want
|
||||||
std::unordered_map<int, const SHContact*> contactMap;
|
std::unordered_map<int, const SHContact*> contactMap;
|
||||||
|
|
||||||
const int32_t NUM_CONTACTS = static_cast<int32_t>(in.size());
|
const int32_t NUM_CONTACTS = static_cast<int32_t>(in.size());
|
||||||
for (int32_t i = 0; i < NUM_CONTACTS; ++i)
|
for (int32_t i = 0; i < NUM_CONTACTS; ++i)
|
||||||
contactMap.emplace(i, &in[i]);
|
contactMap.emplace(i, &in[i]);
|
||||||
|
|
||||||
// Find the furthest point in a given direction
|
// Find the furthest point in a given direction
|
||||||
int32_t indexToKeep = -1;
|
int32_t indexToKeep = 0;
|
||||||
float bestDistance = std::numeric_limits<float>::lowest();
|
float bestDistance = std::numeric_limits<float>::lowest();
|
||||||
|
|
||||||
for (const auto& [index, contact] : contactMap)
|
for (const auto& [index, contact] : contactMap)
|
||||||
|
@ -691,8 +691,7 @@ namespace SHADE
|
||||||
indicesToKeep.emplace_back(indexToKeep);
|
indicesToKeep.emplace_back(indexToKeep);
|
||||||
contactMap.erase(indexToKeep);
|
contactMap.erase(indexToKeep);
|
||||||
|
|
||||||
|
indexToKeep = 0;
|
||||||
indexToKeep = -1;
|
|
||||||
bestDistance = std::numeric_limits<float>::lowest();
|
bestDistance = std::numeric_limits<float>::lowest();
|
||||||
|
|
||||||
// Find point furthest away from the first index
|
// Find point furthest away from the first index
|
||||||
|
@ -710,7 +709,7 @@ namespace SHADE
|
||||||
indicesToKeep.emplace_back(indexToKeep);
|
indicesToKeep.emplace_back(indexToKeep);
|
||||||
contactMap.erase(indexToKeep);
|
contactMap.erase(indexToKeep);
|
||||||
|
|
||||||
indexToKeep = -1;
|
indexToKeep = 0;
|
||||||
|
|
||||||
// We compute the triangle with the largest area.
|
// We compute the triangle with the largest area.
|
||||||
// The area can be positive or negative depending on the winding order.
|
// 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
|
// Compare which triangle creates the largest area
|
||||||
bool isAreaPositive = false;
|
bool isAreaPositive = false;
|
||||||
if (maxArea > (-minArea))
|
if (maxArea > std::fabs(minArea))
|
||||||
{
|
{
|
||||||
isAreaPositive = true;
|
isAreaPositive = true;
|
||||||
indexToKeep = maxAreaIndex;
|
indexToKeep = maxAreaIndex;
|
||||||
|
@ -759,7 +758,7 @@ namespace SHADE
|
||||||
indicesToKeep.emplace_back(indexToKeep);
|
indicesToKeep.emplace_back(indexToKeep);
|
||||||
contactMap.erase(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
|
// 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.
|
// The areas should be inverted: If area was -ve, we want a +ve. Otherwise, vice versa.
|
||||||
|
|
|
@ -15,36 +15,42 @@
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* The number of contacts required to build a stable manifold.
|
||||||
|
*/
|
||||||
|
static constexpr int SHPHYSICS_MAX_MANIFOLD_CONTACTS = 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
* The number of simulations length for every real world unit meter. <br/>
|
* The number of simulations length for every real world unit meter. <br/>
|
||||||
* Modify this to change the global scale of the simulation.
|
* 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
|
* @brief
|
||||||
* Linear Collision & Constraint tolerance.
|
* 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
|
* @brief
|
||||||
* Velocity threshold for restitution to be applied.
|
* Velocity threshold for restitution to be applied.
|
||||||
*/
|
*/
|
||||||
static constexpr float SHPHYSICS_RESTITUTION_THRESHOLD = 1.0f;
|
static constexpr float SHPHYSICS_RESTITUTION_THRESHOLD = 1.0f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
* Scaling factor to control how fast overlaps are resolved.<br/>
|
* 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.
|
* 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
|
* @brief
|
||||||
* Distance threshold to consider two contacts as the same.
|
* 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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue