From 45e549f9f1c5c4c9c80fea3f23043588169b0cda Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sat, 12 Nov 2022 16:56:58 +0800 Subject: [PATCH] .....small restructure.... --- .../src/Application/SBApplication.cpp | 4 +- SHADE_Application/src/Scenes/SBMainScene.cpp | 4 +- SHADE_Application/src/Scenes/SBTestScene.cpp | 4 +- .../Inspector/SHEditorComponentView.hpp | 2 +- .../Inspector/SHEditorInspector.cpp | 4 +- .../SHCollisionInfo.cpp} | 28 +- .../SHCollisionInfo.h} | 48 +- .../Physics/Collision/SHCollisionListener.cpp | 236 ++++++ .../Physics/Collision/SHCollisionListener.h | 81 ++ .../SHColliderComponent.cpp | 21 +- .../SHColliderComponent.h | 2 +- .../{ => Interface}/SHCollisionShape.cpp | 2 +- .../{ => Interface}/SHCollisionShape.h | 0 .../{ => Interface}/SHPhysicsMaterial.cpp | 0 .../{ => Interface}/SHPhysicsMaterial.h | 0 .../SHRigidBodyComponent.cpp | 384 +++------- .../SHRigidBodyComponent.h | 64 +- .../Physics/PhysicsObject/SHPhysicsObject.cpp | 361 +++++++++ .../{ => PhysicsObject}/SHPhysicsObject.h | 43 +- .../PhysicsObject/SHPhysicsObjectManager.cpp | 266 +++++++ .../PhysicsObject/SHPhysicsObjectManager.h | 178 +++++ SHADE_Engine/src/Physics/SHPhysicsEvents.h | 37 + SHADE_Engine/src/Physics/SHPhysicsObject.cpp | 219 ------ SHADE_Engine/src/Physics/SHPhysicsSystem.cpp | 706 ------------------ SHADE_Engine/src/Physics/SHPhysicsSystem.hpp | 84 --- SHADE_Engine/src/Physics/SHPhysicsWorld.cpp | 66 ++ SHADE_Engine/src/Physics/SHPhysicsWorld.h | 74 ++ .../{ => System}/SHPhysicsDebugDrawSystem.cpp | 0 .../{ => System}/SHPhysicsDebugDrawSystem.h | 0 .../src/Physics/System/SHPhysicsSystem.cpp | 307 ++++++++ .../Physics/{ => System}/SHPhysicsSystem.h | 149 ++-- .../{ => System}/SHPhysicsSystemInterface.cpp | 15 +- .../{ => System}/SHPhysicsSystemInterface.h | 6 +- .../System/SHPhysicsSystemRoutines.cpp | 314 ++++++++ SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 3 +- .../src/Serialization/SHSerialization.cpp | 2 +- .../src/Serialization/SHYAMLConverters.h | 4 +- SHADE_Managed/src/Components/Collider.hxx | 2 +- SHADE_Managed/src/Components/RigidBody.hxx | 2 +- SHADE_Managed/src/Engine/ECS.cxx | 4 +- SHADE_Managed/src/Engine/Time.cxx | 2 +- SHADE_Managed/src/Scripts/ScriptStore.cxx | 17 +- 42 files changed, 2259 insertions(+), 1486 deletions(-) rename SHADE_Engine/src/Physics/{SHPhysicsUtils.cpp => Collision/SHCollisionInfo.cpp} (72%) rename SHADE_Engine/src/Physics/{SHPhysicsUtils.h => Collision/SHCollisionInfo.h} (71%) create mode 100644 SHADE_Engine/src/Physics/Collision/SHCollisionListener.cpp create mode 100644 SHADE_Engine/src/Physics/Collision/SHCollisionListener.h rename SHADE_Engine/src/Physics/{Components => Interface}/SHColliderComponent.cpp (90%) rename SHADE_Engine/src/Physics/{Components => Interface}/SHColliderComponent.h (98%) rename SHADE_Engine/src/Physics/{ => Interface}/SHCollisionShape.cpp (99%) rename SHADE_Engine/src/Physics/{ => Interface}/SHCollisionShape.h (100%) rename SHADE_Engine/src/Physics/{ => Interface}/SHPhysicsMaterial.cpp (100%) rename SHADE_Engine/src/Physics/{ => Interface}/SHPhysicsMaterial.h (100%) rename SHADE_Engine/src/Physics/{Components => Interface}/SHRigidBodyComponent.cpp (55%) rename SHADE_Engine/src/Physics/{Components => Interface}/SHRigidBodyComponent.h (78%) create mode 100644 SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp rename SHADE_Engine/src/Physics/{ => PhysicsObject}/SHPhysicsObject.h (70%) create mode 100644 SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp create mode 100644 SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h create mode 100644 SHADE_Engine/src/Physics/SHPhysicsEvents.h delete mode 100644 SHADE_Engine/src/Physics/SHPhysicsObject.cpp delete mode 100644 SHADE_Engine/src/Physics/SHPhysicsSystem.cpp delete mode 100644 SHADE_Engine/src/Physics/SHPhysicsSystem.hpp create mode 100644 SHADE_Engine/src/Physics/SHPhysicsWorld.cpp create mode 100644 SHADE_Engine/src/Physics/SHPhysicsWorld.h rename SHADE_Engine/src/Physics/{ => System}/SHPhysicsDebugDrawSystem.cpp (100%) rename SHADE_Engine/src/Physics/{ => System}/SHPhysicsDebugDrawSystem.h (100%) create mode 100644 SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp rename SHADE_Engine/src/Physics/{ => System}/SHPhysicsSystem.h (57%) rename SHADE_Engine/src/Physics/{ => System}/SHPhysicsSystemInterface.cpp (81%) rename SHADE_Engine/src/Physics/{ => System}/SHPhysicsSystemInterface.h (91%) create mode 100644 SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 6955035b..bf5b8d49 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -30,8 +30,8 @@ #include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h" #include "Input/SHInputManager.h" #include "Math/Transform/SHTransformSystem.h" -#include "Physics/SHPhysicsSystem.h" -#include "Physics/SHPhysicsDebugDrawSystem.h" +#include "Physics/System/SHPhysicsSystem.h" +#include "Physics/System/SHPhysicsDebugDrawSystem.h" #include "Scripting/SHScriptEngine.h" // Components diff --git a/SHADE_Application/src/Scenes/SBMainScene.cpp b/SHADE_Application/src/Scenes/SBMainScene.cpp index 34190915..b14f2e6f 100644 --- a/SHADE_Application/src/Scenes/SBMainScene.cpp +++ b/SHADE_Application/src/Scenes/SBMainScene.cpp @@ -10,8 +10,8 @@ #include "Scripting/SHScriptEngine.h" #include "Math/Transform/SHTransformComponent.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" -#include "Physics/Components/SHRigidBodyComponent.h" -#include "Physics/Components/SHColliderComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" +#include "Physics/Interface/SHColliderComponent.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h" #include "Assets/SHAssetManager.h" diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index 8281f114..bcc7f09d 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -10,8 +10,8 @@ #include "Scripting/SHScriptEngine.h" #include "Math/Transform/SHTransformComponent.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" -#include "Physics/Components/SHRigidBodyComponent.h" -#include "Physics/Components/SHColliderComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" +#include "Physics/Interface/SHColliderComponent.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h" #include "Assets/SHAssetManager.h" diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 7e7db174..2e55ea7a 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -15,7 +15,7 @@ #include "Editor/SHEditorWidgets.hpp" #include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h" -#include "Physics/Components/SHColliderComponent.h" +#include "Physics/Interface/SHColliderComponent.h" #include "Reflection/SHReflectionMetadata.h" #include "Resource/SHResourceManager.h" diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp index 2fecae25..c4dd1fdb 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp @@ -14,8 +14,8 @@ #include "Scripting/SHScriptEngine.h" #include "ECS_Base/Managers/SHSystemManager.h" -#include "Physics/Components/SHRigidBodyComponent.h" -#include "Physics/Components/SHColliderComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" +#include "Physics/Interface/SHColliderComponent.h" #include "Camera/SHCameraComponent.h" #include "Camera/SHCameraArmComponent.h" #include "SHEditorComponentView.h" diff --git a/SHADE_Engine/src/Physics/SHPhysicsUtils.cpp b/SHADE_Engine/src/Physics/Collision/SHCollisionInfo.cpp similarity index 72% rename from SHADE_Engine/src/Physics/SHPhysicsUtils.cpp rename to SHADE_Engine/src/Physics/Collision/SHCollisionInfo.cpp index 14b6cc2f..43ad05ca 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsUtils.cpp +++ b/SHADE_Engine/src/Physics/Collision/SHCollisionInfo.cpp @@ -1,7 +1,7 @@ /**************************************************************************************** - * \file SHPhysicsUtils.cpp + * \file SHCollisionInfo.cpp * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Implementation for some Physics Utilities + * \brief Implementation for Collision Info. * * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or * disclosure of this file or its contents without the prior written consent @@ -11,7 +11,7 @@ #include // Primary Header -#include "SHPhysicsUtils.h" +#include "SHCollisionInfo.h" namespace SHADE { @@ -19,7 +19,7 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHCollisionEvent::SHCollisionEvent() noexcept + SHCollisionInfo::SHCollisionInfo() noexcept : collisionState { State::INVALID } { ids[ENTITY_A] = MAX_EID; @@ -28,7 +28,7 @@ namespace SHADE ids[COLLIDER_B] = std::numeric_limits::max(); } - SHCollisionEvent::SHCollisionEvent(EntityID entityA, EntityID entityB) noexcept + SHCollisionInfo::SHCollisionInfo(EntityID entityA, EntityID entityB) noexcept : collisionState { State::INVALID } { ids[ENTITY_A] = entityA; @@ -41,12 +41,12 @@ namespace SHADE /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ - bool SHCollisionEvent::operator==(const SHCollisionEvent& rhs) const noexcept + bool SHCollisionInfo::operator==(const SHCollisionInfo& rhs) const noexcept { return value[0] == rhs.value[0] && value[1] == rhs.value[1]; } - bool SHCollisionEvent::operator!=(const SHCollisionEvent& rhs) const noexcept + bool SHCollisionInfo::operator!=(const SHCollisionInfo& rhs) const noexcept { return value[0] != rhs.value[0] || value[1] != rhs.value[1]; } @@ -55,37 +55,37 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - EntityID SHCollisionEvent::GetEntityA() const noexcept + EntityID SHCollisionInfo::GetEntityA() const noexcept { return ids[ENTITY_A]; } - EntityID SHCollisionEvent::GetEntityB() const noexcept + EntityID SHCollisionInfo::GetEntityB() const noexcept { return ids[ENTITY_B]; } - const SHRigidBodyComponent* SHCollisionEvent::GetRigidBodyA() const noexcept + const SHRigidBodyComponent* SHCollisionInfo::GetRigidBodyA() const noexcept { return SHComponentManager::GetComponent_s(ids[ENTITY_A]); } - const SHRigidBodyComponent* SHCollisionEvent::GetRigidBodyB() const noexcept + const SHRigidBodyComponent* SHCollisionInfo::GetRigidBodyB() const noexcept { return SHComponentManager::GetComponent_s(ids[ENTITY_B]); } - const SHCollisionShape* SHCollisionEvent::GetColliderA() const noexcept + const SHCollisionShape* SHCollisionInfo::GetColliderA() const noexcept { return &SHComponentManager::GetComponent(ids[ENTITY_A])->GetCollisionShape(ids[COLLIDER_A]); } - const SHCollisionShape* SHCollisionEvent::GetColliderB() const noexcept + const SHCollisionShape* SHCollisionInfo::GetColliderB() const noexcept { return &SHComponentManager::GetComponent(ids[ENTITY_B])->GetCollisionShape(ids[COLLIDER_B]); } - SHCollisionEvent::State SHCollisionEvent::GetCollisionState() const noexcept + SHCollisionInfo::State SHCollisionInfo::GetCollisionState() const noexcept { return collisionState; } diff --git a/SHADE_Engine/src/Physics/SHPhysicsUtils.h b/SHADE_Engine/src/Physics/Collision/SHCollisionInfo.h similarity index 71% rename from SHADE_Engine/src/Physics/SHPhysicsUtils.h rename to SHADE_Engine/src/Physics/Collision/SHCollisionInfo.h index 753f8d3b..d2dad647 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsUtils.h +++ b/SHADE_Engine/src/Physics/Collision/SHCollisionInfo.h @@ -1,7 +1,7 @@ /**************************************************************************************** - * \file SHPhysicsUtils.h + * \file SHCollisionInfo.h * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Interface for some Physics Utilities + * \brief Interface for Collision Information for Collision & Triggers. * * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or * disclosure of this file or its contents without the prior written consent @@ -11,8 +11,8 @@ #pragma once // Project Headers -#include "Components/SHColliderComponent.h" -#include "Components/SHRigidBodyComponent.h" +#include "Physics/Interface/SHColliderComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" namespace SHADE @@ -21,27 +21,14 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - struct SHPhysicsColliderAddedEvent - { - EntityID entityID; - SHCollisionShape::Type colliderType; - int colliderIndex; - }; - - struct SHPhysicsColliderRemovedEvent - { - EntityID entityID; - int colliderIndex; - }; - - class SH_API SHCollisionEvent + class SH_API SHCollisionInfo { private: /*---------------------------------------------------------------------------------*/ /* Friends */ /*---------------------------------------------------------------------------------*/ - friend class SHPhysicsSystem; + friend class SHCollisionListener; public: /*---------------------------------------------------------------------------------*/ @@ -62,23 +49,23 @@ namespace SHADE /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHCollisionEvent () noexcept; - SHCollisionEvent (EntityID entityA, EntityID entityB) noexcept; + SHCollisionInfo () noexcept; + SHCollisionInfo (EntityID entityA, EntityID entityB) noexcept; - SHCollisionEvent (const SHCollisionEvent& rhs) = default; - SHCollisionEvent (SHCollisionEvent&& rhs) = default; - ~SHCollisionEvent () = default; + SHCollisionInfo (const SHCollisionInfo& rhs) = default; + SHCollisionInfo (SHCollisionInfo&& rhs) = default; + ~SHCollisionInfo () = default; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ /*---------------------------------------------------------------------------------*/ - bool operator== (const SHCollisionEvent& rhs) const noexcept; - bool operator!= (const SHCollisionEvent& rhs) const noexcept; + bool operator== (const SHCollisionInfo& rhs) const noexcept; + bool operator!= (const SHCollisionInfo& rhs) const noexcept; - SHCollisionEvent& operator= (const SHCollisionEvent& rhs) = default; - SHCollisionEvent& operator= (SHCollisionEvent&& rhs) = default; + SHCollisionInfo& operator= (const SHCollisionInfo& rhs) = default; + SHCollisionInfo& operator= (SHCollisionInfo&& rhs) = default; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ @@ -88,8 +75,8 @@ namespace SHADE [[nodiscard]] EntityID GetEntityB () const noexcept; [[nodiscard]] const SHRigidBodyComponent* GetRigidBodyA () const noexcept; [[nodiscard]] const SHRigidBodyComponent* GetRigidBodyB () const noexcept; - [[nodiscard]] const SHCollisionShape* GetColliderA () const noexcept; - [[nodiscard]] const SHCollisionShape* GetColliderB () const noexcept; + [[nodiscard]] const SHCollisionShape* GetColliderA () const noexcept; + [[nodiscard]] const SHCollisionShape* GetColliderB () const noexcept; [[nodiscard]] State GetCollisionState () const noexcept; private: @@ -112,5 +99,4 @@ namespace SHADE State collisionState; }; - } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/SHCollisionListener.cpp b/SHADE_Engine/src/Physics/Collision/SHCollisionListener.cpp new file mode 100644 index 00000000..e8379b09 --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/SHCollisionListener.cpp @@ -0,0 +1,236 @@ +/**************************************************************************************** + * \file SHCollisionListener.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Collision Listener. + * + * \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 + +// Primary Header +#include "SHCollisionListener.h" + +// Project Headers +#include "Physics/PhysicsObject/SHPhysicsObject.h" +#include "Physics/System/SHPhysicsSystem.h" + +/*-------------------------------------------------------------------------------------*/ +/* Local Helper Functions */ +/*-------------------------------------------------------------------------------------*/ + +uint32_t matchColliders(const SHADE::SHPhysicsObject&physicsObject, const rp3d::Entity colliderID) +{ + for (uint32_t i = 0; i < physicsObject.GetCollisionBody()->getNbColliders(); ++i) + { + const auto* collider = physicsObject.GetCollisionBody()->getCollider(i); + if (collider->getEntity() == colliderID) + return i; + } + + return std::numeric_limits::max(); +} + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHCollisionListener::SHCollisionListener() noexcept + : system { nullptr } + {} + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + const std::vector& SHCollisionListener::GetCollisionInfoContainer() const noexcept + { + return collisionInfoContainer; + } + + const std::vector& SHCollisionListener::GetTriggerInfoContainer() const noexcept + { + return triggerInfoContainer; + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHCollisionListener::BindToSystem(SHPhysicsSystem* physicsSystem) noexcept + { + system = physicsSystem; + } + + void SHCollisionListener::BindToWorld(rp3d::PhysicsWorld* world) noexcept + { + if (!world) + return; + + world->setEventListener(this); + } + + void SHCollisionListener::CleanContainers() noexcept + { + static const auto CLEAR = [](std::vector& container) + { + for (auto eventIter = container.begin(); eventIter != container.end();) + { + const bool CLEAR_EVENT = eventIter->GetCollisionState() == SHCollisionInfo::State::EXIT + || eventIter->GetCollisionState() == SHCollisionInfo::State::INVALID; + + if (CLEAR_EVENT) + eventIter = container.erase(eventIter); + else + ++eventIter; + } + }; + + CLEAR(collisionInfoContainer); + CLEAR(triggerInfoContainer); + } + + void SHCollisionListener::ClearContainers() noexcept + { + collisionInfoContainer.clear(); + triggerInfoContainer.clear(); + } + + void SHCollisionListener::onContact(const rp3d::CollisionCallback::CallbackData& callbackData) + { + for (uint32_t i = 0; i < callbackData.getNbContactPairs(); ++i) + { + const auto CONTACT_PAIR = callbackData.getContactPair(i); + const SHCollisionInfo NEW_INFO = generateCollisionInfo(CONTACT_PAIR); + + updateInfoContainers(NEW_INFO, collisionInfoContainer); + } + } + + void SHCollisionListener::onTrigger(const rp3d::OverlapCallback::CallbackData& callbackData) + { + for (uint32_t i = 0; i < callbackData.getNbOverlappingPairs(); ++i) + { + const auto OVERLAP_PAIR = callbackData.getOverlappingPair(i); + const SHCollisionInfo NEW_INFO = generateTriggerInfo(OVERLAP_PAIR); + + updateInfoContainers(NEW_INFO, triggerInfoContainer); + } + } + + /*-----------------------------------------------------------------------------------*/ + /* Private Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHCollisionListener::updateInfoContainers(const SHCollisionInfo& collisionEvent, std::vector& container) noexcept + { + const auto IT = std::ranges::find_if(container.begin(), container.end(), [&](const SHCollisionInfo& info) + { + const bool ENTITY_MATCH = (info.ids[0] == collisionEvent.ids[0] && info.ids[1] == collisionEvent.ids[1]) + || (info.ids[0] == collisionEvent.ids[1] && info.ids[1] == collisionEvent.ids[0]); + const bool COLLIDERS_MATCH = (info.ids[2] == collisionEvent.ids[2] && info.ids[3] == collisionEvent.ids[3]) + || (info.ids[2] == collisionEvent.ids[3] && info.ids[3] == collisionEvent.ids[2]); + return ENTITY_MATCH && COLLIDERS_MATCH; + }); + + if (IT == container.end()) + container.emplace_back(collisionEvent); + else + IT->collisionState = collisionEvent.collisionState; + } + + SHCollisionInfo SHCollisionListener::generateCollisionInfo(const rp3d::CollisionCallback::ContactPair& cp) const noexcept + { + SHCollisionInfo cInfo; + + // Update collision state + cInfo.collisionState = static_cast(cp.getEventType()); + + // Match body and collider for collision event + const rp3d::Entity body1 = cp.getBody1()->getEntity(); + const rp3d::Entity body2 = cp.getBody2()->getEntity(); + const rp3d::Entity collider1 = cp.getCollider1()->getEntity(); + const rp3d::Entity collider2 = cp.getCollider2()->getEntity(); + + // Find and match both ids + bool matched[2] = { false, false }; + + + for (auto& [entityID, physicsObject] : system->GetPhysicsObjects()) + { + // Match body 1 + if (matched[SHCollisionInfo::ENTITY_A] == false && physicsObject.GetCollisionBody()->getEntity() == body1) + { + cInfo.ids[SHCollisionInfo::ENTITY_A] = entityID; + cInfo.ids[SHCollisionInfo::COLLIDER_A] = matchColliders(physicsObject, collider1); + + matched[SHCollisionInfo::ENTITY_A] = true; + } + + // Match body 2 + if (matched[SHCollisionInfo::ENTITY_B] == false && physicsObject.GetCollisionBody()->getEntity() == body2) + { + cInfo.ids[SHCollisionInfo::ENTITY_B] = entityID; + cInfo.ids[SHCollisionInfo::COLLIDER_B] = matchColliders(physicsObject, collider2); + + matched[SHCollisionInfo::ENTITY_B] = true; + } + + if (matched[SHCollisionInfo::ENTITY_A] == true && matched[SHCollisionInfo::ENTITY_B] == true) + return cInfo; + } + + return cInfo; + } + + SHCollisionInfo SHCollisionListener::generateTriggerInfo(const rp3d::OverlapCallback::OverlapPair& cp) const noexcept + { + SHCollisionInfo cInfo; + + // Update collision state + cInfo.collisionState = static_cast(cp.getEventType()); + + // Match body and collider for collision event + const rp3d::Entity body1 = cp.getBody1()->getEntity(); + const rp3d::Entity body2 = cp.getBody2()->getEntity(); + const rp3d::Entity collider1 = cp.getCollider1()->getEntity(); + const rp3d::Entity collider2 = cp.getCollider2()->getEntity(); + + // Find and match both ids + bool matched[2] = { false, false }; + + + for (auto& [entityID, physicsObject] : system->GetPhysicsObjects()) + { + // Match body 1 + if (matched[SHCollisionInfo::ENTITY_A] == false && physicsObject.GetCollisionBody()->getEntity() == body1) + { + cInfo.ids[SHCollisionInfo::ENTITY_A] = entityID; + cInfo.ids[SHCollisionInfo::COLLIDER_A] = matchColliders(physicsObject, collider1); + + matched[SHCollisionInfo::ENTITY_A] = true; + } + + // Match body 2 + if (matched[SHCollisionInfo::ENTITY_B] == false && physicsObject.GetCollisionBody()->getEntity() == body2) + { + cInfo.ids[SHCollisionInfo::ENTITY_B] = entityID; + cInfo.ids[SHCollisionInfo::COLLIDER_B] = matchColliders(physicsObject, collider2); + + matched[SHCollisionInfo::ENTITY_B] = true; + } + + if (matched[SHCollisionInfo::ENTITY_A] == true && matched[SHCollisionInfo::ENTITY_B] == true) + return cInfo; + } + + return cInfo; + } + + + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/SHCollisionListener.h b/SHADE_Engine/src/Physics/Collision/SHCollisionListener.h new file mode 100644 index 00000000..6262b946 --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/SHCollisionListener.h @@ -0,0 +1,81 @@ +/**************************************************************************************** + * \file SHCollisionListener.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Collision Listener. + * + * \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 + +// External Dependencies +#include + +// Project Headers +#include "SH_API.h" +#include "SHCollisionInfo.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-----------------------------------------------------------------------------------*/ + + class SHPhysicsSystem; + + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + class SH_API SHCollisionListener final : public rp3d::EventListener + { + public: + + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHCollisionListener() noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Getter Functions */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] const std::vector& GetCollisionInfoContainer () const noexcept; + [[nodiscard]] const std::vector& GetTriggerInfoContainer () const noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + void BindToSystem (SHPhysicsSystem* physicsSystem) noexcept; + void BindToWorld (rp3d::PhysicsWorld* world) noexcept; + void CleanContainers () noexcept; + void ClearContainers () noexcept; + + void onContact (const rp3d::CollisionCallback::CallbackData& callbackData) override; + void onTrigger (const rp3d::OverlapCallback::CallbackData& callbackData) override; + + private: + + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + SHPhysicsSystem* system; + std::vector collisionInfoContainer; + std::vector triggerInfoContainer; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + static void updateInfoContainers (const SHCollisionInfo& collisionEvent, std::vector& container) noexcept; + + SHCollisionInfo generateCollisionInfo (const rp3d::CollisionCallback::ContactPair& cp) const noexcept; + SHCollisionInfo generateTriggerInfo (const rp3d::OverlapCallback::OverlapPair& cp) const noexcept; + }; + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp similarity index 90% rename from SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp rename to SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp index 864de46f..1c8149ad 100644 --- a/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp @@ -16,7 +16,7 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" #include "Math/SHMathHelpers.h" -#include "Physics/SHPhysicsSystem.h" +#include "Physics/System/SHPhysicsSystem.h" namespace SHADE { @@ -72,7 +72,14 @@ namespace SHADE void SHColliderComponent::OnCreate() { - system = SHSystemManager::GetSystem(); + auto* physicsSystem = SHSystemManager::GetSystem(); + if (!physicsSystem) + { + SHLOG_ERROR("Physics System does not exist to link with Physics Components!") + return; + } + + system = physicsSystem; } void SHColliderComponent::OnDestroy() @@ -132,9 +139,10 @@ namespace SHADE collider.SetBoundingBox(halfExtents); // Notify Physics System - system->AddCollisionShape(GetEID(), &collider); + const int NEW_SHAPE_INDEX = static_cast(collisionShapes.size()) - 1; - return static_cast(collisionShapes.size()) - 1; + system->AddCollisionShape(GetEID(), NEW_SHAPE_INDEX); + return NEW_SHAPE_INDEX; } int SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept @@ -154,9 +162,10 @@ namespace SHADE collider.SetBoundingSphere(radius); // Notify Physics System - system->AddCollisionShape(GetEID(), &collider); + const int NEW_SHAPE_INDEX = static_cast(collisionShapes.size()) - 1; - return static_cast(collisionShapes.size()) - 1; + system->AddCollisionShape(GetEID(), NEW_SHAPE_INDEX); + return NEW_SHAPE_INDEX; } void SHColliderComponent::RemoveCollider(int index) diff --git a/SHADE_Engine/src/Physics/Components/SHColliderComponent.h b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h similarity index 98% rename from SHADE_Engine/src/Physics/Components/SHColliderComponent.h rename to SHADE_Engine/src/Physics/Interface/SHColliderComponent.h index 5f9b7a1b..88dc306f 100644 --- a/SHADE_Engine/src/Physics/Components/SHColliderComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h @@ -14,9 +14,9 @@ // Project Headers #include "ECS_Base/Components/SHComponent.h" -#include "Physics/SHCollisionShape.h" #include "Math/Geometry/SHBoundingBox.h" #include "Math/Geometry/SHBoundingSphere.h" +#include "SHCollisionShape.h" //namespace SHADE //{ diff --git a/SHADE_Engine/src/Physics/SHCollisionShape.cpp b/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp similarity index 99% rename from SHADE_Engine/src/Physics/SHCollisionShape.cpp rename to SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp index bc2347e7..1ea2a7d3 100644 --- a/SHADE_Engine/src/Physics/SHCollisionShape.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp @@ -16,8 +16,8 @@ #include "Math/Geometry/SHBoundingBox.h" #include "Math/Geometry/SHBoundingSphere.h" #include "Math/SHMathHelpers.h" -#include "Physics/Components/SHColliderComponent.h" #include "Reflection/SHReflectionMetadata.h" +#include "SHColliderComponent.h" namespace SHADE { diff --git a/SHADE_Engine/src/Physics/SHCollisionShape.h b/SHADE_Engine/src/Physics/Interface/SHCollisionShape.h similarity index 100% rename from SHADE_Engine/src/Physics/SHCollisionShape.h rename to SHADE_Engine/src/Physics/Interface/SHCollisionShape.h diff --git a/SHADE_Engine/src/Physics/SHPhysicsMaterial.cpp b/SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.cpp similarity index 100% rename from SHADE_Engine/src/Physics/SHPhysicsMaterial.cpp rename to SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.cpp diff --git a/SHADE_Engine/src/Physics/SHPhysicsMaterial.h b/SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.h similarity index 100% rename from SHADE_Engine/src/Physics/SHPhysicsMaterial.h rename to SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.h diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp similarity index 55% rename from SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp rename to SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp index 369d26a5..5fe1e55e 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp @@ -19,7 +19,7 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" #include "Math/SHMathHelpers.h" -#include "Physics/SHPhysicsSystem.h" +#include "Physics/System/SHPhysicsSystem.h" namespace SHADE { @@ -30,8 +30,17 @@ namespace SHADE SHRigidBodyComponent::SHRigidBodyComponent() noexcept : type { Type::DYNAMIC } , interpolate { true } - , rp3dBody { nullptr } - {} + , flags { 0 } + , dirtyFlags { std::numeric_limits::max() } + , mass { 1.0f } + , drag { 0.01f } + , angularDrag { 0.01f } + , system { nullptr } + { + // Initialise default flags + flags |= 1U << 0; // Gravity set to true + flags |= 1U << 1; // Sleeping allowed + } /*-----------------------------------------------------------------------------------*/ /* Getter Function Definitions */ @@ -39,24 +48,14 @@ namespace SHADE bool SHRigidBodyComponent::IsGravityEnabled() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return false; - } - - return rp3dBody->isGravityEnabled(); + static constexpr int FLAG_POS = 0; + return flags & (1U << FLAG_POS); } bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return false; - } - - return rp3dBody->isAllowedToSleep(); + static constexpr int FLAG_POS = 1; + return flags & (1U << FLAG_POS); } bool SHRigidBodyComponent::IsInterpolating() const noexcept @@ -71,151 +70,85 @@ namespace SHADE float SHRigidBodyComponent::GetMass() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return 0.0f; - } - - return rp3dBody->getMass(); + return mass; } float SHRigidBodyComponent::GetDrag() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return 0.0f; - } - - return rp3dBody->getLinearDamping(); + return drag; } float SHRigidBodyComponent::GetAngularDrag() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return 0.0f; - } - - return rp3dBody->getAngularDamping(); + return angularDrag; } bool SHRigidBodyComponent::GetFreezePositionX() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return false; - } - - const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor(); - return SHMath::CompareFloat(LINEAR_CONSTRAINTS.x, 0.0f); + static constexpr int FLAG_POS = 2; + return flags & (1U << FLAG_POS); } bool SHRigidBodyComponent::GetFreezePositionY() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return false; - } - - const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor(); - return SHMath::CompareFloat(LINEAR_CONSTRAINTS.y, 0.0f); + static constexpr int FLAG_POS = 3; + return flags & (1U << FLAG_POS); } bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return false; - } - - const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor(); - return SHMath::CompareFloat(LINEAR_CONSTRAINTS.z, 0.0f); + static constexpr int FLAG_POS = 4; + return flags & (1U << FLAG_POS); } bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return false; - } - - const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor(); - return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.x, 0.0f); + static constexpr int FLAG_POS = 5; + return flags & (1U << FLAG_POS); } bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return false; - } - - const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor(); - return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.y, 0.0f); + static constexpr int FLAG_POS = 6; + return flags & (1U << FLAG_POS); } bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return false; - } - - const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor(); - return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.z, 0.0f); + static constexpr int FLAG_POS = 7; + return flags & (1U << FLAG_POS); } SHVec3 SHRigidBodyComponent::GetForce() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return false; - } + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + return physicsObject->GetRigidBody()->getForce(); - return rp3dBody->getForce(); + return SHVec3::Zero; } SHVec3 SHRigidBodyComponent::GetTorque() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return SHVec3::Zero; - } + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + return physicsObject->GetRigidBody()->getTorque(); - return rp3dBody->getTorque(); + return SHVec3::Zero; } SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return SHVec3::Zero; - } + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + return physicsObject->GetRigidBody()->getLinearVelocity(); - return rp3dBody->getLinearVelocity(); + return SHVec3::Zero; } SHVec3 SHRigidBodyComponent::GetAngularVelocity() const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return SHVec3::Zero; - } + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + return physicsObject->GetRigidBody()->getAngularVelocity(); - return rp3dBody->getAngularVelocity(); + return SHVec3::Zero; } const SHVec3& SHRigidBodyComponent::GetPosition() const noexcept @@ -239,18 +172,13 @@ namespace SHADE void SHRigidBodyComponent::SetType(Type newType) noexcept { + static constexpr int FLAG_POS = 8; + if (type == newType) return; type = newType; - - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->setType(static_cast(type)); + dirtyFlags |= 1U << FLAG_POS; } void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept @@ -263,13 +191,8 @@ namespace SHADE return; } - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->enableGravity(enableGravity); + dirtyFlags |= 1U << FLAG_POS; + enableGravity ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept @@ -282,127 +205,92 @@ namespace SHADE return; } - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->setIsAllowedToSleep(isAllowedToSleep); + dirtyFlags |= 1U << FLAG_POS; + isAllowedToSleep ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept { + static constexpr int FLAG_POS = 2; + if (type == Type::STATIC) { SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID()) return; } - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - auto linearConstraints = rp3dBody->getLinearLockAxisFactor(); - linearConstraints.x = freezePositionX ? 0.0f : 1.0f; - rp3dBody->setLinearLockAxisFactor(linearConstraints); + dirtyFlags |= 1U << FLAG_POS; + freezePositionX ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept { + static constexpr int FLAG_POS = 3; + if (type == Type::STATIC) { SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID()) return; } - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - auto linearConstraints = rp3dBody->getLinearLockAxisFactor(); - linearConstraints.y = freezePositionY ? 0.0f : 1.0f; - rp3dBody->setLinearLockAxisFactor(linearConstraints); + dirtyFlags |= 1U << FLAG_POS; + freezePositionY ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept { + static constexpr int FLAG_POS = 4; + if (type == Type::STATIC) { SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID()) return; } - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - auto linearConstraints = rp3dBody->getLinearLockAxisFactor(); - linearConstraints.z = freezePositionZ ? 0.0f : 1.0f; - rp3dBody->setLinearLockAxisFactor(linearConstraints); + dirtyFlags |= 1U << FLAG_POS; + freezePositionZ ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept { + static constexpr int FLAG_POS = 5; + if (type == Type::STATIC) { SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID()) return; } - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - auto angularConstraints = rp3dBody->getAngularLockAxisFactor(); - angularConstraints.x = freezeRotationX ? 0.0f : 1.0f; - rp3dBody->setAngularLockAxisFactor(angularConstraints); + dirtyFlags |= 1U << FLAG_POS; + freezeRotationX ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept { + static constexpr int FLAG_POS = 6; + if (type == Type::STATIC) { SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID()) return; } - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - auto angularConstraints = rp3dBody->getAngularLockAxisFactor(); - angularConstraints.y = freezeRotationY ? 0.0f : 1.0f; - rp3dBody->setAngularLockAxisFactor(angularConstraints); + dirtyFlags |= 1U << FLAG_POS; + freezeRotationY ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept { + static constexpr int FLAG_POS = 7; + if (type == Type::STATIC) { SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID()) return; } - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - auto angularConstraints = rp3dBody->getAngularLockAxisFactor(); - angularConstraints.z = freezeRotationZ ? 0.0f : 1.0f; - rp3dBody->setAngularLockAxisFactor(angularConstraints); + dirtyFlags |= 1U << FLAG_POS; + freezeRotationZ ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept @@ -412,179 +300,127 @@ namespace SHADE void SHRigidBodyComponent::SetMass(float newMass) noexcept { + static constexpr int FLAG_POS = 9; + if (type != Type::DYNAMIC) { SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID()) return; } - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->setMass(newMass); + dirtyFlags |= 1U << FLAG_POS; + mass = newMass; } void SHRigidBodyComponent::SetDrag(float newDrag) noexcept { + static constexpr int FLAG_POS = 10; + if (type != Type::DYNAMIC) { SHLOG_WARNING("Cannot set drag of a non-dynamic object {}", GetEID()) return; } - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->setLinearDamping(newDrag); + dirtyFlags |= 1U << FLAG_POS; + drag = newDrag; } void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept { + static constexpr int FLAG_POS = 11; + if (type != Type::DYNAMIC) { SHLOG_WARNING("Cannot set angular drag of a non-dynamic object {}", GetEID()) return; } - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->setLinearDamping(newAngularDrag); + dirtyFlags |= 1U << FLAG_POS; + angularDrag = newAngularDrag; } void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept { + if (type == Type::STATIC) { SHLOG_WARNING("Cannot set linear velocity of a static object {}", GetEID()) return; } - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->setLinearVelocity(newLinearVelocity); + auto* physicsObject = system->GetPhysicsObject(GetEID()); + physicsObject->GetRigidBody()->setLinearVelocity(newLinearVelocity); } void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept { + static constexpr int FLAG_POS = 13; + if (type == Type::STATIC) { SHLOG_WARNING("Cannot set angular velocity of a static object {}", GetEID()) return; } - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->setAngularVelocity(newAngularVelocity); + auto* physicsObject = system->GetPhysicsObject(GetEID()); + physicsObject->GetRigidBody()->setAngularVelocity(newAngularVelocity); } /*-----------------------------------------------------------------------------------*/ /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept + void SHRigidBodyComponent::OnCreate() { - if (rp3dBody == nullptr) + auto* physicsSystem = SHSystemManager::GetSystem(); + if (!physicsSystem) { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) + SHLOG_ERROR("Physics System does not exist to link with Physics Components!") return; } - rp3dBody->applyWorldForceAtCenterOfMass(force); + system = physicsSystem; + } + + void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept + { + system->AddForce(GetEID(), force); } void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->applyWorldForceAtLocalPosition(force, localPos); + system->AddForceAtLocalPos(GetEID(), force, localPos); } void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->applyWorldForceAtWorldPosition(force, worldPos); + system->AddForceAtWorldPos(GetEID(), force, worldPos); } void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->applyLocalForceAtCenterOfMass(relativeForce); + system->AddRelativeForce(GetEID(), relativeForce); } void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->applyLocalForceAtLocalPosition(relativeForce, localPos); + system->AddRelativeForceAtLocalPos(GetEID(), relativeForce, localPos); } void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->applyLocalForceAtWorldPosition(relativeForce, worldPos); + system->AddRelativeForceAtWorldPos(GetEID(), relativeForce, worldPos); } void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->applyWorldTorque(torque); + system->AddTorque(GetEID(), torque); } void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept { - if (rp3dBody == nullptr) - { - SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID()) - return; - } - - rp3dBody->applyLocalTorque(relativeTorque); + system->AddRelativeTorque(GetEID(), relativeTorque); } } // namespace SHADE diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h similarity index 78% rename from SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h rename to SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h index ba7d2dd9..48a5d723 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h @@ -17,16 +17,6 @@ #include "Math/Vector/SHVec3.h" #include "Math/SHQuaternion.h" -//namespace SHADE -//{ -// class SHPhysicsSystem; -//} - -namespace reactphysics3d -{ - class RigidBody; -} - namespace SHADE { /*-----------------------------------------------------------------------------------*/ @@ -107,29 +97,31 @@ namespace SHADE /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetType (Type newType) noexcept; + void SetType (Type newType) noexcept; - void SetGravityEnabled (bool enableGravity) noexcept; - void SetIsAllowedToSleep(bool isAllowedToSleep) noexcept; - void SetFreezePositionX (bool freezePositionX) noexcept; - void SetFreezePositionY (bool freezePositionY) noexcept; - void SetFreezePositionZ (bool freezePositionZ) noexcept; - void SetFreezeRotationX (bool freezeRotationX) noexcept; - void SetFreezeRotationY (bool freezeRotationY) noexcept; - void SetFreezeRotationZ (bool freezeRotationZ) noexcept; - void SetInterpolate (bool allowInterpolation) noexcept; + void SetGravityEnabled (bool enableGravity) noexcept; + void SetIsAllowedToSleep (bool isAllowedToSleep) noexcept; + void SetFreezePositionX (bool freezePositionX) noexcept; + void SetFreezePositionY (bool freezePositionY) noexcept; + void SetFreezePositionZ (bool freezePositionZ) noexcept; + void SetFreezeRotationX (bool freezeRotationX) noexcept; + void SetFreezeRotationY (bool freezeRotationY) noexcept; + void SetFreezeRotationZ (bool freezeRotationZ) noexcept; + void SetInterpolate (bool allowInterpolation) noexcept; - void SetMass (float newMass) noexcept; - void SetDrag (float newDrag) noexcept; - void SetAngularDrag (float newAngularDrag) noexcept; + void SetMass (float newMass) noexcept; + void SetDrag (float newDrag) noexcept; + void SetAngularDrag (float newAngularDrag) noexcept; - void SetLinearVelocity (const SHVec3& newLinearVelocity) noexcept; - void SetAngularVelocity (const SHVec3& newAngularVelocity) noexcept; + void SetLinearVelocity (const SHVec3& newLinearVelocity) noexcept; + void SetAngularVelocity (const SHVec3& newAngularVelocity) noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ + void OnCreate () override; + void AddForce (const SHVec3& force) const noexcept; void AddForceAtLocalPos (const SHVec3& force, const SHVec3& localPos) const noexcept; void AddForceAtWorldPos (const SHVec3& force, const SHVec3& worldPos) const noexcept; @@ -147,15 +139,25 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ static constexpr size_t NUM_FLAGS = 8; - static constexpr size_t NUM_DIRTY_FLAGS = 16; + static constexpr size_t NUM_DIRTY_FLAGS = 12; - Type type; - bool interpolate; + Type type; - reactphysics3d::RigidBody* rp3dBody; + bool interpolate; + uint8_t flags; // aZ aY aX lZ lY lX slp g + uint16_t dirtyFlags; // 0 0 0 0 aD d m t aZ aY aX lZ lY lX slp g - SHVec3 position; - SHQuaternion orientation; + float mass; + float drag; + float angularDrag; + + SHVec3 linearVelocity; + SHVec3 angularVelocity; + + SHPhysicsSystem* system; + + SHVec3 position; + SHQuaternion orientation; RTTR_ENABLE() }; diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp new file mode 100644 index 00000000..d4668963 --- /dev/null +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp @@ -0,0 +1,361 @@ +/**************************************************************************************** + * \file SHPhysicsObject.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Physics Object. + * + * \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 + +// Primary Header +#include "SHPhysicsObject.h" + +// Project Headers +#include "ECS_Base/Managers/SHSystemManager.h" +#include "ECS_Base/Managers/SHComponentManager.h" + + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept + : entityID { eid } + , factory { physicsFactory } + , world { physicsWorld } + , rp3dBody { nullptr } + { + // Implicitly create a static body. + + const auto* TRANSFORM = SHComponentManager::GetComponent(eid); + + const rp3d::Transform RP3D_TRANSFORM { TRANSFORM->GetWorldPosition(), TRANSFORM->GetWorldOrientation() }; + + rp3dBody = world->createRigidBody(RP3D_TRANSFORM); + rp3dBody->setType(rp3d::BodyType::STATIC); + } + + SHPhysicsObject::~SHPhysicsObject() noexcept + { + factory = nullptr; + world = nullptr; + rp3dBody = nullptr; + } + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHVec3 SHPhysicsObject::GetPosition() const noexcept + { + return rp3dBody->getTransform().getPosition(); + } + + SHQuaternion SHPhysicsObject::GetOrientation() const noexcept + { + return rp3dBody->getTransform().getOrientation(); + } + + SHVec3 SHPhysicsObject::GetRotation() const noexcept + { + return SHQuaternion{ rp3dBody->getTransform().getOrientation() }.ToEuler(); + } + + rp3d::CollisionBody* SHPhysicsObject::GetCollisionBody() const noexcept + { + return rp3dBody; + } + + rp3d::RigidBody* SHPhysicsObject::GetRigidBody() const noexcept + { + return rp3dBody; + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsObject::SetStaticBody() const noexcept + { + if (!rp3dBody) + return; + + rp3dBody->setType(rp3d::BodyType::STATIC); + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + int SHPhysicsObject::AddCollisionShape(int index) const + { + // Get collider component + auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); + if (!colliderComponent) + { + SHLOGV_ERROR("Unable to add Collision Shape to Entity {} due to Missing Collider Component!", entityID) + return -1; + } + + auto& collisionShape = colliderComponent->GetCollisionShape(index); + switch (collisionShape.GetType()) + { + // TODO(Diren): Add more collider shapes + + case SHCollisionShape::Type::BOX: addBoxShape(collisionShape); break; + case SHCollisionShape::Type::SPHERE: addSphereShape(collisionShape); break; + default: break; + } + + return index; + } + + void SHPhysicsObject::RemoveCollisionShape(int index) const + { + const int NUM_COLLIDERS = static_cast(rp3dBody->getNbColliders()); + if (NUM_COLLIDERS == 0) + return; + + if (index < 0 || index >= NUM_COLLIDERS) + throw std::invalid_argument("Index out of range!"); + + auto* collider = rp3dBody->getCollider(index); + rp3dBody->removeCollider(collider); + } + + void SHPhysicsObject::RemoveAllCollisionShapes() const noexcept + { + int numColliders = static_cast(rp3dBody->getNbColliders()); + if (numColliders == 0) + return; + + while (numColliders >= 0) + { + auto* collider = rp3dBody->getCollider(numColliders); + rp3dBody->removeCollider(collider); + + --numColliders; + } + } + + void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent& component) const noexcept + { + if (component.dirtyFlags == 0) + return; + + for (size_t i = 0; i < SHRigidBodyComponent::NUM_DIRTY_FLAGS; ++i) + { + if (const bool IS_DIRTY = component.dirtyFlags & (1U << i); IS_DIRTY) + { + switch (i) + { + case 0: // Gravity + { + const bool IS_ENABLED = component.flags & (1U << i); + rp3dBody->enableGravity(IS_ENABLED); + + break; + } + case 1: // Sleeping + { + const bool IS_ENABLED = component.flags & (1U << i); + rp3dBody->setIsAllowedToSleep(IS_ENABLED); + + break; + } + case 2: // Lock Position X + { + const bool IS_ENABLED = component.flags & (1U << i); + + auto positionLock = rp3dBody->getLinearLockAxisFactor(); + positionLock.x = IS_ENABLED ? 0.0f : 1.0f; + rp3dBody->setLinearLockAxisFactor(positionLock); + + break; + } + case 3: // Lock Position Y + { + const bool IS_ENABLED = component.flags & (1U << i); + + auto positionLock = rp3dBody->getLinearLockAxisFactor(); + positionLock.y = IS_ENABLED ? 0.0f : 1.0f; + rp3dBody->setLinearLockAxisFactor(positionLock); + + break; + } + case 4: // Lock Position Z + { + const bool IS_ENABLED = component.flags & (1U << i); + + auto positionLock = rp3dBody->getLinearLockAxisFactor(); + positionLock.z = IS_ENABLED ? 0.0f : 1.0f; + rp3dBody->setLinearLockAxisFactor(positionLock); + + break; + } + case 5: // Lock Rotation X + { + const bool IS_ENABLED = component.flags & (1U << i); + + auto rotationLock = rp3dBody->getAngularLockAxisFactor(); + rotationLock.x = IS_ENABLED ? 0.0f : 1.0f; + rp3dBody->setAngularLockAxisFactor(rotationLock); + + break; + } + case 6: // Lock Rotation Y + { + const bool IS_ENABLED = component.flags & (1U << i); + + auto rotationLock = rp3dBody->getAngularLockAxisFactor(); + rotationLock.y = IS_ENABLED ? 0.0f : 1.0f; + rp3dBody->setAngularLockAxisFactor(rotationLock); + + break; + } + case 7: // Lock Rotation Z + { + const bool IS_ENABLED = component.flags & (1U << i); + + auto rotationLock = rp3dBody->getAngularLockAxisFactor(); + rotationLock.z = IS_ENABLED ? 0.0f : 1.0f; + rp3dBody->setAngularLockAxisFactor(rotationLock); + + break; + } + case 8: // Type + { + rp3dBody->setType(static_cast(component.type)); + + break; + } + case 9: // Mass + { + rp3dBody->setMass(component.mass); + rp3dBody->updateLocalInertiaTensorFromColliders(); + + break; + } + case 10: // Drag + { + rp3dBody->setLinearDamping(component.drag); + + break; + } + case 11: // Angular Drag + { + rp3dBody->setAngularDamping(component.angularDrag); + + break; + } + default: break; + } + } + } + + component.dirtyFlags = 0; + } + + void SHPhysicsObject::SyncColliders(SHColliderComponent& component) const noexcept + { + int index = 0; + for (auto& collisionShape : component.collisionShapes) + { + if (!collisionShape.dirty) + continue; + + switch (collisionShape.GetType()) + { + case SHCollisionShape::Type::BOX: syncBoxShape(index, collisionShape); break; + case SHCollisionShape::Type::SPHERE: syncSphereShape(index, collisionShape); break; + default: break; + } + + // TODO(Diren): Update Material + + collisionShape.dirty = false; + ++index; + } + } + + /*-----------------------------------------------------------------------------------*/ + /* Private Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsObject::addBoxShape(SHCollisionShape& boxShape) const noexcept + { + const rp3d::Transform OFFSETS + { + boxShape.GetPositionOffset() + , boxShape.GetRotationOffset() + }; + + const auto* BOX = reinterpret_cast(boxShape.GetShape()); + rp3d::BoxShape* newBox = factory->createBoxShape(BOX->GetWorldExtents()); + + rp3dBody->addCollider(newBox, OFFSETS); + + rp3dBody->updateLocalCenterOfMassFromColliders(); + rp3dBody->updateLocalInertiaTensorFromColliders(); + } + + void SHPhysicsObject::syncBoxShape(int index, SHCollisionShape& boxShape) const noexcept + { + const auto* BOX = reinterpret_cast(boxShape.GetShape()); + + auto* rp3dCollider = rp3dBody->getCollider(index); + auto* rp3dBox = reinterpret_cast(rp3dCollider->getCollisionShape()); + + const rp3d::Transform OFFSETS + { + boxShape.GetPositionOffset() + , boxShape.GetRotationOffset() + }; + + rp3dCollider->setIsTrigger(boxShape.IsTrigger()); + rp3dCollider->setLocalToBodyTransform(OFFSETS); + + rp3dBox->setHalfExtents(BOX->GetWorldExtents()); + } + + void SHPhysicsObject::addSphereShape(SHCollisionShape& sphereShape) const noexcept + { + const rp3d::Transform OFFSETS + { + sphereShape.GetPositionOffset() + , sphereShape.GetRotationOffset() + }; + + const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); + rp3d::SphereShape* newSphere = factory->createSphereShape(SPHERE->GetWorldRadius()); + + rp3dBody->addCollider(newSphere, OFFSETS); + + rp3dBody->updateLocalCenterOfMassFromColliders(); + rp3dBody->updateLocalInertiaTensorFromColliders(); + } + + void SHPhysicsObject::syncSphereShape(int index, SHCollisionShape& sphereShape) const noexcept + { + const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); + + auto* rp3dCollider = rp3dBody->getCollider(index); + auto* rp3dSphere = reinterpret_cast(rp3dCollider->getCollisionShape()); + + const rp3d::Transform OFFSETS + { + sphereShape.GetPositionOffset() + , sphereShape.GetRotationOffset() + }; + + rp3dCollider->setIsTrigger(sphereShape.IsTrigger()); + rp3dCollider->setLocalToBodyTransform(OFFSETS); + + rp3dSphere->setRadius(SPHERE->GetWorldRadius()); + } +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.h b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h similarity index 70% rename from SHADE_Engine/src/Physics/SHPhysicsObject.h rename to SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h index 09b70b11..f18a0738 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.h +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h @@ -14,8 +14,8 @@ // Project Headers #include "Math/Transform/SHTransformComponent.h" -#include "Components/SHRigidBodyComponent.h" -#include "Components/SHColliderComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" +#include "Physics/Interface/SHColliderComponent.h" namespace SHADE { @@ -31,6 +31,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ friend class SHPhysicsSystem; + friend class SHPhysicsObjectManager; public: /*---------------------------------------------------------------------------------*/ @@ -53,26 +54,29 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] SHVec3 GetPosition () const noexcept; - [[nodiscard]] SHQuaternion GetOrientation () const noexcept; - [[nodiscard]] SHVec3 GetRotation () const noexcept; + [[nodiscard]] SHVec3 GetPosition () const noexcept; + [[nodiscard]] SHQuaternion GetOrientation () const noexcept; + [[nodiscard]] SHVec3 GetRotation () const noexcept; + + [[nodiscard]] rp3d::CollisionBody* GetCollisionBody () const noexcept; + [[nodiscard]] rp3d::RigidBody* GetRigidBody () const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetPosition (const SHVec3& position) noexcept; - void SetOrientation (const SHQuaternion& orientation) noexcept; - void SetRotation (const SHVec3& rotation) noexcept; + void SetStaticBody () const noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - int AddCollider (SHCollisionShape* collider); - void RemoveCollider (int index); + int AddCollisionShape (int index) const; + void RemoveCollisionShape (int index) const; + void RemoveAllCollisionShapes () const noexcept; - void SyncColliders (SHColliderComponent* c) const noexcept; + void SyncRigidBody (SHRigidBodyComponent& component) const noexcept; + void SyncColliders (SHColliderComponent& component) const noexcept; private: /*---------------------------------------------------------------------------------*/ @@ -83,7 +87,22 @@ namespace SHADE rp3d::PhysicsCommon* factory; rp3d::PhysicsWorld* world; - rp3d::CollisionBody* rp3dBody; // Can be either a collision body or a rigid body + + rp3d::RigidBody* rp3dBody; rp3d::Transform prevTransform; // Cached transform for interpolation + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + // Box Shapes + + void addBoxShape (SHCollisionShape& boxShape) const noexcept; + void syncBoxShape (int index, SHCollisionShape& boxShape) const noexcept; + + // Sphere Shapes + + void addSphereShape (SHCollisionShape& sphereShape) const noexcept; + void syncSphereShape (int index, SHCollisionShape& sphereShape) const noexcept; }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp new file mode 100644 index 00000000..38a3c658 --- /dev/null +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp @@ -0,0 +1,266 @@ +/**************************************************************************************** + * \file SHPhysicsObjectManager.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Physics Object Manager. + * + * \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 + +// Primary Header +#include "SHPhysicsObjectManager.h" + +// Project Headers +#include "Tools/SHUtilities.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Static Data Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsObjectManager::CommandFunctionPtr SHPhysicsObjectManager::componentFunc[2][2] + { + addRigidBody , addCollider + , removeRigidBody , removeCollider + }; + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsObjectManager::SetFactory(rp3d::PhysicsCommon& physicsFactory) noexcept + { + factory = &physicsFactory; + } + + void SHPhysicsObjectManager::SetWorld(rp3d::PhysicsWorld& physicsWorld) noexcept + { + world = &physicsWorld; + } + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsObject* SHPhysicsObjectManager::GetPhysicsObject(EntityID eid) noexcept + { + const auto it = physicsObjects.find(eid); + if (it == physicsObjects.end()) + return nullptr; + + return &it->second; + } + + const SHPhysicsObjectManager::PhysicsObjectEntityMap SHPhysicsObjectManager::GetPhysicsObjects() const noexcept + { + return physicsObjects; + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsObjectManager::AddRigidBody(EntityID eid) noexcept + { + const QueueCommand NEW_QUEUE_COMMAND + { + .eid = eid + , .command = QueueCommand::Command::ADD + , .component = PhysicsComponents::RIGID_BODY + }; + + commandQueue.push(NEW_QUEUE_COMMAND); + } + + void SHPhysicsObjectManager::AddCollider(EntityID eid) noexcept + { + const QueueCommand NEW_QUEUE_COMMAND + { + .eid = eid + , .command = QueueCommand::Command::ADD + , .component = PhysicsComponents::COLLIDER + }; + + commandQueue.push(NEW_QUEUE_COMMAND); + } + + void SHPhysicsObjectManager::AddCollisionShape(EntityID eid, int shapeIndex) noexcept + { + const QueueCommand NEW_QUEUE_COMMAND + { + .eid = eid + , .command = QueueCommand::Command::ADD + , .component = PhysicsComponents::COLLISION_SHAPE + , .shapeIndex = shapeIndex + }; + + commandQueue.push(NEW_QUEUE_COMMAND); + } + + void SHPhysicsObjectManager::RemoveRigidBody(EntityID eid) noexcept + { + const QueueCommand NEW_QUEUE_COMMAND + { + .eid = eid + , .command = QueueCommand::Command::REMOVE + , .component = PhysicsComponents::RIGID_BODY + }; + + commandQueue.push(NEW_QUEUE_COMMAND); + } + + void SHPhysicsObjectManager::RemoveCollider(EntityID eid) noexcept + { + const QueueCommand NEW_QUEUE_COMMAND + { + .eid = eid + , .command = QueueCommand::Command::REMOVE + , .component = PhysicsComponents::COLLIDER + }; + + commandQueue.push(NEW_QUEUE_COMMAND); + } + + void SHPhysicsObjectManager::RemoveCollisionShape(EntityID eid, int shapeIndex) noexcept + { + const QueueCommand NEW_QUEUE_COMMAND + { + .eid = eid + , .command = QueueCommand::Command::REMOVE + , .component = PhysicsComponents::COLLISION_SHAPE + , .shapeIndex = shapeIndex + }; + + commandQueue.push(NEW_QUEUE_COMMAND); + } + + void SHPhysicsObjectManager::UpdateCommands() + { + if (commandQueue.empty()) + return; + + while (!commandQueue.empty()) + { + const QueueCommand COMMAND = commandQueue.front(); + commandQueue.pop(); + + // Check validity of command + if (COMMAND.command == QueueCommand::Command::INVALID || COMMAND.component == PhysicsComponents::INVALID) + continue; + + // Find the physics Object & retrieve components. Create an object if none exists. + SHPhysicsObject* physicsObject = GetPhysicsObject(COMMAND.eid); + if (!physicsObject) + physicsObject = createPhysicsObject(COMMAND.eid); + + const PhysicsComponentGroup COMPONENT_GROUP + { + .eid = COMMAND.eid + , .rigidBodyComponent = SHComponentManager::GetComponent_s(COMMAND.eid) + , .colliderComponent = SHComponentManager::GetComponent_s(COMMAND.eid) + }; + + if (COMMAND.component == PhysicsComponents::COLLISION_SHAPE) + { + if (COMMAND.command == QueueCommand::Command::ADD) + addCollisionShape(physicsObject, COMMAND.shapeIndex); + + if (COMMAND.command == QueueCommand::Command::REMOVE) + removeCollisionShape(physicsObject, COMMAND.shapeIndex); + } + else // Rigid Body or Collider + { + componentFunc[SHUtilities::ConvertEnum(COMMAND.command)][SHUtilities::ConvertEnum(COMMAND.component)](physicsObject, COMPONENT_GROUP); + } + + // If main components are missing, destroy object + if (!COMPONENT_GROUP.rigidBodyComponent && !COMPONENT_GROUP.colliderComponent) + destroyPhysicsObject(COMMAND.eid); + } + } + + void SHPhysicsObjectManager::RemoveAllObjects() + { + physicsObjects.clear(); + } + + + /*-----------------------------------------------------------------------------------*/ + /* Private Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsObject* SHPhysicsObjectManager::createPhysicsObject(EntityID eid) noexcept + { + auto newObjIter = physicsObjects.emplace(eid, SHPhysicsObject{ eid, factory, world }); + return &(newObjIter.first->second); + } + + void SHPhysicsObjectManager::destroyPhysicsObject(EntityID eid) noexcept + { + physicsObjects.erase(eid); + } + + void SHPhysicsObjectManager::addRigidBody(SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup) + { + SHASSERT(physicsObject != nullptr, "Valid physics object required to add body!") + + if (!componentGroup.rigidBodyComponent) + { + SHLOG_ERROR("Entity {} is missing a Rigidbody Component. Unable to update physics object!", componentGroup.eid) + return; + } + + // A static rigid body is implicitly created on creation of a physics object. + // We only need to sync rigid bodies here in the event it is non-static. + + physicsObject->SyncRigidBody(*componentGroup.rigidBodyComponent); + } + + void SHPhysicsObjectManager::addCollider(SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup) + { + SHASSERT(physicsObject != nullptr, "Valid physics object required to add collider!") + + if (!componentGroup.colliderComponent) + { + SHLOG_ERROR("Entity {} is missing a Rigidbody Component. Unable to update physics object!", componentGroup.eid) + return; + } + + physicsObject->SyncColliders(*componentGroup.colliderComponent); + } + + void SHPhysicsObjectManager::removeRigidBody(SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup) + { + SHASSERT(physicsObject != nullptr, "Valid physics object required to remove body!") + + if (componentGroup.colliderComponent) + physicsObject->SetStaticBody(); + } + + void SHPhysicsObjectManager::removeCollider(SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup) + { + SHASSERT(physicsObject != nullptr, "Valid physics object required to remove collider!") + + physicsObject->RemoveAllCollisionShapes(); + } + + void SHPhysicsObjectManager::addCollisionShape(SHPhysicsObject* physicsObject, int shapeIndex) + { + SHASSERT(physicsObject != nullptr, "Valid physics object required to add collision shape!") + + physicsObject->AddCollisionShape(shapeIndex); + } + + void SHPhysicsObjectManager::removeCollisionShape(SHPhysicsObject* physicsObject, int shapeIndex) + { + SHASSERT(physicsObject != nullptr, "Valid physics object required to remove collision shape!") + + physicsObject->RemoveCollisionShape(shapeIndex); + } + + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h new file mode 100644 index 00000000..f796b723 --- /dev/null +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h @@ -0,0 +1,178 @@ +/**************************************************************************************** + * \file SHPhysicsObjectManager.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Physics Object Manager. + * + * \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 +#include + +#include + +// Project Headers +#include "SHPhysicsObject.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + class SH_API SHPhysicsObjectManager + { + private: + /*---------------------------------------------------------------------------------*/ + /* Friends */ + /*---------------------------------------------------------------------------------*/ + + friend class SHPhysicsSystem; + + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + + using PhysicsObjectEntityMap = std::unordered_map; + + public: + + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + + enum class PhysicsComponents + { + RIGID_BODY + , COLLIDER + , COLLISION_SHAPE + + , TOTAL + , INVALID = -1 + }; + + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHPhysicsObjectManager () = default; + ~SHPhysicsObjectManager () = default; + + SHPhysicsObjectManager (const SHPhysicsObjectManager&) = delete; + SHPhysicsObjectManager (SHPhysicsObjectManager&&) = delete; + + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHPhysicsObjectManager& operator=(const SHPhysicsObjectManager&) = delete; + SHPhysicsObjectManager& operator=(SHPhysicsObjectManager&&) = delete; + + /*---------------------------------------------------------------------------------*/ + /* Getter Functions */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] SHPhysicsObject* GetPhysicsObject (EntityID eid) noexcept; + [[nodiscard]] const PhysicsObjectEntityMap GetPhysicsObjects () const noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*---------------------------------------------------------------------------------*/ + + void SetFactory (rp3d::PhysicsCommon& physicsFactory) noexcept; + void SetWorld (rp3d::PhysicsWorld& physicsWorld) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + void AddRigidBody (EntityID eid) noexcept; + void AddCollider (EntityID eid) noexcept; + void AddCollisionShape (EntityID eid, int shapeIndex) noexcept; + + void RemoveRigidBody (EntityID eid) noexcept; + void RemoveCollider (EntityID eid) noexcept; + void RemoveCollisionShape (EntityID eid, int shapeIndex) noexcept; + + void UpdateCommands (); + void RemoveAllObjects (); + + private: + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + + struct QueueCommand + { + /*-------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-------------------------------------------------------------------------------*/ + + enum class Command + { + ADD + , REMOVE + + , INVALID = -1 + }; + + /*-------------------------------------------------------------------------------*/ + /* Data Members */ + /*-------------------------------------------------------------------------------*/ + + EntityID eid = MAX_EID; + Command command = Command::INVALID; + PhysicsComponents component = PhysicsComponents::INVALID; + int shapeIndex = -1; // Only used when adding & removing collision shapes + }; + + struct PhysicsComponentGroup + { + public: + + /*-------------------------------------------------------------------------------*/ + /* Data Members */ + /*-------------------------------------------------------------------------------*/ + + + EntityID eid = MAX_EID; + SHRigidBodyComponent* rigidBodyComponent = nullptr; + SHColliderComponent* colliderComponent = nullptr; + }; + + using CommandFunctionPtr = void(*)(SHPhysicsObject*, const PhysicsComponentGroup&); + + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + static CommandFunctionPtr componentFunc[2][2]; // Used only for rigid body & collider components. Collision shapes are handled separately. + + rp3d::PhysicsCommon* factory = nullptr; + rp3d::PhysicsWorld* world = nullptr; + + PhysicsObjectEntityMap physicsObjects; + std::queue commandQueue; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + SHPhysicsObject* createPhysicsObject (EntityID eid) noexcept; + void destroyPhysicsObject (EntityID eid) noexcept; + + static void addRigidBody (SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); + static void addCollider (SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); + static void removeRigidBody (SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); + static void removeCollider (SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); + + static void addCollisionShape (SHPhysicsObject* physicsObject, int shapeIndex); + static void removeCollisionShape (SHPhysicsObject* physicsObject, int shapeIndex); + + }; + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsEvents.h b/SHADE_Engine/src/Physics/SHPhysicsEvents.h new file mode 100644 index 00000000..ae48a75b --- /dev/null +++ b/SHADE_Engine/src/Physics/SHPhysicsEvents.h @@ -0,0 +1,37 @@ +/**************************************************************************************** + * \file SHPhysicsUtils.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for some Physics Utilities + * + * \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 + +// Project Headers +#include "Interface/SHCollisionShape.h" + + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + struct SHPhysicsColliderAddedEvent + { + EntityID entityID; + SHCollisionShape::Type colliderType; + int colliderIndex; + }; + + struct SHPhysicsColliderRemovedEvent + { + EntityID entityID; + int colliderIndex; + }; + + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp deleted file mode 100644 index 26e3e786..00000000 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/**************************************************************************************** - * \file SHPhysicsObject.cpp - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Implementation for a Physics Object. - * - * \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 - -// Primary Header -#include "SHPhysicsObject.h" - -// Project Headers -#include "ECS_Base/Managers/SHSystemManager.h" -#include "ECS_Base/Managers/SHComponentManager.h" - - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Constructors & Destructor Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept - : entityID { eid } - , factory { physicsFactory } - , world { physicsWorld } - , rp3dBody { nullptr } - {} - - SHPhysicsObject::~SHPhysicsObject() noexcept - { - factory = nullptr; - world = nullptr; - rp3dBody = nullptr; - } - - /*-----------------------------------------------------------------------------------*/ - /* Getter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHVec3 SHPhysicsObject::GetPosition() const noexcept - { - SHVec3 result; - - if (rp3dBody) - result = SHVec3{ rp3dBody->getTransform().getPosition() }; - - return result; - } - - SHQuaternion SHPhysicsObject::GetOrientation() const noexcept - { - SHQuaternion result; - - if (rp3dBody) - result = SHQuaternion{ rp3dBody->getTransform().getOrientation() }; - - return result; - } - - SHVec3 SHPhysicsObject::GetRotation() const noexcept - { - SHVec3 result; - - if (rp3dBody) - result = SHQuaternion{ rp3dBody->getTransform().getOrientation() }.ToEuler(); - - return result; - } - - /*-----------------------------------------------------------------------------------*/ - /* Setter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHPhysicsObject::SetPosition(const SHVec3& position) noexcept - { - if (!rp3dBody) - { - SHLOG_ERROR("Cannot set position of a non-existent physics body for Entity {}", entityID) - return; - } - - rp3d::Transform rp3dTF; - rp3dTF.setPosition(position); - rp3dTF.setOrientation(rp3dBody->getTransform().getOrientation()); - - rp3dBody->setTransform(rp3dTF); - prevTransform = rp3dTF; - } - - void SHPhysicsObject::SetOrientation(const SHQuaternion& orientation) noexcept - { - if (!rp3dBody) - { - SHLOG_ERROR("Cannot set orientation of a non-existent physics body for Entity {}", entityID) - return; - } - - rp3d::Transform rp3dTF; - rp3dTF.setPosition(rp3dBody->getTransform().getPosition()); - rp3dTF.setOrientation(orientation); - - rp3dBody->setTransform(rp3dTF); - prevTransform = rp3dTF; - } - - void SHPhysicsObject::SetRotation(const SHVec3& rotation) noexcept - { - if (!rp3dBody) - { - SHLOG_ERROR("Cannot set rotation of a non-existent physics body for Entity {}", entityID) - return; - } - - rp3d::Transform rp3dTF; - rp3dTF.setPosition(rp3dBody->getTransform().getPosition()); - rp3dTF.setOrientation(rotation); - - rp3dBody->setTransform(rp3dTF); - prevTransform = rp3dTF; - } - - /*-----------------------------------------------------------------------------------*/ - /* Public Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - int SHPhysicsObject::AddCollider(SHCollisionShape* collider) - { - const rp3d::Transform OFFSETS{ collider->GetPositionOffset(), collider->GetRotationOffset() }; - - switch (collider->GetType()) - { - case SHCollisionShape::Type::BOX: - { - const auto* BOX = reinterpret_cast(collider->GetShape()); - rp3d::BoxShape* newBox = factory->createBoxShape(BOX->GetWorldExtents()); - - rp3dBody->addCollider(newBox, OFFSETS); - break; - } - case SHCollisionShape::Type::SPHERE: - { - const auto* SPHERE = reinterpret_cast(collider->GetShape()); - rp3d::SphereShape* newSphere = factory->createSphereShape(SPHERE->GetWorldRadius()); - - rp3dBody->addCollider(newSphere, OFFSETS); - break; - } - // TODO(Diren): Add more collider shapes - default: break; - } - - return static_cast(rp3dBody->getNbColliders()) - 1; - } - - void SHPhysicsObject::RemoveCollider(int index) - { - const int NUM_COLLIDERS = static_cast(rp3dBody->getNbColliders()); - if (NUM_COLLIDERS == 0) - return; - - if (index < 0 || index >= NUM_COLLIDERS) - throw std::invalid_argument("Index out of range!"); - - auto* collider = rp3dBody->getCollider(index); - rp3dBody->removeCollider(collider); - } - - void SHPhysicsObject::SyncColliders(SHColliderComponent* c) const noexcept - { - int index = 0; - for (auto& collider : c->collisionShapes) - { - if (!collider.dirty) - continue; - - auto* rp3dCollider = rp3dBody->getCollider(index); - - // Update trigger flag - rp3dCollider->setIsTrigger(collider.IsTrigger()); - - // Update offsets - rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), collider.GetRotationOffset())); - - switch (collider.GetType()) - { - case SHCollisionShape::Type::BOX: - { - const auto* BOX = reinterpret_cast(collider.GetShape()); - - auto* rp3dBoxShape = reinterpret_cast(rp3dCollider->getCollisionShape()); - rp3dBoxShape->setHalfExtents(BOX->GetWorldExtents()); - - break; - } - case SHCollisionShape::Type::SPHERE: - { - const auto* SPHERE = reinterpret_cast(collider.GetShape()); - - auto* rp3dSphereShape = reinterpret_cast(rp3dCollider->getCollisionShape()); - rp3dSphereShape->setRadius(SPHERE->GetWorldRadius()); - - break; - } - default: break; - } - - // TODO(Diren): Update Material - - collider.dirty = false; - ++index; - } - } - -} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp deleted file mode 100644 index 35d1b5de..00000000 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp +++ /dev/null @@ -1,706 +0,0 @@ -/**************************************************************************************** - * \file SHPhysicsSystem.cpp - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Implementation for the Physics 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 - -// Primary Header -#include "SHPhysicsSystem.h" - -// Project Headers -#include "ECS_Base/Managers/SHComponentManager.h" -#include "ECS_Base/Managers/SHEntityManager.h" -#include "ECS_Base/Managers/SHSystemManager.h" -#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h" -#include "Math/SHMathHelpers.h" -#include "Math/Transform/SHTransformComponent.h" -#include "Scene/SHSceneManager.h" -#include "Scripting/SHScriptEngine.h" -#include "Tools/SHUtilities.h" - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Constructors & Destructor Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHPhysicsSystem::SHPhysicsSystem() - : worldUpdated { false } - , interpolationFactor { 0.0 } - , fixedDT { 60.0 } - , world { nullptr } - {} - - SHPhysicsSystem::PhysicsPreUpdate::PhysicsPreUpdate() - : SHSystemRoutine { "Physics PreUpdate", true } - {} - - SHPhysicsSystem::PhysicsFixedUpdate::PhysicsFixedUpdate() - : SHFixedSystemRoutine { DEFAULT_FIXED_STEP, "Physics FixedUpdate", false } - {} - - SHPhysicsSystem::PhysicsPostUpdate::PhysicsPostUpdate() - : SHSystemRoutine { "Physics PostUpdate", false } - {} - - /*-----------------------------------------------------------------------------------*/ - /* Getter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - double SHPhysicsSystem::GetFixedDT() const noexcept - { - return fixedDT; - } - - bool SHPhysicsSystem::IsSleepingEnabled() const noexcept - { - if (world) - return world->isSleepingEnabled(); - - SHLOGV_WARNING("No physics world has been initialised!") - return false; - } - - SHVec3 SHPhysicsSystem::GetWorldGravity() const noexcept - { - SHVec3 result; - - if (world) - { - result = world->getGravity(); - } - else - { - SHLOGV_WARNING("No physics world has been initialised!") - } - - return result; - } - - uint16_t SHPhysicsSystem::GetNumberVelocityIterations() const noexcept - { - if (world) - return world->getNbIterationsVelocitySolver(); - - SHLOGV_WARNING("No physics world has been initialised!") - return 0; - } - - uint16_t SHPhysicsSystem::GetNumberPositionIterations() const noexcept - { - if (world) - return world->getNbIterationsPositionSolver(); - - SHLOGV_WARNING("No physics world has been initialised!") - return 0; - } - - const SHPhysicsSystem::EntityObjectMap& SHPhysicsSystem::GetPhysicsObjects() const noexcept - { - return map; - } - - const SHPhysicsSystem::CollisionEvents& SHPhysicsSystem::GetCollisionInfo() const noexcept - { - return collisionInfo; - } - - const SHPhysicsSystem::CollisionEvents& SHPhysicsSystem::GetTriggerInfo() const noexcept - { - return triggerInfo; - } - - /*-----------------------------------------------------------------------------------*/ - /* Setter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHPhysicsSystem::SetFixedDT(double fixedUpdateRate) noexcept - { - fixedDT = fixedUpdateRate; - } - - void SHPhysicsSystem::SetWorldGravity(const SHVec3& gravity) const noexcept - { - if (world) - { - world->setGravity(gravity); - } - else - { - SHLOGV_WARNING("No physics world has been initialised!") - } - } - - void SHPhysicsSystem::SetNumberVelocityIterations(uint16_t numVelIterations) const noexcept - { - if (world) - { - world->setNbIterationsVelocitySolver(numVelIterations); - } - else - { - SHLOGV_WARNING("No physics world has been initialised!") - } - } - - void SHPhysicsSystem::SetNumberPositionIterations(uint16_t numPosIterations) const noexcept - { - if (world) - { - world->setNbIterationsPositionSolver(numPosIterations); - } - else - { - SHLOGV_WARNING("No physics world has been initialised!") - } - } - - void SHPhysicsSystem::SetSleepingEnabled(bool enableSleeping) const noexcept - { - if (world) - { - world->enableSleeping(enableSleeping); - } - else - { - SHLOGV_WARNING("No physics world has been initialised!") - } - } - - void SHPhysicsSystem::SetWorldSettings(const WorldSettings& settings) const noexcept - { - if (world) - { - world->setGravity(settings.gravity); - world->setNbIterationsVelocitySolver(settings.numVelocitySolverIterations); - world->setNbIterationsPositionSolver(settings.numPositionSolverIterations); - world->enableSleeping(settings.sleepingEnabled); - } - else - { - SHLOGV_WARNING("No physics world has been initialised!") - } - } - - /*-----------------------------------------------------------------------------------*/ - /* Public Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHPhysicsSystem::Init() - { - // Create a physics world with the default settings - rp3d::PhysicsWorld::WorldSettings settings; - settings.gravity = SHVec3{ 0.0f, -9.81f, 0.0f }; - settings.isSleepingEnabled = true; - settings.defaultVelocitySolverNbIterations = 8; - settings.defaultPositionSolverNbIterations = 3; - settings.defaultFrictionCoefficient = 0.4f; - settings.defaultBounciness = 0.0f; - - world = factory.createPhysicsWorld(settings); - world->setEventListener(this); - world->setIsDebugRenderingEnabled(true); - - // Set up solvers - world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES); - - // Subscribe to component events - - const std::shared_ptr ADD_COMPONENT_RECEIVER { std::make_shared>(this, &SHPhysicsSystem::AddPhysicsComponent) }; - const ReceiverPtr ADD_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast(ADD_COMPONENT_RECEIVER); - SHEventManager::SubscribeTo(SH_COMPONENT_ADDED_EVENT, ADD_COMPONENT_RECEIVER_PTR); - - const std::shared_ptr REMOVE_COMPONENT_RECEIVER { std::make_shared>(this, &SHPhysicsSystem::RemovePhysicsComponent) }; - const ReceiverPtr REMOVE_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast(REMOVE_COMPONENT_RECEIVER); - SHEventManager::SubscribeTo(SH_COMPONENT_REMOVED_EVENT, REMOVE_COMPONENT_RECEIVER_PTR); - - #ifdef SHEDITOR - const std::shared_ptr EDITOR_STOP_RECEIVER { std::make_shared>(this, &SHPhysicsSystem::ResetWorld) }; - const ReceiverPtr EDITOR_STOP_RECEIVER_PTR = std::dynamic_pointer_cast(EDITOR_STOP_RECEIVER); - SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, EDITOR_STOP_RECEIVER_PTR); - #endif - } - - void SHPhysicsSystem::Exit() - { - factory.destroyPhysicsWorld(world); - } - - void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHCollisionShape* collider) - { - auto* physicsObject = GetPhysicsObject(entityID); - - const SHPhysicsColliderAddedEvent COLLIDER_ADDED_EVENT_DATA - { - .entityID = entityID - , .colliderType = collider->GetType() - , .colliderIndex = physicsObject->AddCollider(collider) - }; - - SHEventManager::BroadcastEvent(COLLIDER_ADDED_EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT); - } - - void SHPhysicsSystem::RemoveCollisionShape(EntityID entityID, int index) - { - auto* physicsObject = GetPhysicsObject(entityID); - physicsObject->RemoveCollider(index); - - const SHPhysicsColliderRemovedEvent COLLIDER_REMOVED_EVENT_DATA - { - .entityID = entityID - , .colliderIndex = index - }; - - SHEventManager::BroadcastEvent(COLLIDER_REMOVED_EVENT_DATA, SH_PHYSICS_COLLIDER_REMOVED_EVENT); - } - - void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept - { - auto* system = reinterpret_cast(GetSystem()); - - // Sync transforms - for (auto& [entityID, physicsObject] : system->map) - { - // Ensure a valid physics Object - if (physicsObject.rp3dBody == nullptr) - continue; - - const auto* transformComponent = SHComponentManager::GetComponent_s(entityID); - auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); - auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); - - if (transformComponent && transformComponent->HasChanged()) - { - const auto WORLD_POS = transformComponent->GetWorldPosition(); - const auto WORLD_ROT = transformComponent->GetWorldOrientation(); - const auto WORLD_SCL = transformComponent->GetWorldScale(); - - physicsObject.SetPosition(WORLD_POS); - physicsObject.SetOrientation(WORLD_ROT); - - // Sync physics component transforms - - if (rigidBodyComponent) - { - rigidBodyComponent->position = WORLD_POS; - rigidBodyComponent->orientation = WORLD_ROT; - } - - if (colliderComponent) - { - colliderComponent->position = WORLD_POS; - colliderComponent->orientation = WORLD_ROT; - colliderComponent->scale = WORLD_SCL; - - colliderComponent->RecomputeCollisionShapes(); - } - } - - // Sync rigid bodies - - if (rigidBodyComponent) - { - // Sync active states - const bool COMPONENT_ACTIVE = rigidBodyComponent->isActive; - SyncActiveStates(physicsObject, COMPONENT_ACTIVE); - - if (!COMPONENT_ACTIVE) - continue; - } - - // Sync colliders - - if (colliderComponent) - { - const bool COMPONENT_ACTIVE = colliderComponent->isActive; - SyncActiveStates(physicsObject, colliderComponent->isActive); - - if (!COMPONENT_ACTIVE) - continue; - - physicsObject.SyncColliders(colliderComponent); - } - } - } - - void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept - { - auto* physicsSystem = reinterpret_cast(GetSystem()); - auto* scriptingSystem = SHSystemManager::GetSystem(); - if (scriptingSystem == nullptr) - { - SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!"); - } - - fixedTimeStep = 1.0 / physicsSystem->fixedDT; - accumulatedTime += dt; - - int count = 0; - while (accumulatedTime > fixedTimeStep) - { - if (scriptingSystem != nullptr) - scriptingSystem->ExecuteFixedUpdates(); - - physicsSystem->world->update(static_cast(fixedTimeStep)); - - accumulatedTime -= fixedTimeStep; - ++count; - } - - stats.numSteps = count; - physicsSystem->worldUpdated = count > 0; - - physicsSystem->interpolationFactor = accumulatedTime / fixedTimeStep; - } - - void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept - { - auto* physicsSystem = reinterpret_cast(GetSystem()); - auto* scriptingSystem = SHSystemManager::GetSystem(); - if (scriptingSystem == nullptr) - { - SHLOGV_ERROR("Unable to invoke collision and trigger script events due to missing SHScriptEngine!"); - } - - // Interpolate transforms for rendering - if (physicsSystem->worldUpdated) - { - physicsSystem->SyncTransforms(); - - // Collision & Trigger messages - if (scriptingSystem != nullptr) - scriptingSystem->ExecuteCollisionFunctions(); - - physicsSystem->ClearInvalidCollisions(); - } - } - - void SHPhysicsSystem::onContact(const CallbackData& callbackData) - { - for (uint32_t i = 0; i < callbackData.getNbContactPairs(); ++i) - { - const auto CONTACT_PAIR = callbackData.getContactPair(i); - const SHCollisionEvent NEW_EVENT = GenerateCollisionEvent(CONTACT_PAIR); - - UpdateEventContainers(NEW_EVENT, collisionInfo); - } - } - - void SHPhysicsSystem::onTrigger(const rp3d::OverlapCallback::CallbackData& callbackData) - { - for (uint32_t i = 0; i < callbackData.getNbOverlappingPairs(); ++i) - { - const auto& OVERLAP_PAIR = callbackData.getOverlappingPair(i); - const SHCollisionEvent NEW_EVENT = GenerateCollisionEvent(OVERLAP_PAIR); - - UpdateEventContainers(NEW_EVENT, triggerInfo); - } - } - - /*-----------------------------------------------------------------------------------*/ - /* Private Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHPhysicsObject* SHPhysicsSystem::EnsurePhysicsObject(EntityID entityID) noexcept - { - const auto it = map.find(entityID); - if (it == map.end()) - { - auto* newPhysicsObject = &map.emplace(entityID, SHPhysicsObject{entityID, &factory, world}).first->second; - return newPhysicsObject; - } - - return &(it->second); - } - - SHPhysicsObject* SHPhysicsSystem::GetPhysicsObject(EntityID entityID) noexcept - { - const auto it = map.find(entityID); - if (it == map.end()) - { - //SHLOG_ERROR("Entity {} is not in the physics system!", entityID) - return nullptr; - } - - return &(it->second); - } - - void SHPhysicsSystem::DestroyPhysicsObject(EntityID entityID) noexcept - { - map.erase(entityID); - } - - void SHPhysicsSystem::SyncActiveStates(SHPhysicsObject& physicsObject, bool componentActive) noexcept - { - const bool RP3D_ACTIVE = physicsObject.rp3dBody->isActive(); - if (RP3D_ACTIVE != componentActive) - physicsObject.rp3dBody->setIsActive(componentActive); - } - - void SHPhysicsSystem::SyncTransforms() noexcept - { - for (auto& [entityID, physicsObject] : map) - { - rp3d::Vector3 rp3dPos; - rp3d::Quaternion rp3dRot; - - const rp3d::Transform CURRENT_TF = physicsObject.rp3dBody->getTransform(); - - auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); - auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); - - // Check if transform should be interpolated - - if (rigidBodyComponent != nullptr) - { - if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC) - continue; - - if (rigidBodyComponent->IsInterpolating()) - { - const rp3d::Transform PREV_TF = physicsObject.prevTransform; - const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast(interpolationFactor)); - - - rp3dPos = INTERPOLATED_TF.getPosition(); - rp3dRot = INTERPOLATED_TF.getOrientation(); - } - else - { - rp3dPos = CURRENT_TF.getPosition(); - rp3dRot = CURRENT_TF.getOrientation(); - } - - rigidBodyComponent->position = CURRENT_TF.getPosition(); - rigidBodyComponent->orientation = CURRENT_TF.getOrientation(); - - if (colliderComponent != nullptr) - { - - colliderComponent->position = CURRENT_TF.getPosition(); - colliderComponent->orientation = CURRENT_TF.getOrientation(); - } - } - else - { - rp3dPos = CURRENT_TF.getPosition(); - rp3dRot = CURRENT_TF.getOrientation(); - } - - // Convert RP3D Transform to SHADE - auto* transformComponent = SHComponentManager::GetComponent_s(entityID); - - if (transformComponent != nullptr) - { - transformComponent->SetWorldPosition(rp3dPos); - transformComponent->SetWorldOrientation(rp3dRot); - } - - // Cache transforms - physicsObject.prevTransform = CURRENT_TF; - } - } - - void SHPhysicsSystem::UpdateEventContainers(const SHCollisionEvent& collisionEvent, CollisionEvents& container) noexcept - { - const auto IT = std::ranges::find_if(container.begin(), container.end(), [&](const SHCollisionEvent& e) - { - const bool ENTITY_MATCH = (e.ids[0] == collisionEvent.ids[0] && e.ids[1] == collisionEvent.ids[1]) - || (e.ids[0] == collisionEvent.ids[1] && e.ids[1] == collisionEvent.ids[0]); - const bool COLLIDERS_MATCH = (e.ids[2] == collisionEvent.ids[2] && e.ids[3] == collisionEvent.ids[3]) - || (e.ids[2] == collisionEvent.ids[3] && e.ids[3] == collisionEvent.ids[2]); - return ENTITY_MATCH && COLLIDERS_MATCH; - }); - - if (IT == container.end()) - container.emplace_back(collisionEvent); - else - IT->collisionState = collisionEvent.collisionState; - } - - void SHPhysicsSystem::ClearInvalidCollisions() noexcept - { - static const auto CLEAR = [](CollisionEvents& container) - { - for (auto eventIter = container.begin(); eventIter != container.end();) - { - const bool CLEAR_EVENT = eventIter->GetCollisionState() == SHCollisionEvent::State::EXIT - || eventIter->GetCollisionState() == SHCollisionEvent::State::INVALID; - - if (CLEAR_EVENT) - eventIter = container.erase(eventIter); - else - ++eventIter; - } - }; - - CLEAR(collisionInfo); - CLEAR(triggerInfo); - } - - SHEventHandle SHPhysicsSystem::AddPhysicsComponent(SHEventPtr addComponentEvent) - { - const auto& EVENT_DATA = reinterpret_cast*>(addComponentEvent.get()); - - static const auto RIGID_BODY_ID = ComponentFamily::GetID(); - static const auto COLLIDER_ID = ComponentFamily::GetID(); - - const auto ADDED_ID = EVENT_DATA->data->addedComponentType; - const bool IS_PHYSICS_COMPONENT = ADDED_ID == RIGID_BODY_ID || ADDED_ID == COLLIDER_ID; - if (IS_PHYSICS_COMPONENT) - { - const EntityID ENTITY_ID = EVENT_DATA->data->eid; - auto* physicsObject = EnsurePhysicsObject(ENTITY_ID); - - auto* transformComponent = SHComponentManager::GetComponent_s(ENTITY_ID); - if (transformComponent == nullptr) - { - SHLOG_ERROR("Entity {} cannot add a Physics Component without a Transform! Component not created!", ENTITY_ID) - return EVENT_DATA->handle; - } - - auto* rigidBodyComponent = SHComponentManager::GetComponent_s(ENTITY_ID); - auto* colliderComponent = SHComponentManager::GetComponent_s(ENTITY_ID); - - if (ADDED_ID == RIGID_BODY_ID) - { - if (colliderComponent != nullptr) - { - world->destroyCollisionBody(physicsObject->rp3dBody); - physicsObject->rp3dBody = nullptr; - } - - rigidBodyComponent->position = transformComponent->GetWorldPosition(); - rigidBodyComponent->orientation = transformComponent->GetWorldOrientation(); - - physicsObject->rp3dBody = world->createRigidBody - ( - rp3d::Transform{ rigidBodyComponent->position, rigidBodyComponent->orientation } - ); - - rigidBodyComponent->rp3dBody = reinterpret_cast(physicsObject->rp3dBody); - - // Add collision shapes back into the body - if (colliderComponent != nullptr) - { - for (auto& collider : colliderComponent->collisionShapes) - physicsObject->AddCollider(&collider); - } - } - - if (ADDED_ID == COLLIDER_ID) - { - SHASSERT(colliderComponent != nullptr, "Collider Component was not added to Entity " + std::to_string(ENTITY_ID) + "!"); - - colliderComponent->position = transformComponent->GetWorldPosition(); - colliderComponent->orientation = transformComponent->GetWorldOrientation(); - colliderComponent->scale = transformComponent->GetWorldScale(); - - if (physicsObject->rp3dBody == nullptr) - { - physicsObject->rp3dBody = world->createCollisionBody - ( - rp3d::Transform{ colliderComponent->position, colliderComponent->orientation } - ); - } - - // Add Collision Shapes - for (auto& collider : colliderComponent->collisionShapes) - physicsObject->AddCollider(&collider); - } - } - - return EVENT_DATA->handle; - } - - SHEventHandle SHPhysicsSystem::RemovePhysicsComponent(SHEventPtr removeComponentEvent) - { - const auto& EVENT_DATA = reinterpret_cast*>(removeComponentEvent.get()); - - static const auto RIGID_BODY_ID = ComponentFamily::GetID(); - static const auto COLLIDER_ID = ComponentFamily::GetID(); - - const auto REMOVED_ID = EVENT_DATA->data->removedComponentType; - const bool IS_PHYSICS_COMPONENT = REMOVED_ID == RIGID_BODY_ID || REMOVED_ID == COLLIDER_ID; - if (IS_PHYSICS_COMPONENT) - { - const EntityID ENTITY_ID = EVENT_DATA->data->eid; - auto* physicsObject = GetPhysicsObject(ENTITY_ID); - - auto* rigidBodyComponent = SHComponentManager::GetComponent_s(ENTITY_ID); - auto* colliderComponent = SHComponentManager::GetComponent_s(ENTITY_ID); - - // Wake up all physics objects - for (auto& [entityID, object] : map) - { - if (SHComponentManager::HasComponent(entityID)) - reinterpret_cast(object.rp3dBody)->setIsSleeping(false); - } - - if (REMOVED_ID == RIGID_BODY_ID && physicsObject != nullptr) - { - world->destroyRigidBody(reinterpret_cast(physicsObject->rp3dBody)); - physicsObject->rp3dBody = nullptr; - - if (colliderComponent != nullptr) - { - // Preserve colliders as a collision body - physicsObject->rp3dBody = world->createCollisionBody - ( - rp3d::Transform{ colliderComponent->position, colliderComponent->orientation } - ); - - for (auto& collider : colliderComponent->collisionShapes) - physicsObject->AddCollider(&collider); - } - } - - if (REMOVED_ID == COLLIDER_ID && physicsObject != nullptr) - { - // Remove all colliders - const int NUM_COLLIDERS = static_cast(physicsObject->rp3dBody->getNbColliders()); - - for (int i = NUM_COLLIDERS - 1; i >= 0; --i) - { - auto* collider = physicsObject->rp3dBody->getCollider(i); - physicsObject->rp3dBody->removeCollider(collider); - } - - // Check for a rigidbody component - if (rigidBodyComponent == nullptr) - physicsObject->rp3dBody = nullptr; - } - - if (physicsObject != nullptr && physicsObject->rp3dBody == nullptr) - DestroyPhysicsObject(ENTITY_ID); - } - - return EVENT_DATA->handle; - } - - SHEventHandle SHPhysicsSystem::ResetWorld(SHEventPtr editorStopEvent) - { - // TODO(Diren): Rebuild world based on how scene reloading is done - - for (auto& [entityID, physicsObject] : map) - { - if (SHComponentManager::HasComponent(entityID)) - { - auto* rp3dRigidBody = reinterpret_cast(physicsObject.rp3dBody); - rp3dRigidBody->resetForce(); - rp3dRigidBody->resetTorque(); - rp3dRigidBody->setLinearVelocity(SHVec3::Zero); - rp3dRigidBody->setAngularVelocity(SHVec3::Zero); - } - } - - return editorStopEvent->handle; - } - -} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.hpp b/SHADE_Engine/src/Physics/SHPhysicsSystem.hpp deleted file mode 100644 index 957fb3aa..00000000 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.hpp +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************************** - * \file SHPhysicsSystem.hpp - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Implementation for templated functions the Physics 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 - -// Primary Header -#include "SHPhysicsSystem.h" - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Private Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - template - SHCollisionEvent SHPhysicsSystem::GenerateCollisionEvent(const RP3DCollisionPair& cp) noexcept - { - static const auto MATCH_COLLIDER = [] - ( - const SHPhysicsObject& physicsObject - , const rp3d::Entity colliderID - )->uint32_t - { - for (uint32_t i = 0; i < physicsObject.rp3dBody->getNbColliders(); ++i) - { - const auto* collider = physicsObject.rp3dBody->getCollider(i); - if (collider->getEntity() == colliderID) - return i; - } - - return std::numeric_limits::max(); - }; - - SHCollisionEvent cInfo; - - // Update collision state - cInfo.collisionState = static_cast(cp.getEventType()); - - // Match body and collider for collision event - const rp3d::Entity body1 = cp.getBody1()->getEntity(); - const rp3d::Entity body2 = cp.getBody2()->getEntity(); - const rp3d::Entity collider1 = cp.getCollider1()->getEntity(); - const rp3d::Entity collider2 = cp.getCollider2()->getEntity(); - - // Find and match both ids - bool matched[2] = { false, false }; - - - for (auto& [entityID, physicsObject] : map) - { - // Match body 1 - if (matched[SHCollisionEvent::ENTITY_A] == false && physicsObject.rp3dBody->getEntity() == body1) - { - cInfo.ids[SHCollisionEvent::ENTITY_A] = entityID; - cInfo.ids[SHCollisionEvent::COLLIDER_A] = MATCH_COLLIDER(physicsObject, collider1); - - matched[SHCollisionEvent::ENTITY_A] = true; - } - - // Match body 2 - if (matched[SHCollisionEvent::ENTITY_B] == false && physicsObject.rp3dBody->getEntity() == body2) - { - cInfo.ids[SHCollisionEvent::ENTITY_B] = entityID; - cInfo.ids[SHCollisionEvent::COLLIDER_B] = MATCH_COLLIDER(physicsObject, collider2); - - matched[SHCollisionEvent::ENTITY_B] = true; - } - - if (matched[SHCollisionEvent::ENTITY_A] == true && matched[SHCollisionEvent::ENTITY_B] == true) - return cInfo; - } - - return cInfo; - } -} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsWorld.cpp b/SHADE_Engine/src/Physics/SHPhysicsWorld.cpp new file mode 100644 index 00000000..1326ea3e --- /dev/null +++ b/SHADE_Engine/src/Physics/SHPhysicsWorld.cpp @@ -0,0 +1,66 @@ +/**************************************************************************************** + * \file SHPhysicsWorld.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Physics World. + * + * \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 + +// Primary Header +#include "SHPhysicsWorld.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsWorldState::SHPhysicsWorldState() noexcept + : world { nullptr } + {} + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Members Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsWorldState::CreateWorld(rp3d::PhysicsCommon& factory) + { + rp3d::PhysicsWorld::WorldSettings rp3dWorldSettings; + rp3dWorldSettings.gravity = settings.gravity; + rp3dWorldSettings.defaultVelocitySolverNbIterations = settings.numVelocitySolverIterations; + rp3dWorldSettings.defaultPositionSolverNbIterations = settings.numPositionSolverIterations; + rp3dWorldSettings.isSleepingEnabled = settings.sleepingEnabled; + + world = factory.createPhysicsWorld(rp3dWorldSettings); + } + + void SHPhysicsWorldState::DestroyWorld(rp3d::PhysicsCommon& factory) + { + if (!world) + return; + + factory.destroyPhysicsWorld(world); + world = nullptr; + } + + void SHPhysicsWorldState::UpdateSettings() const noexcept + { + if (!world) + { + SHLOGV_ERROR("Unable to update Physics World settings without creating a world!") + return; + } + + world->setGravity(settings.gravity); + world->setNbIterationsVelocitySolver(settings.numVelocitySolverIterations); + world->setNbIterationsPositionSolver(settings.numPositionSolverIterations); + world->enableSleeping(settings.sleepingEnabled); + } + + + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsWorld.h b/SHADE_Engine/src/Physics/SHPhysicsWorld.h new file mode 100644 index 00000000..bf788c0f --- /dev/null +++ b/SHADE_Engine/src/Physics/SHPhysicsWorld.h @@ -0,0 +1,74 @@ +/**************************************************************************************** + * \file SHPhysicsWorld.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Physics World. + * + * \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 + +// Project Headers +#include "Math/SHMath.h" +#include "SH_API.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + struct SH_API SHPhysicsWorldState + { + public: + + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + + struct WorldSettings + { + public: + /*-------------------------------------------------------------------------------*/ + /* Data Members */ + /*-------------------------------------------------------------------------------*/ + + SHVec3 gravity = SHVec3{ 0.0f, -9.81f, 0.0f }; + uint16_t numVelocitySolverIterations = 8; + uint16_t numPositionSolverIterations = 3; + bool sleepingEnabled = true; + }; + + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + rp3d::PhysicsWorld* world; + WorldSettings settings; + + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHPhysicsWorldState() noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + void CreateWorld (rp3d::PhysicsCommon& factory); + void DestroyWorld (rp3d::PhysicsCommon& factory); + + /** + * @brief Applies the current settings to the physics world. The world must be created + * before this is called. + */ + void UpdateSettings () const noexcept; + }; + + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsDebugDrawSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp similarity index 100% rename from SHADE_Engine/src/Physics/SHPhysicsDebugDrawSystem.cpp rename to SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp diff --git a/SHADE_Engine/src/Physics/SHPhysicsDebugDrawSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h similarity index 100% rename from SHADE_Engine/src/Physics/SHPhysicsDebugDrawSystem.h rename to SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp new file mode 100644 index 00000000..ad137ed4 --- /dev/null +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -0,0 +1,307 @@ +/**************************************************************************************** + * \file SHPhysicsSystem.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for the Physics 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 + +// Primary Header +#include "SHPhysicsSystem.h" + +// Project Headers +#include "ECS_Base/Managers/SHComponentManager.h" +#include "ECS_Base/Managers/SHEntityManager.h" +#include "ECS_Base/Managers/SHSystemManager.h" +#include "Editor/SHEditor.h" +#include "Math/Transform/SHTransformComponent.h" +#include "Physics/SHPhysicsEvents.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsSystem::SHPhysicsSystem() + : worldUpdated { false } + , interpolationFactor { 0.0 } + , fixedDT { 60.0 } + {} + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + double SHPhysicsSystem::GetFixedDT() const noexcept + { + return fixedDT; + } + + const SHPhysicsWorldState::WorldSettings& SHPhysicsSystem::GetWorldSettings() const noexcept + { + return worldState.settings; + } + + const std::vector& SHPhysicsSystem::GetAllCollisionInfo() const noexcept + { + return collisionListener.GetCollisionInfoContainer(); + } + + const std::vector& SHPhysicsSystem::GetAllTriggerInfo() const noexcept + { + return collisionListener.GetTriggerInfoContainer(); + } + + const SHPhysicsObject* const SHPhysicsSystem::GetPhysicsObject(EntityID eid) noexcept + { + return objectManager.GetPhysicsObject(eid); + } + + + const SHPhysicsObjectManager::PhysicsObjectEntityMap& SHPhysicsSystem::GetPhysicsObjects() const noexcept + { + return objectManager.physicsObjects; + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsSystem::SetFixedDT(double fixedUpdateRate) noexcept + { + fixedDT = fixedUpdateRate; + } + + void SHPhysicsSystem::SetWorldSettings(const SHPhysicsWorldState::WorldSettings& settings) noexcept + { + worldState.settings = settings; + worldState.UpdateSettings(); + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsSystem::Init() + { + // Subscribe to component events + const std::shared_ptr ADD_COMPONENT_RECEIVER { std::make_shared>(this, &SHPhysicsSystem::addPhysicsComponent) }; + const ReceiverPtr ADD_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast(ADD_COMPONENT_RECEIVER); + SHEventManager::SubscribeTo(SH_COMPONENT_ADDED_EVENT, ADD_COMPONENT_RECEIVER_PTR); + + const std::shared_ptr REMOVE_COMPONENT_RECEIVER { std::make_shared>(this, &SHPhysicsSystem::removePhysicsComponent) }; + const ReceiverPtr REMOVE_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast(REMOVE_COMPONENT_RECEIVER); + SHEventManager::SubscribeTo(SH_COMPONENT_REMOVED_EVENT, REMOVE_COMPONENT_RECEIVER_PTR); + + #ifdef SHEDITOR + + // Subscribe to Editor State Change Events + const std::shared_ptr ON_PLAY_RECEIVER { std::make_shared>(this, &SHPhysicsSystem::onPlay) }; + const ReceiverPtr ON_PLAY_RECEIVER_PTR = std::dynamic_pointer_cast(ON_PLAY_RECEIVER); + SHEventManager::SubscribeTo(SH_EDITOR_ON_PLAY_EVENT, ON_PLAY_RECEIVER_PTR); + + const std::shared_ptr ON_STOP_RECEIVER { std::make_shared>(this, &SHPhysicsSystem::onStop) }; + const ReceiverPtr ON_STOP_RECEIVER_PTR = std::dynamic_pointer_cast(ON_STOP_RECEIVER); + SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, ON_STOP_RECEIVER_PTR); + + #endif + // Link Physics Object Manager with System + objectManager.SetFactory(factory); + + // Link Collision Listener with System + collisionListener.BindToSystem(this); + } + + void SHPhysicsSystem::Exit() + { + worldState.DestroyWorld(factory); + } + + void SHPhysicsSystem::AddCollisionShape(EntityID eid, int shapeIndex) + { + objectManager.AddCollisionShape(eid, shapeIndex); + + const SHPhysicsColliderAddedEvent COLLIDER_ADDED_EVENT_DATA + { + .entityID = eid + , .colliderType = SHComponentManager::GetComponent(eid)->GetCollisionShape(shapeIndex).GetType() + , .colliderIndex = shapeIndex + }; + + SHEventManager::BroadcastEvent(COLLIDER_ADDED_EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT); + } + + void SHPhysicsSystem::RemoveCollisionShape(EntityID eid, int shapeIndex) + { + objectManager.RemoveCollisionShape(eid, shapeIndex); + + const SHPhysicsColliderRemovedEvent COLLIDER_REMOVED_EVENT_DATA + { + .entityID = eid + , .colliderIndex = shapeIndex + }; + + SHEventManager::BroadcastEvent(COLLIDER_REMOVED_EVENT_DATA, SH_PHYSICS_COLLIDER_REMOVED_EVENT); + } + + void SHPhysicsSystem::AddForce(EntityID eid, const SHVec3& force) noexcept + { + auto* physicsObject = objectManager.GetPhysicsObject(eid); + + } + + void SHPhysicsSystem::AddForceAtLocalPos(EntityID eid, const SHVec3& force, const SHVec3& localPos) noexcept + { + auto* physicsObject = objectManager.GetPhysicsObject(eid); + } + + void SHPhysicsSystem::AddForceAtWorldPos(EntityID eid, const SHVec3& force, const SHVec3& worldPos) noexcept + { + auto* physicsObject = objectManager.GetPhysicsObject(eid); + } + + void SHPhysicsSystem::AddRelativeForce(EntityID eid, const SHVec3& relativeForce) noexcept + { + auto* physicsObject = objectManager.GetPhysicsObject(eid); + } + + void SHPhysicsSystem::AddRelativeForceAtLocalPos(EntityID eid, const SHVec3& relativeForce, const SHVec3& localPos) noexcept + { + auto* physicsObject = objectManager.GetPhysicsObject(eid); + } + + + void SHPhysicsSystem::AddRelativeForceAtWorldPos(EntityID eid, const SHVec3& relativeForce, const SHVec3& worldPos) noexcept + { + auto* physicsObject = objectManager.GetPhysicsObject(eid); + } + + void SHPhysicsSystem::AddTorque(EntityID eid, const SHVec3& torque) noexcept + { + auto* physicsObject = objectManager.GetPhysicsObject(eid); + } + + void SHPhysicsSystem::AddRelativeTorque(EntityID eid, const SHVec3& relativeTorque) noexcept + { + auto* physicsObject = objectManager.GetPhysicsObject(eid); + } + + /*-----------------------------------------------------------------------------------*/ + /* Private Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHEventHandle SHPhysicsSystem::addPhysicsComponent(SHEventPtr addComponentEvent) noexcept + { + const auto& EVENT_DATA = reinterpret_cast*>(addComponentEvent.get()); + + static const auto RIGID_BODY_ID = ComponentFamily::GetID(); + static const auto COLLIDER_ID = ComponentFamily::GetID(); + + const auto ADDED_ID = EVENT_DATA->data->addedComponentType; + const bool IS_PHYSICS_COMPONENT = ADDED_ID == RIGID_BODY_ID || ADDED_ID == COLLIDER_ID; + if (IS_PHYSICS_COMPONENT) + { + const EntityID EID = EVENT_DATA->data->eid; + + // We only add tell the physics object manager to add a component if the scene is played + + #ifdef _PUBLISH + + ADDED_ID == RIGID_BODY_ID ? objectManager.AddRigidBody(EID) : objectManager.AddCollider(EID); + + #elif SHEDITOR + + auto* editor = SHSystemManager::GetSystem(); + if (editor) + { + if (editor->editorState != SHEditor::State::STOP) + ADDED_ID == RIGID_BODY_ID ? objectManager.AddRigidBody(EID) : objectManager.AddCollider(EID); + } + + #endif + } + + return EVENT_DATA->handle; + } + + SHEventHandle SHPhysicsSystem::removePhysicsComponent(SHEventPtr removeComponentEvent) noexcept + { + const auto& EVENT_DATA = reinterpret_cast*>(removeComponentEvent.get()); + + static const auto RIGID_BODY_ID = ComponentFamily::GetID(); + static const auto COLLIDER_ID = ComponentFamily::GetID(); + + const auto REMOVED_ID = EVENT_DATA->data->removedComponentType; + const bool IS_PHYSICS_COMPONENT = REMOVED_ID == RIGID_BODY_ID || REMOVED_ID == COLLIDER_ID; + if (IS_PHYSICS_COMPONENT) + { + const EntityID EID = EVENT_DATA->data->eid; + + // We only add tell the physics object manager to remove a component if the scene is played + + #ifdef _PUBLISH + + REMOVED_ID == RIGID_BODY_ID ? objectManager.RemoveRigidBody(EID) : objectManager.RemoveCollider(EID); + + #elif SHEDITOR + + auto* editor = SHSystemManager::GetSystem(); + if (editor) + { + if (editor->editorState != SHEditor::State::STOP) + REMOVED_ID == RIGID_BODY_ID ? objectManager.RemoveRigidBody(EID) : objectManager.RemoveCollider(EID); + } + + #endif + + } + + return EVENT_DATA->handle; + } + + SHEventHandle SHPhysicsSystem::onPlay(SHEventPtr onPlayEvent) + { + // Create physics world + worldState.CreateWorld(factory); + + // Link Collision Listener + collisionListener.BindToWorld(worldState.world); + + // Link with object manager & create all physics objects + objectManager.SetWorld(*worldState.world); + + const auto& RIGIDBODY_DENSE = SHComponentManager::GetDense(); + const auto& COLLIDER_DENSE = SHComponentManager::GetDense(); + + for (auto& rigidBodyComponent : RIGIDBODY_DENSE) + objectManager.AddRigidBody(rigidBodyComponent.GetEID()); + + for (auto& colliderComponent : COLLIDER_DENSE) + objectManager.AddCollider(colliderComponent.GetEID()); + + return onPlayEvent->handle; + } + + SHEventHandle SHPhysicsSystem::onStop(SHEventPtr onStopEvent) + { + // Remove all physics objects + objectManager.RemoveAllObjects(); + + // Clear all collision info + // Collision listener is automatically unbound when world is destroyed + collisionListener.ClearContainers(); + + // Destroy the world + worldState.DestroyWorld(factory); + + + return onStopEvent->handle; + } + + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h similarity index 57% rename from SHADE_Engine/src/Physics/SHPhysicsSystem.h rename to SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index 3bacb061..4254efc7 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -13,28 +13,29 @@ #include #include +// External Dependencies #include // Project Headers -#include "Components/SHRigidBodyComponent.h" -#include "Components/SHColliderComponent.h" #include "ECS_Base/System/SHSystemRoutine.h" #include "ECS_Base/System/SHFixedSystemRoutine.h" + #include "Math/Transform/SHTransformComponent.h" -#include "Scene/SHSceneGraph.h" -#include "SHPhysicsObject.h" -#include "SHPhysicsUtils.h" + +#include "Physics/Collision/SHCollisionListener.h" +#include "Physics/Interface/SHRigidBodyComponent.h" +#include "Physics/Interface/SHColliderComponent.h" +#include "Physics/PhysicsObject//SHPhysicsObjectManager.h" +#include "Physics/SHPhysicsWorld.h" namespace SHADE { - /*-----------------------------------------------------------------------------------*/ /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ class SH_API SHPhysicsSystem final : public SHSystem - , public rp3d::EventListener { private: /*---------------------------------------------------------------------------------*/ @@ -44,21 +45,6 @@ namespace SHADE friend class SHPhysicsDebugDrawSystem; public: - /*---------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*---------------------------------------------------------------------------------*/ - - using CollisionEvents = std::vector; - using EntityObjectMap = std::unordered_map; - - struct WorldSettings - { - SHVec3 gravity; - uint16_t numVelocitySolverIterations; - uint16_t numPositionSolverIterations; - bool sleepingEnabled; - }; - /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ @@ -69,29 +55,20 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] double GetFixedDT () const noexcept; + [[nodiscard]] double GetFixedDT () const noexcept; + [[nodiscard]] const SHPhysicsWorldState::WorldSettings& GetWorldSettings () const noexcept; - [[nodiscard]] bool IsSleepingEnabled () const noexcept; - - [[nodiscard]] SHVec3 GetWorldGravity () const noexcept; - [[nodiscard]] uint16_t GetNumberVelocityIterations () const noexcept; - [[nodiscard]] uint16_t GetNumberPositionIterations () const noexcept; - - [[nodiscard]] const EntityObjectMap& GetPhysicsObjects () const noexcept; - [[nodiscard]] const CollisionEvents& GetCollisionInfo () const noexcept; - [[nodiscard]] const CollisionEvents& GetTriggerInfo () const noexcept; + [[nodiscard]] const std::vector& GetAllCollisionInfo () const noexcept; + [[nodiscard]] const std::vector& GetAllTriggerInfo () const noexcept; + [[nodiscard]] const SHPhysicsObject* const GetPhysicsObject (EntityID eid) noexcept; + [[nodiscard]] const SHPhysicsObjectManager::PhysicsObjectEntityMap& GetPhysicsObjects () const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetFixedDT (double fixedUpdateRate) noexcept; - void SetWorldGravity (const SHVec3& gravity) const noexcept; - void SetNumberVelocityIterations (uint16_t numVelIterations) const noexcept; - void SetNumberPositionIterations (uint16_t numPosIterations) const noexcept; - void SetSleepingEnabled (bool enableSleeping) const noexcept; - - void SetWorldSettings (const WorldSettings& settings) const noexcept; + void SetFixedDT (double fixedUpdateRate) noexcept; + void SetWorldSettings (const SHPhysicsWorldState::WorldSettings& settings) noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ @@ -100,11 +77,24 @@ namespace SHADE void Init () override; void Exit () override; - void AddCollisionShape (EntityID entityID, SHCollisionShape* collider); - void RemoveCollisionShape (EntityID entityID, int index); + // Specific Handling for Collision Shapes as they are not under the Component System - void onContact (const rp3d::CollisionCallback::CallbackData& callbackData) override; - void onTrigger (const rp3d::OverlapCallback::CallbackData& callbackData) override; + void AddCollisionShape (EntityID eid, int shapeIndex); + void RemoveCollisionShape (EntityID eid, int shapeIndex); + + // Forces are applied from components here. These functions should only be invoked during play (through scripts) + // Thus there is no need to check for an editor. + + void AddForce (EntityID eid, const SHVec3& force) noexcept; + void AddForceAtLocalPos (EntityID eid, const SHVec3& force, const SHVec3& localPos) noexcept; + void AddForceAtWorldPos (EntityID eid, const SHVec3& force, const SHVec3& worldPos) noexcept; + + void AddRelativeForce (EntityID eid, const SHVec3& relativeForce) noexcept; + void AddRelativeForceAtLocalPos (EntityID eid, const SHVec3& relativeForce, const SHVec3& localPos) noexcept; + void AddRelativeForceAtWorldPos (EntityID eid, const SHVec3& relativeForce, const SHVec3& worldPos) noexcept; + + void AddTorque (EntityID eid, const SHVec3& torque) noexcept; + void AddRelativeTorque (EntityID eid, const SHVec3& relativeTorque) noexcept; /*---------------------------------------------------------------------------------*/ /* System Routines */ @@ -124,6 +114,21 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ void Execute(double dt) noexcept override; + + private: + /*-------------------------------------------------------------------------------*/ + /* Function Members */ + /*-------------------------------------------------------------------------------*/ + + static void syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept; + + static void preUpdateSyncTransform + ( + SHPhysicsObject& physicsObject + , SHTransformComponent& transformComponent + , SHRigidBodyComponent* rigidBodyComponent + , SHColliderComponent* colliderComponent + ) noexcept; }; class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine @@ -156,6 +161,20 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ void Execute(double dt) noexcept override; + + private: + /*-------------------------------------------------------------------------------*/ + /* Function Members */ + /*-------------------------------------------------------------------------------*/ + + static void postUpdateSyncTransforms + ( + SHPhysicsObject& physicsObject + , SHTransformComponent& transformComponent + , SHRigidBodyComponent* rigidBodyComponent + , SHColliderComponent* colliderComponent + , double interpolationFactor + ) noexcept; }; private: @@ -163,41 +182,31 @@ namespace SHADE /* Data Members */ /*---------------------------------------------------------------------------------*/ - bool worldUpdated; + // System data - double interpolationFactor; - double fixedDT; + bool worldUpdated; + double interpolationFactor; + double fixedDT; - rp3d::PhysicsWorld* world; - rp3d::PhysicsCommon factory; + // rp3d - EntityObjectMap map; - CollisionEvents collisionInfo; - CollisionEvents triggerInfo; + rp3d::PhysicsCommon factory; + + // Interface objects + + SHPhysicsWorldState worldState; + SHPhysicsObjectManager objectManager; + SHCollisionListener collisionListener; /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept; - SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept; - void DestroyPhysicsObject (EntityID entityID) noexcept; + SHEventHandle addPhysicsComponent (SHEventPtr addComponentEvent) noexcept; + SHEventHandle removePhysicsComponent (SHEventPtr removeComponentEvent) noexcept; - static void SyncActiveStates (SHPhysicsObject& physicsObject, bool componentActive) noexcept; - void SyncTransforms () noexcept; + SHEventHandle onPlay (SHEventPtr onPlayEvent); + SHEventHandle onStop (SHEventPtr onStopEvent); - static void UpdateEventContainers (const SHCollisionEvent& collisionEvent, CollisionEvents& container) noexcept; - void ClearInvalidCollisions () noexcept; - - SHEventHandle AddPhysicsComponent (SHEventPtr addComponentEvent); - SHEventHandle RemovePhysicsComponent (SHEventPtr removeComponentEvent); - SHEventHandle ResetWorld (SHEventPtr editorStopEvent); - - template - || std::is_same_v>> - SHCollisionEvent GenerateCollisionEvent (const RP3DCollisionPair& cp) noexcept; }; -} // namespace SHADE - -#include "SHPhysicsSystem.hpp" \ No newline at end of file +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystemInterface.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp similarity index 81% rename from SHADE_Engine/src/Physics/SHPhysicsSystemInterface.cpp rename to SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp index 4b292340..30d29167 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystemInterface.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp @@ -16,35 +16,34 @@ of DigiPen Institute of Technology is prohibited. #include "SHPhysicsSystemInterface.h" // Project Includes #include "ECS_Base/Managers/SHSystemManager.h" -#include "Physics/SHPhysicsSystem.h" -#include "Physics/SHPhysicsUtils.h" +#include "Physics/System/SHPhysicsSystem.h" namespace SHADE { /*-----------------------------------------------------------------------------------*/ /* Static Usage Functions */ /*-----------------------------------------------------------------------------------*/ - const std::vector& SHPhysicsSystemInterface::GetCollisionInfo() noexcept + const std::vector& SHPhysicsSystemInterface::GetCollisionInfo() noexcept { - static std::vector emptyVec; + static std::vector emptyVec; auto phySystem = SHSystemManager::GetSystem(); if (phySystem) { - return phySystem->GetCollisionInfo(); + return phySystem->GetAllCollisionInfo(); } SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get collision events. Empty vector returned instead."); return emptyVec; } - const std::vector& SHPhysicsSystemInterface::GetTriggerInfo() noexcept + const std::vector& SHPhysicsSystemInterface::GetTriggerInfo() noexcept { - static std::vector emptyVec; + static std::vector emptyVec; auto phySystem = SHSystemManager::GetSystem(); if (phySystem) { - return phySystem->GetTriggerInfo(); + return phySystem->GetAllTriggerInfo(); } SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get trigger events. Empty vector returned instead."); diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystemInterface.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h similarity index 91% rename from SHADE_Engine/src/Physics/SHPhysicsSystemInterface.h rename to SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h index da6a0433..bdd04686 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystemInterface.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h @@ -19,7 +19,7 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ /* Forward Declarations */ /*-----------------------------------------------------------------------------------*/ - class SHCollisionEvent; + class SHCollisionInfo; /*-----------------------------------------------------------------------------------*/ /* Type Definitions */ @@ -39,8 +39,8 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Static Usage Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] static const std::vector& GetCollisionInfo() noexcept; - [[nodiscard]] static const std::vector& GetTriggerInfo() noexcept; + [[nodiscard]] static const std::vector& GetCollisionInfo() noexcept; + [[nodiscard]] static const std::vector& GetTriggerInfo() noexcept; [[nodiscard]] static double GetFixedDT() noexcept; }; } diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp new file mode 100644 index 00000000..26c740cc --- /dev/null +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp @@ -0,0 +1,314 @@ +/**************************************************************************************** + * \file SHPhysicsSystemRoutines.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for the Physics System Routines + * + * \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 + +// Primary Header +#include "SHPhysicsSystem.h" +// Project Headers +#include "ECS_Base/Managers/SHSystemManager.h" +#include "Editor/SHEditor.h" +#include "Scripting/SHScriptEngine.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsSystem::PhysicsPreUpdate::PhysicsPreUpdate() + : SHSystemRoutine { "Physics PreUpdate", true } + {} + + SHPhysicsSystem::PhysicsFixedUpdate::PhysicsFixedUpdate() + : SHFixedSystemRoutine { DEFAULT_FIXED_STEP, "Physics FixedUpdate", false } + {} + + SHPhysicsSystem::PhysicsPostUpdate::PhysicsPostUpdate() + : SHSystemRoutine { "Physics PostUpdate", false } + {} + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept + { + auto* physicsSystem = reinterpret_cast(GetSystem()); + + #ifdef SHEDITOR + + auto* editor = SHSystemManager::GetSystem(); + + // Only Sync on Play. + // Otherwise, Components are only holding data until the world is built on play. + + if (editor) + { + if (editor->editorState != SHEditor::State::STOP) + { + physicsSystem->objectManager.UpdateCommands(); + + for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) + { + // Ensure a valid physics Object + if (physicsObject.rp3dBody == nullptr) + continue; + + syncOnPlay(entityID, physicsObject); + } + } + else + { + auto& rigidBodyDense = SHComponentManager::GetDense(); + auto& colliderDense = SHComponentManager::GetDense(); + + for (auto& rigidBodyComponent : rigidBodyDense) + { + const auto* TRANSFORM = SHComponentManager::GetComponent_s(rigidBodyComponent.GetEID()); + + if (TRANSFORM && TRANSFORM->HasChanged()) + { + rigidBodyComponent.position = TRANSFORM->GetWorldPosition(); + rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation(); + } + } + + for (auto& colliderComponent : colliderDense) + { + const auto* TRANSFORM = SHComponentManager::GetComponent_s(colliderComponent.GetEID()); + + if (TRANSFORM && TRANSFORM->HasChanged()) + { + colliderComponent.position = TRANSFORM->GetWorldPosition(); + colliderComponent.orientation = TRANSFORM->GetWorldOrientation(); + colliderComponent.scale = TRANSFORM->GetWorldScale(); + + colliderComponent.RecomputeCollisionShapes(); + } + } + } + } + + #else + + // Always sync Rigid Body & Collider Components with Physics Objects + // Do not check for an editor here + + physicsSystem->objectManager.UpdateCommands(); + + for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) + { + // Ensure a valid physics Object + if (physicsObject.rp3dBody == nullptr) + continue; + + syncOnPlay(entityID, physicsObject); + } + + #endif + } + + void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept + { + auto* physicsSystem = reinterpret_cast(GetSystem()); + auto* scriptingSystem = SHSystemManager::GetSystem(); + if (scriptingSystem == nullptr) + { + SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!"); + } + + fixedTimeStep = 1.0 / physicsSystem->fixedDT; + accumulatedTime += dt; + + int count = 0; + while (accumulatedTime > fixedTimeStep) + { + if (scriptingSystem != nullptr) + scriptingSystem->ExecuteFixedUpdates(); + + physicsSystem->worldState.world->update(static_cast(fixedTimeStep)); + + accumulatedTime -= fixedTimeStep; + ++count; + } + + stats.numSteps = count; + physicsSystem->worldUpdated = count > 0; + + physicsSystem->interpolationFactor = accumulatedTime / fixedTimeStep; + } + + void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept + { + auto* physicsSystem = reinterpret_cast(GetSystem()); + auto* scriptingSystem = SHSystemManager::GetSystem(); + + if (scriptingSystem == nullptr) + { + SHLOGV_ERROR("Unable to invoke collision and trigger script events due to missing SHScriptEngine!"); + } + + // Interpolate transforms for rendering + if (physicsSystem->worldUpdated) + { + for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) + { + auto* transformComponent = SHComponentManager::GetComponent_s(entityID); + auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); + auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); + + if (transformComponent) + { + postUpdateSyncTransforms + ( + physicsObject + , *transformComponent + , rigidBodyComponent + , colliderComponent + , physicsSystem->interpolationFactor + ); + } + } + + // Collision & Trigger messages + if (scriptingSystem != nullptr) + scriptingSystem->ExecuteCollisionFunctions(); + + // Since this function never runs when editor in not in play, execute the function anyway + } + } + + /*-----------------------------------------------------------------------------------*/ + /* Private Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsSystem::PhysicsPreUpdate::syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept + { + auto* transformComponent = SHComponentManager::GetComponent_s(eid); + auto* rigidBodyComponent = SHComponentManager::GetComponent_s(eid); + auto* colliderComponent = SHComponentManager::GetComponent_s(eid); + + // Sync transforms & physics components transforms + if (transformComponent && transformComponent->HasChanged()) + { + preUpdateSyncTransform + ( + physicsObject + , *transformComponent + , rigidBodyComponent + , colliderComponent + ); + } + + // Sync Rigid Bodies + if (rigidBodyComponent) + physicsObject.SyncRigidBody(*rigidBodyComponent); + + // Sync Colliders + if (colliderComponent) + physicsObject.SyncColliders(*colliderComponent); + } + + void SHPhysicsSystem::PhysicsPreUpdate::preUpdateSyncTransform + ( + SHPhysicsObject& physicsObject + , SHTransformComponent& transformComponent + , SHRigidBodyComponent* rigidBodyComponent + , SHColliderComponent* colliderComponent + ) noexcept + { + const SHVec3& WORLD_POS = transformComponent.GetWorldPosition(); + const SHQuaternion& WORLD_ROT = transformComponent.GetWorldOrientation(); + const SHVec3& WORLD_SCL = transformComponent.GetWorldScale(); + + const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT }; + physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM); + + if (rigidBodyComponent) + { + rigidBodyComponent->position = WORLD_POS; + rigidBodyComponent->orientation = WORLD_ROT; + } + + if (colliderComponent) + { + colliderComponent->position = WORLD_POS; + colliderComponent->orientation = WORLD_ROT; + colliderComponent->scale = WORLD_SCL; + + colliderComponent->RecomputeCollisionShapes(); + } + } + + void SHPhysicsSystem::PhysicsPostUpdate::postUpdateSyncTransforms + ( + SHPhysicsObject& physicsObject + , SHTransformComponent& transformComponent + , SHRigidBodyComponent* rigidBodyComponent + , SHColliderComponent* colliderComponent + , double interpolationFactor + ) noexcept + { + rp3d::Vector3 rp3dPos; + rp3d::Quaternion rp3dRot; + + const rp3d::Transform CURRENT_TF = physicsObject.rp3dBody->getTransform(); + + // Check if transform should be interpolated + + if (rigidBodyComponent) + { + // Skip static bodies + if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC) + return; + + if (rigidBodyComponent->IsInterpolating()) + { + // Interpolate transforms between current and predicted next transform + + const rp3d::Transform PREV_TF = physicsObject.prevTransform; + const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast(interpolationFactor)); + + rp3dPos = INTERPOLATED_TF.getPosition(); + rp3dRot = INTERPOLATED_TF.getOrientation(); + } + else + { + rp3dPos = CURRENT_TF.getPosition(); + rp3dRot = CURRENT_TF.getOrientation(); + } + + rigidBodyComponent->position = CURRENT_TF.getPosition(); + rigidBodyComponent->orientation = CURRENT_TF.getOrientation(); + + if (colliderComponent) + { + // Sync with colliders + + colliderComponent->position = CURRENT_TF.getPosition(); + colliderComponent->orientation = CURRENT_TF.getOrientation(); + } + } + else + { + rp3dPos = CURRENT_TF.getPosition(); + rp3dRot = CURRENT_TF.getOrientation(); + } + + // Convert RP3D Transform to SHADE + transformComponent.SetWorldPosition(rp3dPos); + transformComponent.SetWorldOrientation(rp3dRot); + + // Cache transforms + physicsObject.prevTransform = CURRENT_TF; + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 4f3fbce6..7c0cd70b 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -24,7 +24,8 @@ of DigiPen Institute of Technology is prohibited. #include "Events/SHEvent.h" #include "Events/SHEventReceiver.h" #include "Events/SHEventManager.hpp" -#include "Physics/SHPhysicsSystem.h" +#include "Physics/System/SHPhysicsSystem.h" +#include "Physics/SHPhysicsEvents.h" #include "Assets/SHAssetMacros.h" diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index f2829b95..ae931778 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -14,7 +14,7 @@ #include "Camera/SHCameraComponent.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Math/Transform/SHTransformComponent.h" -#include "Physics/Components/SHRigidBodyComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" #include "ECS_Base/Managers/SHSystemManager.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h" #include "Scripting/SHScriptEngine.h" diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index c0d95491..0f8933e2 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -3,7 +3,7 @@ #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" #include "Math/Geometry/SHBoundingBox.h" #include "Math/Geometry/SHBoundingSphere.h" -#include "Physics/SHCollisionShape.h" +#include "Physics/Interface/SHCollisionShape.h" #include "Resource/SHResourceManager.h" #include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec3.h" @@ -11,7 +11,7 @@ #include "Graphics/MiddleEnd/Interface/SHMaterial.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" #include "SHSerializationTools.h" -#include "Physics/Components/SHColliderComponent.h" +#include "Physics/Interface/SHColliderComponent.h" namespace YAML { using namespace SHADE; diff --git a/SHADE_Managed/src/Components/Collider.hxx b/SHADE_Managed/src/Components/Collider.hxx index dc17ae7f..1711e8b9 100644 --- a/SHADE_Managed/src/Components/Collider.hxx +++ b/SHADE_Managed/src/Components/Collider.hxx @@ -15,7 +15,7 @@ of DigiPen Institute of Technology is prohibited. #pragma once // External Dependencies -#include "Physics/Components/SHColliderComponent.h" +#include "Physics/Interface/SHColliderComponent.h" // Project Includes #include "Components/Component.hxx" #include "Math/Vector3.hxx" diff --git a/SHADE_Managed/src/Components/RigidBody.hxx b/SHADE_Managed/src/Components/RigidBody.hxx index d3a30612..f2953bbd 100644 --- a/SHADE_Managed/src/Components/RigidBody.hxx +++ b/SHADE_Managed/src/Components/RigidBody.hxx @@ -15,7 +15,7 @@ of DigiPen Institute of Technology is prohibited. #pragma once // External Dependencies -#include "Physics/Components/SHRigidBodyComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" // Project Includes #include "Components/Component.hxx" diff --git a/SHADE_Managed/src/Engine/ECS.cxx b/SHADE_Managed/src/Engine/ECS.cxx index 00c3c182..80f070e2 100644 --- a/SHADE_Managed/src/Engine/ECS.cxx +++ b/SHADE_Managed/src/Engine/ECS.cxx @@ -22,8 +22,8 @@ of DigiPen Institute of Technology is prohibited. // External Dependencies #include "ECS_Base/Managers/SHEntityManager.h" #include "Math/Transform/SHTransformComponent.h" -#include "Physics/Components/SHColliderComponent.h" -#include "Physics/Components/SHRigidBodyComponent.h" +#include "Physics/Interface/SHColliderComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" #include "Scene/SHSceneManager.h" #include "Scene/SHSceneGraph.h" #include "Tools/SHLog.h" diff --git a/SHADE_Managed/src/Engine/Time.cxx b/SHADE_Managed/src/Engine/Time.cxx index 36032e00..8784ec90 100644 --- a/SHADE_Managed/src/Engine/Time.cxx +++ b/SHADE_Managed/src/Engine/Time.cxx @@ -16,7 +16,7 @@ of DigiPen Institute of Technology is prohibited. #include "SHpch.h" // External Dependencies #include "FRC/SHFramerateController.h" -#include "Physics/SHPhysicsSystemInterface.h" +#include "Physics/System/SHPhysicsSystemInterface.h" // Primary Header #include "Time.hxx" diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index a90b4f12..b3e02a9e 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -28,8 +28,9 @@ of DigiPen Institute of Technology is prohibited. #include "Engine/Entity.hxx" #include "Serialisation/ReflectionUtilities.hxx" #include "Engine/Application.hxx" -#include "Physics/SHPhysicsSystemInterface.h" -#include "Physics/SHPhysicsUtils.h" +#include "Physics/System/SHPhysicsSystemInterface.h" +#include "Physics/SHPhysicsEvents.h" +#include "Physics/Collision/SHCollisionInfo.h" namespace SHADE { @@ -526,13 +527,13 @@ namespace SHADE { switch (collisionInfo.GetCollisionState()) { - case SHCollisionEvent::State::ENTER: + case SHCollisionInfo::State::ENTER: script->OnCollisionEnter(info); break; - case SHCollisionEvent::State::STAY: + case SHCollisionInfo::State::STAY: script->OnCollisionStay(info); break; - case SHCollisionEvent::State::EXIT: + case SHCollisionInfo::State::EXIT: script->OnCollisionExit(info); break; } @@ -567,13 +568,13 @@ namespace SHADE { switch (triggerInfo.GetCollisionState()) { - case SHCollisionEvent::State::ENTER: + case SHCollisionInfo::State::ENTER: script->OnTriggerEnter(info); break; - case SHCollisionEvent::State::STAY: + case SHCollisionInfo::State::STAY: script->OnTriggerStay(info); break; - case SHCollisionEvent::State::EXIT: + case SHCollisionInfo::State::EXIT: script->OnTriggerExit(info); break; }