Slight refactor to fix collision states for very fast moving objects
This commit is contained in:
parent
b58b475c04
commit
265a5bece8
|
@ -4,8 +4,8 @@
|
||||||
NumberOfChildren: 0
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
Transform Component:
|
Transform Component:
|
||||||
Translate: {x: 0, y: 3, z: 0}
|
Translate: {x: 0, y: 0.0579863191, z: 0}
|
||||||
Rotate: {x: 0, y: 0, z: -0}
|
Rotate: {x: -0, y: 0, z: -0}
|
||||||
Scale: {x: 1, y: 1, z: 1}
|
Scale: {x: 1, y: 1, z: 1}
|
||||||
IsActive: true
|
IsActive: true
|
||||||
RigidBody Component:
|
RigidBody Component:
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
Drag: 1
|
Drag: 1
|
||||||
Angular Drag: 1
|
Angular Drag: 1
|
||||||
Use Gravity: true
|
Use Gravity: true
|
||||||
Gravity Scale: 1
|
Gravity Scale: 10
|
||||||
Interpolate: true
|
Interpolate: true
|
||||||
Sleeping Enabled: true
|
Sleeping Enabled: true
|
||||||
Freeze Position X: false
|
Freeze Position X: false
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
NumberOfChildren: 0
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
Camera Component:
|
Camera Component:
|
||||||
Position: {x: 0, y: 2, z: 3}
|
Position: {x: 0, y: 0.5, z: 2}
|
||||||
Pitch: 0
|
Pitch: 0
|
||||||
Yaw: 0
|
Yaw: 0
|
||||||
Roll: 0
|
Roll: 0
|
||||||
|
|
|
@ -25,6 +25,23 @@ namespace SHADE
|
||||||
struct SH_API SHManifold
|
struct SH_API SHManifold
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHManifold (SHCollisionShape* a, SHCollisionShape* b) noexcept;
|
||||||
|
SHManifold (const SHManifold& rhs) noexcept;
|
||||||
|
SHManifold (SHManifold&& rhs) noexcept;
|
||||||
|
|
||||||
|
~SHManifold () noexcept = default;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Operator Overloads */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHManifold& operator=(const SHManifold& rhs) noexcept;
|
||||||
|
SHManifold& operator=(SHManifold&& rhs) noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -32,8 +49,8 @@ namespace SHADE
|
||||||
// We only need 4 contact points to build a stable manifold.
|
// We only need 4 contact points to build a stable manifold.
|
||||||
static constexpr int MAX_NUM_CONTACTS = 4;
|
static constexpr int MAX_NUM_CONTACTS = 4;
|
||||||
|
|
||||||
SHCollisionShape* A = nullptr;
|
SHCollisionShape* A;
|
||||||
SHCollisionShape* B = nullptr;
|
SHCollisionShape* B;
|
||||||
|
|
||||||
uint32_t numContacts = 0;
|
uint32_t numContacts = 0;
|
||||||
SHCollisionState state = SHCollisionState::INVALID;
|
SHCollisionState state = SHCollisionState::INVALID;
|
||||||
|
@ -44,4 +61,7 @@ namespace SHADE
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace SHADE
|
||||||
|
|
||||||
|
#include "SHManifold.hpp"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHManifold.h
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Interface for a Collision Manifold
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Primary Header
|
||||||
|
#include "SHManifold.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
inline SHManifold::SHManifold(SHCollisionShape* a, SHCollisionShape* b) noexcept
|
||||||
|
: A { a }
|
||||||
|
, B { b }
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline SHManifold::SHManifold(const SHManifold& rhs) noexcept
|
||||||
|
: A { rhs.A }
|
||||||
|
, B { rhs.B }
|
||||||
|
, numContacts { rhs.numContacts }
|
||||||
|
, state { rhs.state }
|
||||||
|
, normal { rhs.normal }
|
||||||
|
{
|
||||||
|
for (int i = 0; i < SHContact::NUM_TANGENTS; ++i)
|
||||||
|
tangents[i] = rhs.tangents[i];
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUM_CONTACTS; ++i)
|
||||||
|
{
|
||||||
|
contacts[i].penetration = rhs.contacts[i].penetration;
|
||||||
|
contacts[i].bias = rhs.contacts[i].bias;
|
||||||
|
contacts[i].normalImpulse = rhs.contacts[i].normalImpulse;
|
||||||
|
contacts[i].normalMass = rhs.contacts[i].normalMass;
|
||||||
|
|
||||||
|
for (int j = 0; j < SHContact::NUM_TANGENTS; ++j)
|
||||||
|
{
|
||||||
|
contacts[i].tangentImpulse[j] = rhs.contacts[i].tangentImpulse[j];
|
||||||
|
contacts[i].tangentMass[j] = rhs.contacts[i].tangentMass[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
contacts[i].position = rhs.contacts[i].position;
|
||||||
|
contacts[i].featurePair.key = rhs.contacts[i].featurePair.key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline SHManifold::SHManifold(SHManifold&& rhs) noexcept
|
||||||
|
: A { rhs.A }
|
||||||
|
, B { rhs.B }
|
||||||
|
, numContacts { rhs.numContacts }
|
||||||
|
, state { rhs.state }
|
||||||
|
, normal { rhs.normal }
|
||||||
|
{
|
||||||
|
for (int i = 0; i < SHContact::NUM_TANGENTS; ++i)
|
||||||
|
tangents[i] = rhs.tangents[i];
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUM_CONTACTS; ++i)
|
||||||
|
{
|
||||||
|
contacts[i].penetration = rhs.contacts[i].penetration;
|
||||||
|
contacts[i].bias = rhs.contacts[i].bias;
|
||||||
|
contacts[i].normalImpulse = rhs.contacts[i].normalImpulse;
|
||||||
|
contacts[i].normalMass = rhs.contacts[i].normalMass;
|
||||||
|
|
||||||
|
for (int j = 0; j < SHContact::NUM_TANGENTS; ++j)
|
||||||
|
{
|
||||||
|
contacts[i].tangentImpulse[j] = rhs.contacts[i].tangentImpulse[j];
|
||||||
|
contacts[i].tangentMass[j] = rhs.contacts[i].tangentMass[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
contacts[i].position = rhs.contacts[i].position;
|
||||||
|
contacts[i].featurePair.key = rhs.contacts[i].featurePair.key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Operator Overload Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
inline SHManifold& SHManifold::operator=(const SHManifold& rhs) noexcept
|
||||||
|
{
|
||||||
|
if (this == &rhs)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
A = rhs.A;
|
||||||
|
B = rhs.B;
|
||||||
|
numContacts = rhs.numContacts;
|
||||||
|
state = rhs.state;
|
||||||
|
normal = rhs.normal;
|
||||||
|
|
||||||
|
for (int i = 0; i < SHContact::NUM_TANGENTS; ++i)
|
||||||
|
tangents[i] = rhs.tangents[i];
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUM_CONTACTS; ++i)
|
||||||
|
{
|
||||||
|
contacts[i].penetration = rhs.contacts[i].penetration;
|
||||||
|
contacts[i].bias = rhs.contacts[i].bias;
|
||||||
|
contacts[i].normalImpulse = rhs.contacts[i].normalImpulse;
|
||||||
|
contacts[i].normalMass = rhs.contacts[i].normalMass;
|
||||||
|
|
||||||
|
for (int j = 0; j < SHContact::NUM_TANGENTS; ++j)
|
||||||
|
{
|
||||||
|
contacts[i].tangentImpulse[j] = rhs.contacts[i].tangentImpulse[j];
|
||||||
|
contacts[i].tangentMass[j] = rhs.contacts[i].tangentMass[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
contacts[i].position = rhs.contacts[i].position;
|
||||||
|
contacts[i].featurePair.key = rhs.contacts[i].featurePair.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline SHManifold& SHManifold::operator=(SHManifold&& rhs) noexcept
|
||||||
|
{
|
||||||
|
A = rhs.A;
|
||||||
|
B = rhs.B;
|
||||||
|
numContacts = rhs.numContacts;
|
||||||
|
state = rhs.state;
|
||||||
|
normal = rhs.normal;
|
||||||
|
|
||||||
|
for (int i = 0; i < SHContact::NUM_TANGENTS; ++i)
|
||||||
|
tangents[i] = rhs.tangents[i];
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUM_CONTACTS; ++i)
|
||||||
|
{
|
||||||
|
contacts[i].penetration = rhs.contacts[i].penetration;
|
||||||
|
contacts[i].bias = rhs.contacts[i].bias;
|
||||||
|
contacts[i].normalImpulse = rhs.contacts[i].normalImpulse;
|
||||||
|
contacts[i].normalMass = rhs.contacts[i].normalMass;
|
||||||
|
|
||||||
|
for (int j = 0; j < SHContact::NUM_TANGENTS; ++j)
|
||||||
|
{
|
||||||
|
contacts[i].tangentImpulse[j] = rhs.contacts[i].tangentImpulse[j];
|
||||||
|
contacts[i].tangentMass[j] = rhs.contacts[i].tangentMass[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
contacts[i].position = rhs.contacts[i].position;
|
||||||
|
contacts[i].featurePair.key = rhs.contacts[i].featurePair.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
} // namespace SHADE
|
|
@ -102,6 +102,8 @@ namespace SHADE
|
||||||
|
|
||||||
void SHCollisionSpace::DetectCollisions() noexcept
|
void SHCollisionSpace::DetectCollisions() noexcept
|
||||||
{
|
{
|
||||||
|
// TODO: Profile broad-phase and narrow-phase
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Broad-phase
|
* Broad-phase
|
||||||
*/
|
*/
|
||||||
|
@ -112,11 +114,14 @@ namespace SHADE
|
||||||
// Colliders without bodies are considered to be static bodies
|
// Colliders without bodies are considered to be static bodies
|
||||||
// This is specific to this engine because of Unity's stupid convention.
|
// This is specific to this engine because of Unity's stupid convention.
|
||||||
const bool IS_IMPLICIT_STATIC = !collider->rigidBody;
|
const bool IS_IMPLICIT_STATIC = !collider->rigidBody;
|
||||||
const bool IS_EXPLICIT_STATIC = collider->rigidBody->GetType() == SHRigidBody::Type::STATIC;
|
|
||||||
const bool IS_ACTIVE = collider->active;
|
const bool IS_ACTIVE = collider->active;
|
||||||
|
|
||||||
// Skip inactive colliders
|
// Skip inactive colliders
|
||||||
if (!IS_ACTIVE || IS_IMPLICIT_STATIC || IS_EXPLICIT_STATIC)
|
if (!IS_ACTIVE || IS_IMPLICIT_STATIC)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const bool IS_EXPLICIT_STATIC = collider->rigidBody->GetType() == SHRigidBody::Type::STATIC;
|
||||||
|
if (IS_EXPLICIT_STATIC)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// All remaining are kinematic or dynamic
|
// All remaining are kinematic or dynamic
|
||||||
|
@ -149,6 +154,10 @@ namespace SHADE
|
||||||
|
|
||||||
// Clear every frame
|
// Clear every frame
|
||||||
narrowphaseBatch.clear();
|
narrowphaseBatch.clear();
|
||||||
|
|
||||||
|
// Test all collisions
|
||||||
|
if (contactManager)
|
||||||
|
contactManager->Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -198,14 +207,12 @@ namespace SHADE
|
||||||
|
|
||||||
void SHCollisionSpace::collideTriggers(const SHCollisionKey& key, NarrowphasePair& narrowphasePair) const noexcept
|
void SHCollisionSpace::collideTriggers(const SHCollisionKey& key, NarrowphasePair& narrowphasePair) const noexcept
|
||||||
{
|
{
|
||||||
const auto* A = narrowphasePair.A;
|
auto* A = narrowphasePair.A;
|
||||||
const auto* B = narrowphasePair.B;
|
auto* B = narrowphasePair.B;
|
||||||
|
|
||||||
const bool COLLIDING = SHCollisionDispatcher::Collide(*A, *B);
|
// Send to contact manager
|
||||||
|
|
||||||
// Send results to contact manager
|
|
||||||
if (contactManager)
|
if (contactManager)
|
||||||
contactManager->AddTrigger(COLLIDING, key);
|
contactManager->AddTrigger(key, A, B);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCollisionSpace::collideManifolds(const SHCollisionKey& key, NarrowphasePair& narrowphasePair) const noexcept
|
void SHCollisionSpace::collideManifolds(const SHCollisionKey& key, NarrowphasePair& narrowphasePair) const noexcept
|
||||||
|
@ -213,11 +220,8 @@ namespace SHADE
|
||||||
auto* A = narrowphasePair.A;
|
auto* A = narrowphasePair.A;
|
||||||
auto* B = narrowphasePair.B;
|
auto* B = narrowphasePair.B;
|
||||||
|
|
||||||
SHManifold newManifold { .A = A, .B = B };
|
// Send to contact manager
|
||||||
const bool COLLIDING = SHCollisionDispatcher::Collide(newManifold, *A, *B);
|
|
||||||
|
|
||||||
// Send results to contact manager
|
|
||||||
if (contactManager)
|
if (contactManager)
|
||||||
contactManager->AddManifold(COLLIDING, key, newManifold);
|
contactManager->AddManifold(key, A, B);
|
||||||
}
|
}
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -14,6 +14,9 @@
|
||||||
// Primary Header
|
// Primary Header
|
||||||
#include "SHContactManager.h"
|
#include "SHContactManager.h"
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "Physics/Collision/Narrowphase/SHCollisionDispatch.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -26,8 +29,8 @@ namespace SHADE
|
||||||
|
|
||||||
triggerEvents.clear();
|
triggerEvents.clear();
|
||||||
|
|
||||||
for (auto& [id, state] : triggers)
|
for (auto& [id, trigger] : triggers)
|
||||||
triggerEvents.emplace_back(SHTriggerEvent{ id, state });
|
triggerEvents.emplace_back(SHTriggerEvent{ id, trigger.state });
|
||||||
|
|
||||||
return triggerEvents;
|
return triggerEvents;
|
||||||
}
|
}
|
||||||
|
@ -62,92 +65,83 @@ namespace SHADE
|
||||||
|
|
||||||
void SHContactManager::Update() noexcept
|
void SHContactManager::Update() noexcept
|
||||||
{
|
{
|
||||||
// Clear expired or invalid collisions
|
// Clear expired or invalid collisions. If not, test collision.
|
||||||
for (auto manifold = manifolds.begin(); manifold != manifolds.end();)
|
for (auto manifoldPair = manifolds.begin(); manifoldPair != manifolds.end();)
|
||||||
{
|
{
|
||||||
const auto COLLISION_STATE = manifold->second.state;
|
// Test collision of every manifold.
|
||||||
|
SHManifold& oldManifold = manifoldPair->second;
|
||||||
|
SHManifold newManifold = oldManifold;
|
||||||
|
|
||||||
const bool IS_EXIT = COLLISION_STATE == SHCollisionState::EXIT;
|
const bool IS_COLLIDING = SHCollisionDispatcher::Collide(newManifold, *newManifold.A, *newManifold.B);
|
||||||
const bool IS_INVALID = COLLISION_STATE == SHCollisionState::INVALID;
|
|
||||||
|
|
||||||
if (IS_EXIT || IS_INVALID)
|
auto& collisionState = newManifold.state;
|
||||||
manifold = manifolds.erase(manifold);
|
updateCollisionState(IS_COLLIDING, collisionState);
|
||||||
else
|
|
||||||
++manifold;
|
const bool IS_INVALID = collisionState == SHCollisionState::INVALID;
|
||||||
|
if (IS_INVALID)
|
||||||
|
{
|
||||||
|
manifoldPair = manifolds.erase(manifoldPair);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateManifold(oldManifold, newManifold);
|
||||||
|
++manifoldPair;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear expired or invalid triggers
|
// Clear expired or invalid triggers, If not, test collision.
|
||||||
for (auto trigger = triggers.begin(); trigger != triggers.end();)
|
for (auto triggerPair = triggers.begin(); triggerPair != triggers.end();)
|
||||||
{
|
{
|
||||||
const auto COLLISION_STATE = trigger->second;
|
// Test collision of every trigger.
|
||||||
|
Trigger& oldTrigger = triggerPair->second;
|
||||||
|
Trigger newTrigger = oldTrigger;
|
||||||
|
|
||||||
const bool IS_EXIT = COLLISION_STATE == SHCollisionState::EXIT;
|
const bool IS_COLLIDING = SHCollisionDispatcher::Collide(*newTrigger.A, *newTrigger.B);
|
||||||
const bool IS_INVALID = COLLISION_STATE == SHCollisionState::INVALID;
|
|
||||||
|
|
||||||
if (IS_EXIT || IS_INVALID)
|
auto& collisionState = newTrigger.state;
|
||||||
trigger = triggers.erase(trigger);
|
updateCollisionState(IS_COLLIDING, collisionState);
|
||||||
|
|
||||||
|
const bool IS_INVALID = collisionState == SHCollisionState::INVALID;
|
||||||
|
if (IS_INVALID)
|
||||||
|
triggerPair = triggers.erase(triggerPair);
|
||||||
else
|
else
|
||||||
++trigger;
|
++triggerPair;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHContactManager::AddTrigger(bool isColliding, const SHCollisionKey& key) noexcept
|
void SHContactManager::AddTrigger(const SHCollisionKey& key, SHCollisionShape* A, SHCollisionShape* B) noexcept
|
||||||
{
|
{
|
||||||
|
// If id not found, emplace new trigger.
|
||||||
auto trigger = triggers.find(key);
|
auto trigger = triggers.find(key);
|
||||||
|
|
||||||
// If id not found, emplace new object.
|
|
||||||
// New object is in the invalid state
|
|
||||||
if (trigger == triggers.end())
|
if (trigger == triggers.end())
|
||||||
trigger = triggers.emplace(key, SHCollisionState::INVALID).first;
|
triggers.emplace(key, Trigger{ A, B, SHCollisionState::INVALID }).first;
|
||||||
|
|
||||||
SHCollisionState& state = trigger->second;
|
|
||||||
updateCollisionState(isColliding, state);
|
|
||||||
|
|
||||||
// If it was a false positive, remove the manifold immediately.
|
|
||||||
// Remove using iterator as it is on average faster.
|
|
||||||
if (state == SHCollisionState::INVALID)
|
|
||||||
trigger = triggers.erase(trigger);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHContactManager::AddManifold(bool isColliding, const SHCollisionKey& key, const SHManifold& newManifold) noexcept
|
void SHContactManager::AddManifold(const SHCollisionKey& key, SHCollisionShape* A, SHCollisionShape* B) noexcept
|
||||||
{
|
{
|
||||||
auto manifold = manifolds.find(key);
|
|
||||||
|
|
||||||
// If id not found, emplace new manifold
|
// If id not found, emplace new manifold
|
||||||
|
auto manifold = manifolds.find(key);
|
||||||
if (manifold == manifolds.end())
|
if (manifold == manifolds.end())
|
||||||
manifold = manifolds.emplace(key, newManifold).first;
|
manifolds.emplace(key, SHManifold{ A, B }).first;
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO: Update existing manifolds with new data
|
|
||||||
}
|
|
||||||
|
|
||||||
SHCollisionState& state = manifold->second.state;
|
|
||||||
updateCollisionState(isColliding, state);
|
|
||||||
|
|
||||||
// If it was a false positive, remove the manifold immediately.
|
|
||||||
// Remove using iterator as it is on average faster.
|
|
||||||
if (state == SHCollisionState::INVALID)
|
|
||||||
manifold = manifolds.erase(manifold);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHContactManager::RemoveInvalidatedTrigger(EntityID eid) noexcept
|
void SHContactManager::RemoveInvalidatedTrigger(EntityID eid) noexcept
|
||||||
{
|
{
|
||||||
remove(triggers, eid);
|
removeInvalidObject(triggers, eid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHContactManager::RemoveInvalidatedTrigger(EntityID eid, uint32_t shapeIndex) noexcept
|
void SHContactManager::RemoveInvalidatedTrigger(EntityID eid, uint32_t shapeIndex) noexcept
|
||||||
{
|
{
|
||||||
remove(triggers, eid, shapeIndex);
|
removeInvalidObject(triggers, eid, shapeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHContactManager::RemoveInvalidatedManifold(EntityID eid) noexcept
|
void SHContactManager::RemoveInvalidatedManifold(EntityID eid) noexcept
|
||||||
{
|
{
|
||||||
remove(manifolds, eid);
|
removeInvalidObject(manifolds, eid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHContactManager::RemoveInvalidatedManifold(EntityID eid, uint32_t shapeIndex) noexcept
|
void SHContactManager::RemoveInvalidatedManifold(EntityID eid, uint32_t shapeIndex) noexcept
|
||||||
{
|
{
|
||||||
remove(manifolds, eid, shapeIndex);
|
removeInvalidObject(manifolds, eid, shapeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -164,10 +158,26 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// New states start at invalid. In false positive, remain unchanged.
|
// If already exited and still not colliding, the collision has expired.
|
||||||
|
// Invalid states are removed in the next frame
|
||||||
|
if (state == SHCollisionState::EXIT)
|
||||||
|
state = SHCollisionState::INVALID;
|
||||||
|
|
||||||
// If previously colliding, move to exit.
|
// If previously colliding, move to exit.
|
||||||
state = state == SHCollisionState::INVALID ? SHCollisionState::INVALID : SHCollisionState::EXIT;
|
if (state == SHCollisionState::ENTER || state == SHCollisionState::STAY)
|
||||||
|
state = SHCollisionState::EXIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHContactManager::updateManifold(SHManifold& oldManifold, SHManifold& newManifold) noexcept
|
||||||
|
{
|
||||||
|
oldManifold.state = newManifold.state;
|
||||||
|
|
||||||
|
// Early out since exiting a collision does not require an update beyond updating the state
|
||||||
|
if (newManifold.state == SHCollisionState::EXIT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -54,26 +54,35 @@ namespace SHADE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
* Removes any invalidated contacts and triggers.
|
* Removes any invalidated contacts and triggers, then performs narrowphase collision
|
||||||
|
* detection on existing triggers and manifolds.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
void Update () noexcept;
|
void Update () noexcept;
|
||||||
|
|
||||||
void AddTrigger (bool isColliding, const SHCollisionKey& key) noexcept;
|
void AddTrigger (const SHCollisionKey& key, SHCollisionShape* A, SHCollisionShape* B) noexcept;
|
||||||
void AddManifold (bool isColliding, const SHCollisionKey& key, const SHManifold& newManifold) noexcept;
|
void AddManifold (const SHCollisionKey& key, SHCollisionShape* A, SHCollisionShape* B) noexcept;
|
||||||
|
|
||||||
void RemoveInvalidatedTrigger (EntityID eid) noexcept;
|
void RemoveInvalidatedTrigger (EntityID eid) noexcept;
|
||||||
void RemoveInvalidatedTrigger (EntityID eid, uint32_t shapeIndex) noexcept;
|
void RemoveInvalidatedTrigger (EntityID eid, uint32_t shapeIndex) noexcept;
|
||||||
void RemoveInvalidatedManifold (EntityID eid) noexcept;
|
void RemoveInvalidatedManifold (EntityID eid) noexcept;
|
||||||
void RemoveInvalidatedManifold (EntityID eid, uint32_t shapeIndex) noexcept;
|
void RemoveInvalidatedManifold (EntityID eid, uint32_t shapeIndex) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
struct Trigger
|
||||||
|
{
|
||||||
|
SHCollisionShape* A = nullptr;
|
||||||
|
SHCollisionShape* B = nullptr;
|
||||||
|
|
||||||
|
SHCollisionState state = SHCollisionState::INVALID;
|
||||||
|
};
|
||||||
|
|
||||||
using Manifolds = std::unordered_map<SHCollisionKey, SHManifold, SHCollisionKeyHash>;
|
using Manifolds = std::unordered_map<SHCollisionKey, SHManifold, SHCollisionKeyHash>;
|
||||||
using Triggers = std::unordered_map<SHCollisionKey, SHCollisionState, SHCollisionKeyHash>;
|
using Triggers = std::unordered_map<SHCollisionKey, Trigger, SHCollisionKeyHash>;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
|
@ -86,14 +95,15 @@ namespace SHADE
|
||||||
/* Member Functions */
|
/* Member Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void updateCollisionState (bool isColliding, SHCollisionState& state) noexcept;
|
static void updateCollisionState (bool isColliding, SHCollisionState& state) noexcept;
|
||||||
|
static void updateManifold (SHManifold& oldManifold, SHManifold& newManifold) noexcept;
|
||||||
|
|
||||||
// Removal Helpers
|
// Removal Helpers
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void remove (std::unordered_map<SHCollisionKey, T, SHCollisionKeyHash>& container, EntityID eid);
|
static void removeInvalidObject (std::unordered_map<SHCollisionKey, T, SHCollisionKeyHash>& container, EntityID eid) noexcept;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void remove (std::unordered_map<SHCollisionKey, T, SHCollisionKeyHash>& container, EntityID eid, uint32_t shapeIndex);
|
static void removeInvalidObject (std::unordered_map<SHCollisionKey, T, SHCollisionKeyHash>& container, EntityID eid, uint32_t shapeIndex) noexcept;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void SHContactManager::remove(std::unordered_map<SHCollisionKey, T, SHCollisionKeyHash>& container, EntityID eid)
|
void SHContactManager::removeInvalidObject(std::unordered_map<SHCollisionKey, T, SHCollisionKeyHash>& container, EntityID eid) noexcept
|
||||||
{
|
{
|
||||||
if (container.empty())
|
if (container.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -40,7 +40,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void SHContactManager::remove(std::unordered_map<SHCollisionKey, T, SHCollisionKeyHash>& container, EntityID eid, uint32_t shapeIndex)
|
void SHContactManager::removeInvalidObject(std::unordered_map<SHCollisionKey, T, SHCollisionKeyHash>& container, EntityID eid, uint32_t shapeIndex) noexcept
|
||||||
{
|
{
|
||||||
if (container.empty())
|
if (container.empty())
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -81,9 +81,6 @@ namespace SHADE
|
||||||
|
|
||||||
void SHPhysicsWorld::Step(float dt)
|
void SHPhysicsWorld::Step(float dt)
|
||||||
{
|
{
|
||||||
// Contact manager to clear expired contacts
|
|
||||||
contactManager.Update();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Detect Collisions
|
* Detect Collisions
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue