Fixed heap corruption caused by out-of-sync collider active states

This commit is contained in:
Diren D Bharwani 2023-03-04 14:31:07 +08:00
parent a691d2ff28
commit b9c9f30ce0
8 changed files with 56 additions and 55 deletions

View File

@ -41,17 +41,17 @@
- EID: 3 - EID: 3
Name: Default Name: Default
IsActive: true IsActive: true
NumberOfChildren: 1 NumberOfChildren: 0
Components: Components:
Transform Component: Transform Component:
Translate: {x: -0.597273231, y: 5, z: 0} Translate: {x: 0.141888797, y: 5, z: 0}
Rotate: {x: -0, y: 0, z: 0.490080804} Rotate: {x: -0, y: 0, z: 0.490080774}
Scale: {x: 0.999999702, y: 0.999999702, z: 1} Scale: {x: 0.999999702, y: 0.999999702, z: 1}
IsActive: true IsActive: true
RigidBody Component: RigidBody Component:
Type: Static Type: Dynamic
Auto Mass: false Auto Mass: false
Mass: .inf Mass: 1
Drag: 0.00999999978 Drag: 0.00999999978
Angular Drag: 0.00999999978 Angular Drag: 0.00999999978
Use Gravity: true Use Gravity: true
@ -88,26 +88,9 @@
NumberOfChildren: 0 NumberOfChildren: 0
Components: Components:
Transform Component: Transform Component:
Translate: {x: 0, y: -2, z: 0} Translate: {x: 0.34412086, y: 3.23541069, z: 0}
Rotate: {x: 0, y: 0, z: 0} Rotate: {x: 0, y: 0, z: 0.490080804}
Scale: {x: 1, y: 1, z: 1} Scale: {x: 0.999999702, y: 0.999999702, z: 1}
IsActive: true
RigidBody Component:
Type: Dynamic
Auto Mass: false
Mass: 1
Drag: 0.00999999978
Angular Drag: 0.00999999978
Use Gravity: true
Gravity Scale: 1
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true IsActive: true
Collider Component: Collider Component:
Colliders: Colliders:
@ -120,5 +103,5 @@
Density: 1 Density: 1
Position Offset: {x: 0, y: 0, z: 0} Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0} Rotation Offset: {x: 0, y: 0, z: 0}
IsActive: true IsActive: false
Scripts: ~ Scripts: ~

View File

@ -432,8 +432,6 @@ namespace SHADE
// TODO: Handle differences between composite & hull collider // TODO: Handle differences between composite & hull collider
if (ImGui::BeginMenu("Add Collider")) if (ImGui::BeginMenu("Add Collider"))
{ {
int newColl = -1;
if (ImGui::Selectable("Box Collider")) if (ImGui::Selectable("Box Collider"))
{ {
auto* compositeCollider = reinterpret_cast<SHCompositeCollider* const>(component->GetCollider()); auto* compositeCollider = reinterpret_cast<SHCompositeCollider* const>(component->GetCollider());

View File

@ -204,7 +204,7 @@ namespace SHADE
for (auto* shape : shapes) for (auto* shape : shapes)
{ {
if (PREV_STATE) // Previously inactive if (!PREV_STATE) // Previously inactive
broadphase->Insert(shape->id, shape->ComputeAABB()); broadphase->Insert(shape->id, shape->ComputeAABB());
else // Previously active else // Previously active
broadphase->Remove(shape->id); broadphase->Remove(shape->id);
@ -300,7 +300,7 @@ namespace SHADE
}; };
// Remove from broadphase // Remove from broadphase
if (broadphase) if (IsActive() && broadphase)
broadphase->Remove((*shape)->id); broadphase->Remove((*shape)->id);
shapeLibrary->DestroyShape(*shape); shapeLibrary->DestroyShape(*shape);

View File

@ -49,12 +49,15 @@ namespace SHADE
return; return;
} }
if (collider->IsActive())
{
collider->broadphase = &broadphase; collider->broadphase = &broadphase;
// Add all existing shapes to the broadphase // Attempt to add all existing shapes to the broadphase
for (const auto* shape : collider->shapes) for (const auto* shape : collider->shapes)
broadphase.Insert(shape->id, shape->ComputeAABB()); broadphase.Insert(shape->id, shape->ComputeAABB());
} }
}
void SHCollisionSpace::RemoveCollider(SHCollider* collider) noexcept void SHCollisionSpace::RemoveCollider(SHCollider* collider) noexcept
{ {
@ -64,6 +67,9 @@ namespace SHADE
if (NUM_SHAPES == 0) if (NUM_SHAPES == 0)
return; return;
// If collider is inactive, skip removals since they were already removed
if (collider->IsActive())
{
for (uint32_t i = 0; i < NUM_SHAPES; ++i) for (uint32_t i = 0; i < NUM_SHAPES; ++i)
broadphase.Remove(collider->shapes[i]->id); broadphase.Remove(collider->shapes[i]->id);
@ -72,6 +78,7 @@ namespace SHADE
contactManager->RemoveInvalidatedTrigger(collider->entityID); contactManager->RemoveInvalidatedTrigger(collider->entityID);
contactManager->RemoveInvalidatedManifold(collider->entityID); contactManager->RemoveInvalidatedManifold(collider->entityID);
} }
}
/* /*
* TODO: * TODO:

View File

@ -252,22 +252,13 @@ namespace SHADE
{ {
// New states start at invalid. In the first frame of collision, move to enter. // New states start at invalid. In the first frame of collision, move to enter.
// If it already in enter, move to stay // If it already in enter, move to stay
if (state == SHCollisionState::ENTER) state = state == SHCollisionState::INVALID ? SHCollisionState::ENTER : SHCollisionState::STAY;
state = SHCollisionState::STAY;
if (state == SHCollisionState::INVALID)
state = SHCollisionState::ENTER;
} }
else else
{ {
// If already exited and still not colliding, the collision has expired. // If already exited and still not colliding, the collision has expired.
// Invalid states are removed in the next frame // Invalid states are removed in the next frame
if (state == SHCollisionState::EXIT) state = state == SHCollisionState::EXIT ? SHCollisionState::INVALID : SHCollisionState::EXIT;
state = SHCollisionState::INVALID;
// If previously colliding, move to exit.
if (state == SHCollisionState::ENTER || state == SHCollisionState::STAY)
state = SHCollisionState::EXIT;
} }
} }

View File

@ -86,8 +86,6 @@ namespace SHADE
void SHPhysicsWorld::Step(float dt) void SHPhysicsWorld::Step(float dt)
{ {
/* /*
* Detect Collisions * Detect Collisions
*/ */

View File

@ -57,6 +57,7 @@ namespace SHADE
for (const auto& COLLIDER_COMPONENT : COLLIDER_COMPONENT_DENSE) for (const auto& COLLIDER_COMPONENT : COLLIDER_COMPONENT_DENSE)
{ {
const auto* COLLIDER = COLLIDER_COMPONENT.GetCollider(); const auto* COLLIDER = COLLIDER_COMPONENT.GetCollider();
if (COLLIDER->IsActive())
drawCollider(debugDrawSystem, *COLLIDER); drawCollider(debugDrawSystem, *COLLIDER);
} }
} }
@ -65,6 +66,7 @@ namespace SHADE
for (const auto EID : physicsDebugDrawSystem->collidersToDraw) for (const auto EID : physicsDebugDrawSystem->collidersToDraw)
{ {
const auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(EID)->GetCollider(); const auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(EID)->GetCollider();
if (COLLIDER->IsActive())
drawCollider(debugDrawSystem, *COLLIDER); drawCollider(debugDrawSystem, *COLLIDER);
} }
} }

View File

@ -52,8 +52,19 @@ namespace SHADE
const bool RIGIDBODY_ACTIVE = physicsObject.rigidBody->IsActive(); const bool RIGIDBODY_ACTIVE = physicsObject.rigidBody->IsActive();
if (IS_ACTIVE != RIGIDBODY_ACTIVE) if (IS_ACTIVE != RIGIDBODY_ACTIVE)
{
physicsObject.rigidBody->SetIsActive(IS_ACTIVE); physicsObject.rigidBody->SetIsActive(IS_ACTIVE);
// If previously active, we remove it from the world.
// If previously inactive, we add it back to the world.
// This removes the need to check for inactive objects in the world every frame to remove invalid contacts.
if (IS_ACTIVE) // Previously inactive
physicsSystem->physicsWorld->AddRigidBody(physicsObject.rigidBody);
else // Previously active
physicsSystem->physicsWorld->RemoveRigidBody(physicsObject.rigidBody);
}
if (UPDATE_TRANSFORM) if (UPDATE_TRANSFORM)
{ {
const SHVec3& WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition(); const SHVec3& WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition();
@ -71,8 +82,19 @@ namespace SHADE
const bool COLLIDER_ACTIVE = physicsObject.collider->IsActive(); const bool COLLIDER_ACTIVE = physicsObject.collider->IsActive();
if (IS_ACTIVE != COLLIDER_ACTIVE) if (IS_ACTIVE != COLLIDER_ACTIVE)
{
physicsObject.collider->SetIsActive(IS_ACTIVE); physicsObject.collider->SetIsActive(IS_ACTIVE);
// If previously active, we remove it from the world.
// If previously inactive, we add it back to the world.
// This removes the need to check for inactive objects in the world every frame to remove invalid contacts.
if (IS_ACTIVE) // Previously inactive
physicsSystem->collisionSpace->AddCollider(physicsObject.collider);
else // Previously active
physicsSystem->collisionSpace->RemoveCollider(physicsObject.collider);
}
if (UPDATE_TRANSFORM) if (UPDATE_TRANSFORM)
{ {
const SHVec3& WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition(); const SHVec3& WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition();