Fixed bug where collision & trigger state were called more than once
This commit is contained in:
parent
446db133d2
commit
6200e3f533
|
@ -38,10 +38,6 @@
|
|||
Rotation Offset: {x: 0, y: 0, z: 0}
|
||||
IsActive: true
|
||||
Scripts:
|
||||
- Type: PhysicsTestObj
|
||||
Enabled: true
|
||||
forceAmount: 50
|
||||
torqueAmount: 500
|
||||
- Type: CollisionTest
|
||||
Enabled: true
|
||||
- EID: 1
|
||||
|
@ -176,46 +172,6 @@
|
|||
Rotation Offset: {x: 0, y: 0, z: 0}
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 7
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0, z: 3}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
IsActive: true
|
||||
RigidBody Component:
|
||||
Type: Dynamic
|
||||
Auto Mass: false
|
||||
Mass: 1
|
||||
Drag: 0.00999999978
|
||||
Angular Drag: 0.100000001
|
||||
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
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Collision Tag: 1
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0, z: 0}
|
||||
Rotation Offset: {x: 0, y: 0, z: 0}
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 8
|
||||
Name: Target
|
||||
IsActive: true
|
||||
|
|
|
@ -76,8 +76,6 @@ namespace SHADE
|
|||
continue;
|
||||
|
||||
const auto* SHAPE_A = manifold.shapeA;
|
||||
const auto* SHAPE_B = manifold.shapeB;
|
||||
|
||||
const SHCollisionUtils::ShapeTransform TF_A = { SHAPE_A->GetWorldCentroid(), SHAPE_A->GetWorldOrientation() };
|
||||
|
||||
for (uint32_t i = 0; i < manifold.numContacts; ++i)
|
||||
|
@ -138,22 +136,41 @@ namespace SHADE
|
|||
removeInvalidObject(manifolds, eid, shapeIndex);
|
||||
}
|
||||
|
||||
void SHContactManager::RemoveExpiredContacts() noexcept
|
||||
{
|
||||
// Manifolds
|
||||
for (auto manifoldsIter = manifolds.begin(); manifoldsIter != manifolds.end();)
|
||||
{
|
||||
const auto STATE = manifoldsIter->second.state;
|
||||
if (STATE == SHCollisionState::INVALID || STATE == SHCollisionState::EXIT)
|
||||
manifoldsIter = manifolds.erase(manifoldsIter);
|
||||
else
|
||||
++manifoldsIter;
|
||||
}
|
||||
|
||||
// Triggers
|
||||
for (auto triggersIter = triggers.begin(); triggersIter != triggers.end();)
|
||||
{
|
||||
const auto STATE = triggersIter->second.state;
|
||||
if (STATE == SHCollisionState::INVALID || STATE == SHCollisionState::EXIT)
|
||||
triggersIter = triggers.erase(triggersIter);
|
||||
else
|
||||
++triggersIter;
|
||||
}
|
||||
}
|
||||
|
||||
void SHContactManager::Update() noexcept
|
||||
{
|
||||
// Clear expired or invalid collisions. If not, test collision.
|
||||
for (auto manifoldPair = manifolds.begin(); manifoldPair != manifolds.end();)
|
||||
{
|
||||
// Test collision of every manifold.
|
||||
SHManifold& manifold = manifoldPair->second;
|
||||
SHManifold& manifold = manifoldPair->second;
|
||||
SHManifold oldManifold = manifold;
|
||||
|
||||
const bool IS_COLLIDING = SHCollisionDispatcher::Collide(manifold, *manifold.shapeA, *manifold.shapeB);
|
||||
updateCollisionState(IS_COLLIDING, manifold.state);
|
||||
|
||||
auto& collisionState = manifold.state;
|
||||
updateCollisionState(IS_COLLIDING, collisionState);
|
||||
|
||||
const bool IS_INVALID = collisionState == SHCollisionState::INVALID;
|
||||
if (IS_INVALID)
|
||||
// For any false positives
|
||||
if (manifold.state == SHCollisionState::INVALID)
|
||||
{
|
||||
manifoldPair = manifolds.erase(manifoldPair);
|
||||
continue;
|
||||
|
@ -163,19 +180,16 @@ namespace SHADE
|
|||
++manifoldPair;
|
||||
}
|
||||
|
||||
// Clear expired or invalid triggers, If not, test collision.
|
||||
for (auto triggerPair = triggers.begin(); triggerPair != triggers.end();)
|
||||
{
|
||||
// Test collision of every trigger.
|
||||
Trigger& trigger = triggerPair->second;
|
||||
Trigger& trigger = triggerPair->second;
|
||||
|
||||
const bool IS_COLLIDING = SHCollisionDispatcher::Collide(*trigger.A, *trigger.B);
|
||||
updateCollisionState(IS_COLLIDING, trigger.state);
|
||||
|
||||
auto& collisionState = trigger.state;
|
||||
updateCollisionState(IS_COLLIDING, collisionState);
|
||||
|
||||
const bool IS_INVALID = collisionState == SHCollisionState::INVALID;
|
||||
if (IS_INVALID)
|
||||
// For any false positives
|
||||
if (trigger.state == SHCollisionState::INVALID)
|
||||
triggerPair = triggers.erase(triggerPair);
|
||||
else
|
||||
++triggerPair;
|
||||
|
@ -238,7 +252,11 @@ namespace SHADE
|
|||
{
|
||||
// New states start at invalid. In the first frame of collision, move to enter.
|
||||
// If it already in enter, move to stay
|
||||
state = state == SHCollisionState::INVALID ? SHCollisionState::ENTER : SHCollisionState::STAY;
|
||||
if (state == SHCollisionState::ENTER)
|
||||
state = SHCollisionState::STAY;
|
||||
|
||||
if (state == SHCollisionState::INVALID)
|
||||
state = SHCollisionState::ENTER;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -79,6 +79,12 @@ namespace SHADE
|
|||
void RemoveInvalidatedManifold (EntityID eid) noexcept;
|
||||
void RemoveInvalidatedManifold (EntityID eid, uint32_t shapeIndex) noexcept;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Removes any contact manifold or triggers that are in the exit or invalid state.
|
||||
*/
|
||||
void RemoveExpiredContacts () noexcept;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Removes any invalidated contacts and triggers, then performs narrowphase collision
|
||||
|
|
|
@ -86,13 +86,19 @@ namespace SHADE
|
|||
|
||||
void SHPhysicsWorld::Step(float dt)
|
||||
{
|
||||
|
||||
|
||||
/*
|
||||
* Detect Collisions
|
||||
*/
|
||||
|
||||
contactManager.RemoveExpiredContacts();
|
||||
|
||||
if (collisionSpace)
|
||||
collisionSpace->DetectCollisions();
|
||||
|
||||
// TODO: Build Islands
|
||||
|
||||
/*
|
||||
* Integrate Forces
|
||||
*/
|
||||
|
@ -106,7 +112,6 @@ namespace SHADE
|
|||
integrateForces(*rigidBody, dt);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Resolve Contacts
|
||||
*/
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Editor/SHEditor.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Physics/System/SHPhysicsSystem.h"
|
||||
|
@ -36,7 +37,6 @@ namespace SHADE
|
|||
|
||||
void SHPhysicsDebugDrawSystem::PhysicsDebugDraw::Execute(double) noexcept
|
||||
{
|
||||
#ifdef SHEDITOR
|
||||
auto* physicsDebugDrawSystem = reinterpret_cast<SHPhysicsDebugDrawSystem*>(GetSystem());
|
||||
|
||||
if (!physicsDebugDrawSystem->IsDebugDrawActive())
|
||||
|
@ -86,17 +86,22 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
if (DRAW_RAYCASTS)
|
||||
{
|
||||
const SHColour& RAY_COLOUR = physicsDebugDrawSystem->DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(Colours::RAYCAST)];
|
||||
#ifdef SHEDITOR
|
||||
if (DRAW_RAYCASTS)
|
||||
{
|
||||
const SHColour& RAY_COLOUR = physicsDebugDrawSystem->DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(Colours::RAYCAST)];
|
||||
|
||||
const auto& RAYS = physicsSystem->raycastHits;
|
||||
for (const auto& hit : RAYS)
|
||||
debugDrawSystem->DrawLine(hit.start, hit.end, RAY_COLOUR, true);
|
||||
auto& rays = physicsSystem->raycastHits;
|
||||
for (const auto& hit : rays)
|
||||
debugDrawSystem->DrawLine(hit.start, hit.end, RAY_COLOUR, true);
|
||||
|
||||
// Clear rays for the physics system
|
||||
physicsSystem->raycastHits.clear();
|
||||
}
|
||||
// Clear the raycast hit container only in play mode.
|
||||
// No other raycasts are assumed to be done in pause or stop mode.
|
||||
const auto EDITOR_STATE = SHSystemManager::GetSystem<SHEditor>()->editorState;
|
||||
if (EDITOR_STATE == SHEditor::State::PLAY)
|
||||
rays.clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (DRAW_BROADPHASE)
|
||||
{
|
||||
|
@ -110,7 +115,6 @@ namespace SHADE
|
|||
debugDrawSystem->DrawWireCube(TRS, AABB_COLOUR);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace SHADE
|
|||
|
||||
void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept
|
||||
{
|
||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
||||
|
||||
if (scriptingSystem == nullptr)
|
||||
|
@ -93,10 +93,6 @@ namespace SHADE
|
|||
*/
|
||||
}
|
||||
}
|
||||
|
||||
// Collision & Trigger messages
|
||||
if (scriptingSystem != nullptr)
|
||||
scriptingSystem->ExecuteCollisionFunctions();
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
||||
|
|
|
@ -35,10 +35,10 @@ namespace SHADE
|
|||
{
|
||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||
|
||||
auto* scriptEngine = SHSystemManager::GetSystem<SHScriptEngine>();
|
||||
if (!scriptEngine)
|
||||
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
||||
if (!scriptingSystem)
|
||||
{
|
||||
SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing ScriptEngine!")
|
||||
SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!")
|
||||
}
|
||||
|
||||
const double FIXED_DT = physicsSystem->fixedDT;
|
||||
|
@ -47,12 +47,15 @@ namespace SHADE
|
|||
int count = 0;
|
||||
while (accumulatedTime > FIXED_DT)
|
||||
{
|
||||
if (scriptEngine)
|
||||
scriptEngine->ExecuteFixedUpdates();
|
||||
if (scriptingSystem)
|
||||
scriptingSystem->ExecuteFixedUpdates();
|
||||
|
||||
if (physicsSystem->physicsWorld)
|
||||
physicsSystem->physicsWorld->Step(static_cast<float>(FIXED_DT));
|
||||
|
||||
if (scriptingSystem != nullptr)
|
||||
scriptingSystem->ExecuteCollisionFunctions();
|
||||
|
||||
accumulatedTime -= FIXED_DT;
|
||||
++count;
|
||||
}
|
||||
|
|
|
@ -287,6 +287,11 @@ namespace SHADE
|
|||
collisionSpace->RemoveCollider(PHYSICS_OBJECT.collider);
|
||||
}
|
||||
|
||||
#ifdef SHEDITOR
|
||||
// HACK: Editor stop always goes into scene exit
|
||||
raycastHits.clear();
|
||||
#endif
|
||||
|
||||
delete collisionSpace;
|
||||
collisionSpace = nullptr;
|
||||
|
||||
|
|
Loading…
Reference in New Issue