Implemented a custom physics engine #316

Merged
direnbharwani merged 95 commits from SHPhysics into main 2023-01-23 15:55:45 +08:00
17 changed files with 482 additions and 95 deletions
Showing only changes of commit af3a5e7dc9 - Show all commits

View File

@ -26,6 +26,7 @@
Freeze Rotation Z: false Freeze Rotation Z: false
IsActive: true IsActive: true
Collider Component: Collider Component:
DrawColliders: true
Colliders: Colliders:
- Is Trigger: false - Is Trigger: false
Type: Sphere Type: Sphere

View File

@ -31,6 +31,7 @@
#include "Input/SHInputManager.h" #include "Input/SHInputManager.h"
#include "Math/Transform/SHTransformSystem.h" #include "Math/Transform/SHTransformSystem.h"
#include "Physics/System/SHPhysicsSystem.h" #include "Physics/System/SHPhysicsSystem.h"
#include "Physics/System/SHPhysicsDebugDrawSystem.h"
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
#include "UI/SHUISystem.h" #include "UI/SHUISystem.h"
@ -83,7 +84,6 @@ namespace Sandbox
SHSystemManager::CreateSystem<SHGraphicsSystem>(); SHSystemManager::CreateSystem<SHGraphicsSystem>();
SHGraphicsSystem* graphicsSystem = static_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>()); SHGraphicsSystem* graphicsSystem = static_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>());
SHPhysicsSystem* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
// Link up SHDebugDraw // Link up SHDebugDraw
SHSystemManager::CreateSystem<SHDebugDrawSystem>(); SHSystemManager::CreateSystem<SHDebugDrawSystem>();
@ -98,6 +98,8 @@ namespace Sandbox
editor->SetSDLWindow(sdlWindow); editor->SetSDLWindow(sdlWindow);
editor->SetSHWindow(&window); editor->SetSHWindow(&window);
} }
SHSystemManager::CreateSystem<SHPhysicsDebugDrawSystem>();
#endif #endif
// Create Routines // Create Routines
@ -111,8 +113,9 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
#ifdef SHEDITOR #ifdef SHEDITOR
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsDebugDraw>(); SHSystemManager::RegisterRoutine<SHPhysicsDebugDrawSystem, SHPhysicsDebugDrawSystem::PhysicsDebugDraw>();
#endif #endif
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>(); SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();

View File

@ -322,8 +322,7 @@ namespace SHADE
{ {
DrawContextMenu(component); DrawContextMenu(component);
auto* collider = component->GetCollider(); SHEditorWidgets::CheckBox("Draw Colliders", [component] { return component->GetDebugDrawState(); }, [component](bool value) { component->SetDebugDrawState(value); });
SHEditorWidgets::CheckBox("Draw Colliders", [collider] { return collider->GetDebugDrawState(); }, [collider](bool value) { collider->SetDebugDrawState(value); });
auto* collisionShapes = component->GetCollisionShapes(); auto* collisionShapes = component->GetCollisionShapes();
int const size = collisionShapes ? static_cast<int>(collisionShapes->size()) : 0; int const size = collisionShapes ? static_cast<int>(collisionShapes->size()) : 0;

View File

@ -10,16 +10,18 @@ constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT { 1 };
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 }; constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 };
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 }; constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 };
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 }; constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 }; constexpr SHEventIdentifier SH_SCENE_INIT_PRE { 5 };
constexpr SHEventIdentifier SH_SCENEGRAPH_ADD_CHILD_EVENT { 6 }; constexpr SHEventIdentifier SH_SCENE_INIT_POST { 6 };
constexpr SHEventIdentifier SH_SCENEGRAPH_REMOVE_CHILD_EVENT { 7 }; constexpr SHEventIdentifier SH_SCENE_EXIT_PRE { 7 };
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 8 }; constexpr SHEventIdentifier SH_SCENE_EXIT_POST { 8 };
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 9 }; constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 9 };
constexpr SHEventIdentifier SH_EDITOR_ON_PLAY_EVENT { 10 }; constexpr SHEventIdentifier SH_SCENEGRAPH_ADD_CHILD_EVENT { 10 };
constexpr SHEventIdentifier SH_EDITOR_ON_PAUSE_EVENT { 11 }; constexpr SHEventIdentifier SH_SCENEGRAPH_REMOVE_CHILD_EVENT { 11 };
constexpr SHEventIdentifier SH_EDITOR_ON_STOP_EVENT { 12 }; constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 12 };
constexpr SHEventIdentifier SH_SCENE_INIT_PRE { 13 }; constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 13 };
constexpr SHEventIdentifier SH_SCENE_INIT_POST { 14 }; constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_DRAW_EVENT { 14 };
constexpr SHEventIdentifier SH_SCENE_EXIT_PRE { 15 }; constexpr SHEventIdentifier SH_EDITOR_ON_PLAY_EVENT { 15 };
constexpr SHEventIdentifier SH_SCENE_EXIT_POST { 16 }; constexpr SHEventIdentifier SH_EDITOR_ON_PAUSE_EVENT { 16 };
constexpr SHEventIdentifier SH_EDITOR_ON_STOP_EVENT { 17 };

View File

@ -14,7 +14,10 @@
#include "SHCollider.h" #include "SHCollider.h"
// Project Headers // Project Headers
#include "Events/SHEvent.h"
#include "Math/SHMathHelpers.h" #include "Math/SHMathHelpers.h"
#include "Physics/SHPhysicsEvents.h"
namespace SHADE namespace SHADE
{ {
@ -25,9 +28,7 @@ namespace SHADE
SHCollider::SHCollider(EntityID eid, const SHTransform& worldTransform) noexcept SHCollider::SHCollider(EntityID eid, const SHTransform& worldTransform) noexcept
: entityID { eid } : entityID { eid }
, shapeIDCounter { 0 } , shapeIDCounter { 0 }
#ifdef SHEDITOR
, debugDraw { false } , debugDraw { false }
#endif
, rigidBody { nullptr } , rigidBody { nullptr }
, shapeFactory { nullptr } , shapeFactory { nullptr }
, transform { worldTransform } , transform { worldTransform }
@ -38,9 +39,7 @@ namespace SHADE
SHCollider::SHCollider(const SHCollider& rhs) noexcept SHCollider::SHCollider(const SHCollider& rhs) noexcept
: entityID { rhs.entityID } : entityID { rhs.entityID }
, shapeIDCounter { rhs.shapeIDCounter } , shapeIDCounter { rhs.shapeIDCounter }
#ifdef SHEDITOR
, debugDraw { rhs.debugDraw } , debugDraw { rhs.debugDraw }
#endif
, rigidBody { rhs.rigidBody } , rigidBody { rhs.rigidBody }
, shapeFactory { rhs.shapeFactory } , shapeFactory { rhs.shapeFactory }
, transform { rhs.transform } , transform { rhs.transform }
@ -57,9 +56,7 @@ namespace SHADE
SHCollider::SHCollider(SHCollider&& rhs) noexcept SHCollider::SHCollider(SHCollider&& rhs) noexcept
: entityID { rhs.entityID } : entityID { rhs.entityID }
, shapeIDCounter { rhs.shapeIDCounter } , shapeIDCounter { rhs.shapeIDCounter }
#ifdef SHEDITOR
, debugDraw { rhs.debugDraw } , debugDraw { rhs.debugDraw }
#endif
, rigidBody { rhs.rigidBody } , rigidBody { rhs.rigidBody }
, shapeFactory { rhs.shapeFactory } , shapeFactory { rhs.shapeFactory }
, transform { rhs.transform } , transform { rhs.transform }
@ -101,14 +98,11 @@ namespace SHADE
} }
entityID = rhs.entityID; entityID = rhs.entityID;
debugDraw = rhs.debugDraw;
rigidBody = rhs.rigidBody; rigidBody = rhs.rigidBody;
shapeFactory = rhs.shapeFactory; shapeFactory = rhs.shapeFactory;
transform = rhs.transform; transform = rhs.transform;
#ifdef SHEDITOR
debugDraw = rhs.debugDraw;
#endif
copyShapes(rhs); copyShapes(rhs);
return *this; return *this;
@ -123,14 +117,11 @@ namespace SHADE
} }
entityID = rhs.entityID; entityID = rhs.entityID;
debugDraw = rhs.debugDraw;
rigidBody = rhs.rigidBody; rigidBody = rhs.rigidBody;
shapeFactory = rhs.shapeFactory; shapeFactory = rhs.shapeFactory;
transform = rhs.transform; transform = rhs.transform;
#ifdef SHEDITOR
debugDraw = rhs.debugDraw;
#endif
copyShapes(rhs); copyShapes(rhs);
return *this; return *this;
@ -140,12 +131,10 @@ namespace SHADE
/* Getter Function Definitions */ /* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
#ifdef SHEDITOR
bool SHCollider::GetDebugDrawState() const noexcept bool SHCollider::GetDebugDrawState() const noexcept
{ {
return debugDraw; return debugDraw;
} }
#endif
const SHTransform& SHCollider::GetTransform() const noexcept const SHTransform& SHCollider::GetTransform() const noexcept
{ {
@ -186,12 +175,23 @@ namespace SHADE
/* Setter Function Definitions */ /* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
#ifdef SHEDITOR
void SHCollider::SetDebugDrawState(bool state) noexcept void SHCollider::SetDebugDrawState(bool state) noexcept
{ {
debugDraw = state; debugDraw = state;
#ifdef SHEDITOR
// Broadcast event for the Debug Draw system to catch
const SHColliderOnDebugDrawEvent EVENT_DATA
{
.entityID = entityID
, .debugDrawState = debugDraw
};
SHEventManager::BroadcastEvent<SHColliderOnDebugDrawEvent>(EVENT_DATA, SH_PHYSICS_COLLIDER_DRAW_EVENT);
#endif
} }
#endif
void SHCollider::SetRigidBody(SHRigidBody* rb) noexcept void SHCollider::SetRigidBody(SHRigidBody* rb) noexcept
{ {
@ -236,7 +236,7 @@ namespace SHADE
{ {
if (!shapeFactory) if (!shapeFactory)
{ {
SHLOGV_ERROR("Shape factory is unlinked with Composite Collider {}. Unable to add new shape!", entityID) SHLOGV_ERROR("Shape factory is unlinked with Collider {}. Unable to add new shape!", entityID)
return -1; return -1;
} }
@ -266,6 +266,17 @@ namespace SHADE
sphere->rotationOffset = rotOffset; sphere->rotationOffset = rotOffset;
shapes.emplace_back(sphere); shapes.emplace_back(sphere);
// Broadcast Event for adding a shape
const SHPhysicsColliderAddedEvent EVENT_DATA
{
.entityID = entityID
, .colliderType = SHCollisionShape::Type::SPHERE
, .colliderIndex = static_cast<int>(shapes.size())
};
SHEventManager::BroadcastEvent<SHPhysicsColliderAddedEvent>(EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT);
return static_cast<int>(shapes.size()); return static_cast<int>(shapes.size());
} }
@ -273,7 +284,7 @@ namespace SHADE
{ {
if (!shapeFactory) if (!shapeFactory)
{ {
SHLOGV_ERROR("Shape factory is unlinked with Composite Collider {}. Unable to add remove shape!", entityID) SHLOGV_ERROR("Shape factory is unlinked with Collider {}. Unable to add remove shape!", entityID)
return; return;
} }
@ -289,12 +300,22 @@ namespace SHADE
break; break;
} }
const SHPhysicsColliderRemovedEvent EVENT_DATA
{
.entityID = entityID
, .colliderType = (*shapeIter)->GetType()
, .colliderIndex = index
};
shapeFactory->DestroyShape(*shapeIter); shapeFactory->DestroyShape(*shapeIter);
*shapeIter = nullptr; *shapeIter = nullptr;
// Remove the shape from the container to prevent accessing a nullptr // Remove the shape from the container to prevent accessing a nullptr
shapeIter = shapes.erase(shapeIter); shapeIter = shapes.erase(shapeIter);
// Broadcast Event for removing a shape
SHEventManager::BroadcastEvent<SHPhysicsColliderRemovedEvent>(EVENT_DATA, SH_PHYSICS_COLLIDER_REMOVED_EVENT);
SHLOG_INFO_D("Removing Collision Shape {} from Entity {}", index, entityID) SHLOG_INFO_D("Removing Collision Shape {} from Entity {}", index, entityID)
} }
@ -386,6 +407,7 @@ namespace SHADE
const SHMatrix TRS = SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(transform.position); const SHMatrix TRS = SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(transform.position);
const SHVec3 NEW_CENTER = SHVec3::Transform(sphere->positionOffset, TRS); const SHVec3 NEW_CENTER = SHVec3::Transform(sphere->positionOffset, TRS);
sphere->SetCenter(NEW_CENTER); sphere->SetCenter(NEW_CENTER);
} }

View File

@ -78,9 +78,7 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
#ifdef SHEDITOR
[[nodiscard]] bool GetDebugDrawState () const noexcept; [[nodiscard]] bool GetDebugDrawState () const noexcept;
#endif
[[nodiscard]] const SHTransform& GetTransform () const noexcept; [[nodiscard]] const SHTransform& GetTransform () const noexcept;
[[nodiscard]] const SHVec3& GetPosition () const noexcept; [[nodiscard]] const SHVec3& GetPosition () const noexcept;
@ -94,9 +92,7 @@ namespace SHADE
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
#ifdef SHEDITOR
void SetDebugDrawState (bool state) noexcept; void SetDebugDrawState (bool state) noexcept;
#endif
void SetRigidBody (SHRigidBody* rb) noexcept; void SetRigidBody (SHRigidBody* rb) noexcept;
@ -161,9 +157,7 @@ namespace SHADE
EntityID entityID; EntityID entityID;
uint32_t shapeIDCounter; // This increments everytime a shape is added to differentiate shapes. uint32_t shapeIDCounter; // This increments everytime a shape is added to differentiate shapes.
#ifdef SHEDITOR
bool debugDraw; bool debugDraw;
#endif
SHRigidBody* rigidBody; SHRigidBody* rigidBody;
SHCollisionShapeFactory* shapeFactory; SHCollisionShapeFactory* shapeFactory;

View File

@ -136,6 +136,8 @@ namespace SHADE
{ {
rigidBody.collider->SetPosition(rigidBody.motionState.position); rigidBody.collider->SetPosition(rigidBody.motionState.position);
// TODO: Sync orientations // TODO: Sync orientations
rigidBody.collider->RecomputeShapes();
} }
} }

View File

@ -54,6 +54,13 @@ namespace SHADE
return collider->GetCollisionShape(index); return collider->GetCollisionShape(index);
} }
bool SHColliderComponent::GetDebugDrawState() const noexcept
{
if (!collider)
return false;
return collider->GetDebugDrawState();
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */ /* Setter Function Definitions */
@ -64,6 +71,13 @@ namespace SHADE
collider = c; collider = c;
} }
void SHColliderComponent::SetDebugDrawState(bool state) noexcept
{
if (collider)
collider->SetDebugDrawState(state);
}
} // namespace SHADE } // namespace SHADE
RTTR_REGISTRATION RTTR_REGISTRATION
@ -71,5 +85,6 @@ RTTR_REGISTRATION
using namespace rttr; using namespace rttr;
using namespace SHADE; using namespace SHADE;
registration::class_<SHColliderComponent>("Collider Component"); registration::class_<SHColliderComponent>("Collider Component")
.property("Is Debug Drawing", &SHColliderComponent::GetDebugDrawState, &SHColliderComponent::SetDebugDrawState);
} }

View File

@ -58,11 +58,19 @@ namespace SHADE
[[nodiscard]] const SHCollider::CollisionShapes* const GetCollisionShapes() const noexcept; [[nodiscard]] const SHCollider::CollisionShapes* const GetCollisionShapes() const noexcept;
[[nodiscard]] SHCollisionShape* const GetCollisionShape (int index) const; [[nodiscard]] SHCollisionShape* const GetCollisionShape (int index) const;
// Required for serialisation
[[nodiscard]] bool GetDebugDrawState () const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SetCollider(SHCollider* c) noexcept; void SetCollider (SHCollider* c) noexcept;
// Required for serialisation
void SetDebugDrawState (bool state) noexcept;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -13,7 +13,6 @@
// Project Headers // Project Headers
#include "Collision/CollisionShapes/SHCollisionShape.h" #include "Collision/CollisionShapes/SHCollisionShape.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -28,9 +27,16 @@ namespace SHADE
}; };
struct SHPhysicsColliderRemovedEvent struct SHPhysicsColliderRemovedEvent
{
EntityID entityID;
SHCollisionShape::Type colliderType;
int colliderIndex;
};
struct SHColliderOnDebugDrawEvent
{ {
EntityID entityID; EntityID entityID;
int colliderIndex; bool debugDrawState;
}; };

View File

@ -1,7 +1,7 @@
/**************************************************************************************** /****************************************************************************************
* \file SHPhysicsDebugDrawRoutine.cpp * \file SHPhysicsDebugDrawRutine.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520 * \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for the Physics Debug-Draw Routine * \brief Implementation for the Physics Debut Draw Routine
* *
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent * disclosure of this file or its contents without the prior written consent
@ -11,14 +11,13 @@
#include <SHpch.h> #include <SHpch.h>
// Primary Header // Primary Header
#include "Physics/System/SHPhysicsSystem.h" #include "Physics/System/SHPhysicsDebugDrawSystem.h"
// Project Headers // Project Headers
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h" #include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Scripting/SHScriptEngine.h" #include "Physics/System/SHPhysicsSystem.h"
namespace SHADE namespace SHADE
{ {
@ -26,35 +25,64 @@ namespace SHADE
/* Constructors & Destructor Definitions */ /* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHPhysicsSystem::PhysicsDebugDraw::PhysicsDebugDraw() SHPhysicsDebugDrawSystem::PhysicsDebugDraw::PhysicsDebugDraw()
: SHSystemRoutine { "Physics Debug Draw", false } : SHSystemRoutine { "Physics Debug-Draw", true }
{} {}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */ /* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHPhysicsSystem::PhysicsDebugDraw::Execute(double) noexcept void SHPhysicsDebugDrawSystem::PhysicsDebugDraw::Execute(double) noexcept
{ {
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem()); auto* physicsDebugDrawSystem = reinterpret_cast<SHPhysicsDebugDrawSystem*>(GetSystem());
// Get debug drawing system if (!physicsDebugDrawSystem->GetFlagState(DebugDrawFlags::ACTIVE))
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
if (!debugDrawSystem)
{
SHLOG_ERROR("Debug draw system unavailable! Colliders cannot be drawn!")
return; return;
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
const bool DRAW_COLLIDERS = physicsDebugDrawSystem->GetFlagState(DebugDrawFlags::COLLIDERS);
const bool DRAW_CONTACTS = physicsDebugDrawSystem->GetFlagState(DebugDrawFlags::CONTACTS);
const bool DRAW_RAYCASTS = physicsDebugDrawSystem->GetFlagState(DebugDrawFlags::RAYCASTS);
const bool DRAW_BROADPHASE = physicsDebugDrawSystem->GetFlagState(DebugDrawFlags::BROADPHASE);
// If draw all colliders is active, get all colliders from the dense set and draw.
// Else we check if any colliders have been flagged for drawing.
if (DRAW_COLLIDERS)
{
const auto& COLLIDER_COMPONENT_DENSE = SHComponentManager::GetDense<SHColliderComponent>();
for (const auto& COLLIDER_COMPONENT : COLLIDER_COMPONENT_DENSE)
{
const auto* COLLIDER = COLLIDER_COMPONENT.GetCollider();
drawCollider(debugDrawSystem, *COLLIDER);
}
}
else if (!physicsDebugDrawSystem->collidersToDraw.empty())
{
for (const auto EID : physicsDebugDrawSystem->collidersToDraw)
{
const auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(EID)->GetCollider();
drawCollider(debugDrawSystem, *COLLIDER);
}
} }
//SHPhysicsDebugDraw& physicsDebugRenderer = physicsSystem->debugRenderer; if (DRAW_CONTACTS)
{
// TODO
}
//if (!physicsDebugRenderer.GetDebugDrawState()) if (DRAW_RAYCASTS)
// return; {
// TODO
physicsDebugDrawSystem->raysToDraw.clear();
}
//// Draw colliders if (DRAW_BROADPHASE)
//if (physicsDebugRenderer.GetDrawSpecificCollidersState()) {
// physicsDebugRenderer.DrawSpecificColliders(debugDrawSystem); // TODO
//else if (physicsDebugRenderer.GetDrawAllCollidersState()) }
// physicsDebugRenderer.DrawAllColliders(debugDrawSystem);
} }
}
} // namespace SHADE

View File

@ -15,7 +15,6 @@
// Project Headers // Project Headers
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"

View File

@ -0,0 +1,158 @@
/****************************************************************************************
* \file SHPhysicsDebugDrawSystem.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for the Physics Debug Draw System
*
* \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.
****************************************************************************************/
#include <SHpch.h>
// Primary Header
#include "SHPhysicsDebugDrawSystem.h"
// Project Header
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Physics/SHPhysicsEvents.h"
#include "Tools/Utilities/SHUtilities.h"
namespace SHADE
{
const SHColour SHPhysicsDebugDrawSystem::DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(Colours::COUNT)]
{
SHColour::GREEN // Colliders
, SHColour::PURPLE // Triggers
, SHColour::RED // Contacts
, SHColour::ORANGE // Raycasts
, SHColour::CYAN // Broadphase
};
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsDebugDrawSystem::SHPhysicsDebugDrawSystem() noexcept
: flags { 0 }
{
collidersToDraw.clear();
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
bool SHPhysicsDebugDrawSystem::GetFlagState(DebugDrawFlags flag) const noexcept
{
const uint8_t ENUM_VALUE = SHUtilities::ConvertEnum(flag);
return flags & ENUM_VALUE;
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsDebugDrawSystem::SetFlagState(DebugDrawFlags flag, bool state) noexcept
{
const uint8_t ENUM_VALUE = SHUtilities::ConvertEnum(flag);
state ? flags |= ENUM_VALUE : flags &= ~ENUM_VALUE;
}
/*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsDebugDrawSystem::Init()
{
SystemFamily::GetID<SHPhysicsDebugDrawSystem>();
// Register collider draw event
const std::shared_ptr EVENT_RECEIVER = std::make_shared<SHEventReceiverSpec<SHPhysicsDebugDrawSystem>>(this, &SHPhysicsDebugDrawSystem::onColliderDraw);
const ReceiverPtr EVENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(EVENT_RECEIVER);
SHEventManager::SubscribeTo(SH_PHYSICS_COLLIDER_DRAW_EVENT, EVENT_RECEIVER_PTR);
}
void SHPhysicsDebugDrawSystem::Exit()
{
}
void SHPhysicsDebugDrawSystem::AddRaycast(const SHRay& ray, const SHPhysicsRaycastResult& result) noexcept
{
}
/*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
SHEventHandle SHPhysicsDebugDrawSystem::onColliderDraw(SHEventPtr onColliderDrawEvent)
{
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHColliderOnDebugDrawEvent>*>(onColliderDrawEvent.get())->data;
if (EVENT_DATA->debugDrawState)
{
if (collidersToDraw.empty())
SetFlagState(DebugDrawFlags::ACTIVE, true);
collidersToDraw.emplace(EVENT_DATA->entityID);
}
else
{
collidersToDraw.erase(EVENT_DATA->entityID);
if (collidersToDraw.empty())
SetFlagState(DebugDrawFlags::ACTIVE, false);
}
return onColliderDrawEvent.get()->handle;
}
void SHPhysicsDebugDrawSystem::drawCollider(SHDebugDrawSystem* debugDrawSystem, const SHCollider& collider) noexcept
{
for (const auto* SHAPE : collider.GetCollisionShapes())
{
switch (SHAPE->GetType())
{
case SHCollisionShape::Type::SPHERE:
{
const SHSphereCollisionShape* SPHERE = dynamic_cast<const SHSphereCollisionShape*>(SHAPE);
drawSphere(debugDrawSystem, *SPHERE);
break;
}
case SHCollisionShape::Type::BOX:
{
break;
}
case SHCollisionShape::Type::CAPSULE:
{
break;
}
default: break;
}
}
}
void SHPhysicsDebugDrawSystem::drawSphere(SHDebugDrawSystem* debugDrawSystem, const SHSphereCollisionShape& sphere) noexcept
{
const SHColour& DRAW_COLOUR = DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(sphere.IsTrigger() ? Colours::TRIGGER : Colours::COLLIDER)];
debugDrawSystem->DrawSphere(DRAW_COLOUR, sphere.GetCenter(), sphere.GetWorldRadius());
}
void SHPhysicsDebugDrawSystem::drawContact(SHDebugDrawSystem* debugDrawSystem, const DebugDrawInfo::Contact& contactInfo) noexcept
{
static const SHColour& DRAW_COLOUR = DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(Colours::CONTACT)];
}
void SHPhysicsDebugDrawSystem::drawRaycast(SHDebugDrawSystem* debugDrawSystem, const DebugDrawInfo::Raycast& raycastInfo) noexcept
{
static const SHColour& DRAW_COLOUR = DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(Colours::RAYCAST)];
}
} // namespace SHADE

View File

@ -0,0 +1,150 @@
/****************************************************************************************
* \file SHPhysicsDebugDrawSystem.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for the Physics Debug Draw System
*
* \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
#include <unordered_set>
// Project Headers
#include "ECS_Base/Entity/SHEntity.h"
#include "ECS_Base/System/SHSystem.h"
#include "ECS_Base/System/SHSystemRoutine.h"
#include "Events/SHEvent.h"
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
#include "Physics/Collision/SHCollider.h"
#include "Physics/Collision/SHPhysicsRaycastResult.h"
#include "Physics/Collision/CollisionShapes/SHSphereCollisionShape.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHPhysicsDebugDrawSystem final : public SHSystem
{
public:
enum class DebugDrawFlags : uint8_t
{
ACTIVE = 0x0001
, COLLIDERS = 0x0002
, CONTACTS = 0x0004
, RAYCASTS = 0x0008
, BROADPHASE = 0x0010
};
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHPhysicsDebugDrawSystem () noexcept;
~SHPhysicsDebugDrawSystem() noexcept = default;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] bool GetFlagState (DebugDrawFlags flag) const noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetFlagState (DebugDrawFlags flag, bool state) noexcept;
/*---------------------------------------------------------------------------------*/
/* Member Functions */
/*---------------------------------------------------------------------------------*/
void Init () override;
void Exit () override;
void AddRaycast (const SHRay& ray, const SHPhysicsRaycastResult& result) noexcept;
/*---------------------------------------------------------------------------------*/
/* System Routines */
/*---------------------------------------------------------------------------------*/
/**
* @brief
* If the editor is enabled, this routine invokes debug drawing for colliders and collision information.
*/
class SH_API PhysicsDebugDraw final : public SHSystemRoutine
{
public:
PhysicsDebugDraw();
void Execute(double dt) noexcept override;
};
private:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
union DebugDrawInfo
{
struct Contact
{
SHVec3 worldPos;
SHVec3 normal;
} contact;
struct Raycast
{
SHVec3 start;
SHVec3 end;
} raycast;
};
using Colliders = std::unordered_set<EntityID>;
using Raycasts = std::vector<DebugDrawInfo>;
using Contacts = std::vector<DebugDrawInfo>;
enum class Colours
{
COLLIDER
, TRIGGER
, CONTACT
, RAYCAST
, BROADPHASE
, COUNT
};
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
static const SHColour DEBUG_DRAW_COLOURS[static_cast<int>(Colours::COUNT)];
// 0 0 0 drawBroadphase drawRaycasts drawContacts drawAllColliders debugDrawActive
uint8_t flags;
Colliders collidersToDraw;
Raycasts raysToDraw;
Contacts contactToDraw;
/*---------------------------------------------------------------------------------*/
/* Member Functions */
/*---------------------------------------------------------------------------------*/
SHEventHandle onColliderDraw(SHEventPtr onColliderDrawEvent);
static void drawCollider (SHDebugDrawSystem* debugDrawSystem, const SHCollider& collider) noexcept;
static void drawSphere (SHDebugDrawSystem* debugDrawSystem, const SHSphereCollisionShape& sphere) noexcept;
static void drawContact (SHDebugDrawSystem* debugDrawSystem, const DebugDrawInfo::Contact& contactInfo) noexcept;
static void drawRaycast (SHDebugDrawSystem* debugDrawSystem, const DebugDrawInfo::Raycast& raycastInfo) noexcept;
};
} // namespace SHADE

View File

@ -110,13 +110,12 @@ namespace SHADE
void SHPhysicsSystem::Init() void SHPhysicsSystem::Init()
{ {
// TODO(Diren): Consider using a non-static collision tag matrix.
// Initialise collision tags // Initialise collision tags
std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT }; std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT };
defaultCollisionTagNameFilePath.append("CollisionTags.SHConfig"); defaultCollisionTagNameFilePath.append("CollisionTags.SHConfig");
SHCollisionTagMatrix::Init(defaultCollisionTagNameFilePath); SHCollisionTagMatrix::Init(defaultCollisionTagNameFilePath);
// Link Managers to system
// Register Events // Register Events
for (int i = 0; i < NUM_EVENT_FUNCTIONS; ++i) for (int i = 0; i < NUM_EVENT_FUNCTIONS; ++i)
{ {

View File

@ -27,6 +27,10 @@ namespace SHADE
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/**
* @brief
* Encapsulates a system for running and managing the physics simulation of the engine.
*/
class SH_API SHPhysicsSystem final : public SHSystem class SH_API SHPhysicsSystem final : public SHSystem
{ {
public: public:
@ -41,23 +45,27 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] double GetFixedUpdateRate() const noexcept; [[nodiscard]] double GetFixedUpdateRate() const noexcept;
[[nodiscard]] double GetFixedDT() const noexcept; [[nodiscard]] double GetFixedDT() const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SetFixedUpdateRate(double fixedUpdateRate) noexcept; void SetFixedUpdateRate(double fixedUpdateRate) noexcept;
void SetFixedDT(double fixedDt) noexcept; void SetFixedDT(double fixedDt) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Member Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/**
* @brief
* - Initialises the static collision tag matrix.
* - Registers the system to catch specific events.
*/
void Init() override; void Init() override;
void Exit() override; void Exit() override;
void ForceUpdate(); void ForceUpdate();
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -104,21 +112,6 @@ namespace SHADE
void Execute(double dt) noexcept override; void Execute(double dt) noexcept override;
}; };
#ifdef SHEDITOR
/**
* @brief
* If the editor is enabled, this routine invokes debug drawing for colliders.
* and collision information.
*/
class SH_API PhysicsDebugDraw final : public SHSystemRoutine
{
public:
PhysicsDebugDraw();
void Execute(double dt) noexcept override;
};
#endif
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */

View File

@ -204,10 +204,15 @@ namespace YAML
template<> template<>
struct convert<SHColliderComponent> struct convert<SHColliderComponent>
{ {
static constexpr const char* DrawColliders = "DrawColliders";
static constexpr const char* Colliders = "Colliders"; static constexpr const char* Colliders = "Colliders";
static Node encode(SHColliderComponent& rhs) static Node encode(SHColliderComponent& rhs)
{ {
Node node, collidersNode; Node node, collidersNode;
node[DrawColliders] = rhs.GetDebugDrawState();
int const numColliders = static_cast<int>(rhs.GetCollisionShapes()->size()); int const numColliders = static_cast<int>(rhs.GetCollisionShapes()->size());
for (int i = 0; i < numColliders; ++i) for (int i = 0; i < numColliders; ++i)
{ {
@ -221,6 +226,9 @@ namespace YAML
} }
static bool decode(Node const& node, SHColliderComponent& rhs) static bool decode(Node const& node, SHColliderComponent& rhs)
{ {
if (node[DrawColliders].IsDefined())
rhs.SetDebugDrawState(node[DrawColliders].as<bool>());
if (node[Colliders].IsDefined()) if (node[Colliders].IsDefined())
{ {
int numColliders{}; int numColliders{};