SP3-2 Physics System restructure & bugfixes #199
|
@ -4,7 +4,7 @@
|
||||||
NumberOfChildren: 0
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
Camera Component:
|
Camera Component:
|
||||||
Position: {x: 0, y: 0, z: 0}
|
Position: {x: 0, y: 0, z: 8}
|
||||||
Pitch: 0
|
Pitch: 0
|
||||||
Yaw: 0
|
Yaw: 0
|
||||||
Roll: 0
|
Roll: 0
|
||||||
|
@ -36,8 +36,8 @@
|
||||||
RigidBody Component:
|
RigidBody Component:
|
||||||
Type: Static
|
Type: Static
|
||||||
Mass: 1
|
Mass: 1
|
||||||
Drag: 0
|
Drag: 0.00999999978
|
||||||
Angular Drag: 0
|
Angular Drag: 0.00999999978
|
||||||
Use Gravity: true
|
Use Gravity: true
|
||||||
Interpolate: true
|
Interpolate: true
|
||||||
Freeze Position X: false
|
Freeze Position X: false
|
||||||
|
@ -56,18 +56,15 @@
|
||||||
Density: 1
|
Density: 1
|
||||||
Position Offset: {x: 0, y: 0, z: 0}
|
Position Offset: {x: 0, y: 0, z: 0}
|
||||||
Scripts: ~
|
Scripts: ~
|
||||||
- EID: 2
|
- EID: 10
|
||||||
Name: Player
|
Name: Default
|
||||||
IsActive: true
|
IsActive: true
|
||||||
NumberOfChildren: 3
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
Transform Component:
|
Transform Component:
|
||||||
Translate: {x: -3.06177855, y: -2, z: -5}
|
Translate: {x: -4.40482807, y: 2.57871056, z: -5.21213436}
|
||||||
Rotate: {x: -0, y: 0, z: -0}
|
Rotate: {x: -0.361265004, y: 1.11661232, z: -0.626627684}
|
||||||
Scale: {x: 2, y: 2, z: 2}
|
Scale: {x: 0.999982238, y: 0.999987125, z: 0.999981165}
|
||||||
Renderable Component:
|
|
||||||
Mesh: 149697411
|
|
||||||
Material: 126974645
|
|
||||||
RigidBody Component:
|
RigidBody Component:
|
||||||
Type: Dynamic
|
Type: Dynamic
|
||||||
Mass: 1
|
Mass: 1
|
||||||
|
@ -89,7 +86,7 @@
|
||||||
Friction: 0.400000006
|
Friction: 0.400000006
|
||||||
Bounciness: 0
|
Bounciness: 0
|
||||||
Density: 1
|
Density: 1
|
||||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
Position Offset: {x: 0, y: 0, z: 0}
|
||||||
Scripts: ~
|
Scripts: ~
|
||||||
- EID: 3
|
- EID: 3
|
||||||
Name: Empty
|
Name: Empty
|
||||||
|
|
|
@ -24,14 +24,15 @@
|
||||||
#include "Scene/SHSceneManager.h"
|
#include "Scene/SHSceneManager.h"
|
||||||
|
|
||||||
// Systems
|
// Systems
|
||||||
#include "Scripting/SHScriptEngine.h"
|
|
||||||
#include "Physics/SHPhysicsSystem.h"
|
|
||||||
#include "Math/Transform/SHTransformSystem.h"
|
|
||||||
#include "Input/SHInputManager.h"
|
|
||||||
#include "FRC/SHFramerateController.h"
|
|
||||||
#include "AudioSystem/SHAudioSystem.h"
|
#include "AudioSystem/SHAudioSystem.h"
|
||||||
#include "Camera/SHCameraSystem.h"
|
#include "Camera/SHCameraSystem.h"
|
||||||
|
#include "FRC/SHFramerateController.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
|
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
|
||||||
|
#include "Input/SHInputManager.h"
|
||||||
|
#include "Math/Transform/SHTransformSystem.h"
|
||||||
|
#include "Physics/System/SHPhysicsSystem.h"
|
||||||
|
#include "Physics/System/SHPhysicsDebugDrawSystem.h"
|
||||||
|
#include "Scripting/SHScriptEngine.h"
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||||
|
@ -39,7 +40,6 @@
|
||||||
|
|
||||||
#include "Scenes/SBTestScene.h"
|
#include "Scenes/SBTestScene.h"
|
||||||
|
|
||||||
|
|
||||||
#include "Assets/SHAssetManager.h"
|
#include "Assets/SHAssetManager.h"
|
||||||
#include "Scenes/SBMainScene.h"
|
#include "Scenes/SBMainScene.h"
|
||||||
#include "Serialization/Configurations/SHConfigurationManager.h"
|
#include "Serialization/Configurations/SHConfigurationManager.h"
|
||||||
|
@ -67,16 +67,21 @@ namespace Sandbox
|
||||||
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow, wndData);
|
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow, wndData);
|
||||||
|
|
||||||
// Create Systems
|
// Create Systems
|
||||||
SHSystemManager::CreateSystem<SHGraphicsSystem>();
|
|
||||||
SHSystemManager::CreateSystem<SHScriptEngine>();
|
SHSystemManager::CreateSystem<SHScriptEngine>();
|
||||||
SHSystemManager::CreateSystem<SHPhysicsSystem>();
|
|
||||||
SHSystemManager::CreateSystem<SHTransformSystem>();
|
SHSystemManager::CreateSystem<SHTransformSystem>();
|
||||||
SHGraphicsSystem* graphicsSystem = static_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>());
|
SHSystemManager::CreateSystem<SHPhysicsSystem>();
|
||||||
|
SHSystemManager::CreateSystem<SHPhysicsDebugDrawSystem>();
|
||||||
|
|
||||||
SHSystemManager::CreateSystem<SHAudioSystem>();
|
SHSystemManager::CreateSystem<SHAudioSystem>();
|
||||||
SHSystemManager::CreateSystem<SHCameraSystem>();
|
SHSystemManager::CreateSystem<SHCameraSystem>();
|
||||||
SHSystemManager::CreateSystem<SHDebugDrawSystem>();
|
|
||||||
|
|
||||||
|
SHSystemManager::CreateSystem<SHGraphicsSystem>();
|
||||||
|
SHGraphicsSystem* graphicsSystem = static_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>());
|
||||||
|
|
||||||
// Link up SHDebugDraw
|
// Link up SHDebugDraw
|
||||||
|
SHSystemManager::CreateSystem<SHDebugDrawSystem>();
|
||||||
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
|
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
|
@ -101,7 +106,8 @@ namespace Sandbox
|
||||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
|
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
|
||||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
|
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
|
||||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
|
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
|
||||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsDebugDraw>();
|
|
||||||
|
SHSystemManager::RegisterRoutine<SHPhysicsDebugDrawSystem, SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine>();
|
||||||
|
|
||||||
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
|
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
|
||||||
SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>();
|
SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>();
|
||||||
|
@ -165,7 +171,7 @@ namespace Sandbox
|
||||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10))
|
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10))
|
||||||
{
|
{
|
||||||
drawColliders = !drawColliders;
|
drawColliders = !drawColliders;
|
||||||
SHSystemManager::GetSystem<SHPhysicsSystem>()->SetDrawColliders(drawColliders);
|
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDER, drawColliders);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Finish all graphics jobs first
|
// Finish all graphics jobs first
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||||
|
|
||||||
#include "Assets/SHAssetManager.h"
|
#include "Assets/SHAssetManager.h"
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||||
|
|
||||||
#include "Assets/SHAssetManager.h"
|
#include "Assets/SHAssetManager.h"
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include "Editor/SHEditorWidgets.hpp"
|
#include "Editor/SHEditorWidgets.hpp"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||||
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
#include "Reflection/SHReflectionMetadata.h"
|
#include "Reflection/SHReflectionMetadata.h"
|
||||||
#include "Resource/SHResourceManager.h"
|
#include "Resource/SHResourceManager.h"
|
||||||
|
|
||||||
|
@ -246,21 +246,21 @@ namespace SHADE
|
||||||
if (collider->GetType() == SHCollisionShape::Type::BOX)
|
if (collider->GetType() == SHCollisionShape::Type::BOX)
|
||||||
{
|
{
|
||||||
SHEditorWidgets::BeginPanel(std::format("{} Box #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
SHEditorWidgets::BeginPanel(std::format("{} Box #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
||||||
auto box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
|
const auto* BOX = reinterpret_cast<const SHBoundingBox*>(collider->GetShape());
|
||||||
SHEditorWidgets::DragVec3
|
SHEditorWidgets::DragVec3
|
||||||
(
|
(
|
||||||
"Half Extents", { "X", "Y", "Z" },
|
"Half Extents", { "X", "Y", "Z" },
|
||||||
[box] { return box->GetRelativeExtents(); },
|
[BOX] { return BOX->GetRelativeExtents(); },
|
||||||
[collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); });
|
[collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); });
|
||||||
}
|
}
|
||||||
else if (collider->GetType() == SHCollisionShape::Type::SPHERE)
|
else if (collider->GetType() == SHCollisionShape::Type::SPHERE)
|
||||||
{
|
{
|
||||||
SHEditorWidgets::BeginPanel(std::format("{} Sphere #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
SHEditorWidgets::BeginPanel(std::format("{} Sphere #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
||||||
auto sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
|
const auto* SPHERE = reinterpret_cast<const SHBoundingSphere*>(collider->GetShape());
|
||||||
SHEditorWidgets::DragFloat
|
SHEditorWidgets::DragFloat
|
||||||
(
|
(
|
||||||
"Radius",
|
"Radius",
|
||||||
[sphere] { return sphere->GetRelativeRadius(); },
|
[SPHERE] { return SPHERE->GetRelativeRadius(); },
|
||||||
[collider](float const& value) { collider->SetBoundingSphere(value); });
|
[collider](float const& value) { collider->SetBoundingSphere(value); });
|
||||||
}
|
}
|
||||||
else if (collider->GetType() == SHCollisionShape::Type::CAPSULE)
|
else if (collider->GetType() == SHCollisionShape::Type::CAPSULE)
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
#include "Camera/SHCameraComponent.h"
|
#include "Camera/SHCameraComponent.h"
|
||||||
#include "Camera/SHCameraArmComponent.h"
|
#include "Camera/SHCameraArmComponent.h"
|
||||||
#include "SHEditorComponentView.h"
|
#include "SHEditorComponentView.h"
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace SHADE
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
for (uint32_t i = 1; i <= SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); ++i)
|
for (uint32_t i = 1; i <= SHUtilities::ConvertEnum(SH_LIGHT_TYPE::NUM_TYPES); ++i)
|
||||||
{
|
{
|
||||||
lightBindings.push_back (SHVkDescriptorSetLayout::Binding
|
lightBindings.push_back (SHVkDescriptorSetLayout::Binding
|
||||||
{
|
{
|
||||||
|
|
|
@ -317,13 +317,14 @@ namespace SHADE
|
||||||
|
|
||||||
void SHDebugDrawSystem::drawSphere(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, double radius)
|
void SHDebugDrawSystem::drawSphere(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, double radius)
|
||||||
{
|
{
|
||||||
if (spherePoints.empty())
|
//if (spherePoints.empty())
|
||||||
{
|
{
|
||||||
|
spherePoints.clear();
|
||||||
// Generate
|
// Generate
|
||||||
static const SHMeshData SPHERE = SHPrimitiveGenerator::Sphere();
|
static const SHMeshData SPHERE = SHPrimitiveGenerator::Sphere();
|
||||||
for (const auto& idx : SPHERE.Indices)
|
for (const auto& idx : SPHERE.Indices)
|
||||||
{
|
{
|
||||||
spherePoints.emplace_back(SPHERE.VertexPositions[idx] * radius);
|
spherePoints.emplace_back(SPHERE.VertexPositions[idx] * radius + pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drawLineSet(storage, color, spherePoints.begin(), spherePoints.end());
|
drawLineSet(storage, color, spherePoints.begin(), spherePoints.end());
|
||||||
|
|
|
@ -379,7 +379,7 @@ namespace SHADE
|
||||||
SHComponentManager::CreateComponentSparseSet<SHLightComponent>();
|
SHComponentManager::CreateComponentSparseSet<SHLightComponent>();
|
||||||
|
|
||||||
logicalDevice = device;
|
logicalDevice = device;
|
||||||
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
|
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ConvertEnum(SH_LIGHT_TYPE::NUM_TYPES);
|
||||||
|
|
||||||
std::vector<uint32_t> variableSizes{ NUM_LIGHT_TYPES };
|
std::vector<uint32_t> variableSizes{ NUM_LIGHT_TYPES };
|
||||||
std::fill (variableSizes.begin(), variableSizes.end(), 1);
|
std::fill (variableSizes.begin(), variableSizes.end(), 1);
|
||||||
|
@ -431,7 +431,7 @@ namespace SHADE
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
void SHLightingSubSystem::Run(SHMatrix const& viewMat, uint32_t frameIndex) noexcept
|
void SHLightingSubSystem::Run(SHMatrix const& viewMat, uint32_t frameIndex) noexcept
|
||||||
{
|
{
|
||||||
static uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
|
static uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ConvertEnum(SH_LIGHT_TYPE::NUM_TYPES);
|
||||||
|
|
||||||
auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
|
auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
|
||||||
bool expanded = false;
|
bool expanded = false;
|
||||||
|
@ -451,7 +451,7 @@ namespace SHADE
|
||||||
|
|
||||||
for (auto& light : lightComps)
|
for (auto& light : lightComps)
|
||||||
{
|
{
|
||||||
auto enumValue = SHUtilities::ToUnderlying(light.GetLightData().type);
|
auto enumValue = SHUtilities::ConvertEnum(light.GetLightData().type);
|
||||||
|
|
||||||
// First we want to make sure the light is already bound to the system. if it
|
// First we want to make sure the light is already bound to the system. if it
|
||||||
// isn't, we write it to the correct buffer.
|
// isn't, we write it to the correct buffer.
|
||||||
|
@ -491,7 +491,7 @@ namespace SHADE
|
||||||
// is a new buffer. If some expansion was detected, update descriptor sets.
|
// is a new buffer. If some expansion was detected, update descriptor sets.
|
||||||
if (expanded)
|
if (expanded)
|
||||||
{
|
{
|
||||||
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
|
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ConvertEnum(SH_LIGHT_TYPE::NUM_TYPES);
|
||||||
for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i)
|
for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i)
|
||||||
{
|
{
|
||||||
UpdateDescSet(i);
|
UpdateDescSet(i);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
* \file SHPhysicsUtils.cpp
|
* \file SHCollisionInfo.cpp
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
* \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
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
* disclosure of this file or its contents without the prior written consent
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
#include <SHpch.h>
|
#include <SHpch.h>
|
||||||
|
|
||||||
// Primary Header
|
// Primary Header
|
||||||
#include "SHPhysicsUtils.h"
|
#include "SHCollisionInfo.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,7 @@ namespace SHADE
|
||||||
/* Constructors & Destructor Definitions */
|
/* Constructors & Destructor Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHCollisionEvent::SHCollisionEvent() noexcept
|
SHCollisionInfo::SHCollisionInfo() noexcept
|
||||||
: collisionState { State::INVALID }
|
: collisionState { State::INVALID }
|
||||||
{
|
{
|
||||||
ids[ENTITY_A] = MAX_EID;
|
ids[ENTITY_A] = MAX_EID;
|
||||||
|
@ -28,7 +28,7 @@ namespace SHADE
|
||||||
ids[COLLIDER_B] = std::numeric_limits<uint32_t>::max();
|
ids[COLLIDER_B] = std::numeric_limits<uint32_t>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
SHCollisionEvent::SHCollisionEvent(EntityID entityA, EntityID entityB) noexcept
|
SHCollisionInfo::SHCollisionInfo(EntityID entityA, EntityID entityB) noexcept
|
||||||
: collisionState { State::INVALID }
|
: collisionState { State::INVALID }
|
||||||
{
|
{
|
||||||
ids[ENTITY_A] = entityA;
|
ids[ENTITY_A] = entityA;
|
||||||
|
@ -41,12 +41,12 @@ namespace SHADE
|
||||||
/* Operator Overload Definitions */
|
/* 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];
|
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];
|
return value[0] != rhs.value[0] || value[1] != rhs.value[1];
|
||||||
}
|
}
|
||||||
|
@ -55,37 +55,37 @@ namespace SHADE
|
||||||
/* Getter Function Definitions */
|
/* Getter Function Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
EntityID SHCollisionEvent::GetEntityA() const noexcept
|
EntityID SHCollisionInfo::GetEntityA() const noexcept
|
||||||
{
|
{
|
||||||
return ids[ENTITY_A];
|
return ids[ENTITY_A];
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityID SHCollisionEvent::GetEntityB() const noexcept
|
EntityID SHCollisionInfo::GetEntityB() const noexcept
|
||||||
{
|
{
|
||||||
return ids[ENTITY_B];
|
return ids[ENTITY_B];
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHRigidBodyComponent* SHCollisionEvent::GetRigidBodyA() const noexcept
|
const SHRigidBodyComponent* SHCollisionInfo::GetRigidBodyA() const noexcept
|
||||||
{
|
{
|
||||||
return SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ids[ENTITY_A]);
|
return SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ids[ENTITY_A]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHRigidBodyComponent* SHCollisionEvent::GetRigidBodyB() const noexcept
|
const SHRigidBodyComponent* SHCollisionInfo::GetRigidBodyB() const noexcept
|
||||||
{
|
{
|
||||||
return SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ids[ENTITY_B]);
|
return SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ids[ENTITY_B]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHCollisionShape* SHCollisionEvent::GetColliderA() const noexcept
|
const SHCollisionShape* SHCollisionInfo::GetColliderA() const noexcept
|
||||||
{
|
{
|
||||||
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_A])->GetCollisionShape(ids[COLLIDER_A]);
|
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_A])->GetCollisionShape(ids[COLLIDER_A]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHCollisionShape* SHCollisionEvent::GetColliderB() const noexcept
|
const SHCollisionShape* SHCollisionInfo::GetColliderB() const noexcept
|
||||||
{
|
{
|
||||||
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_B])->GetCollisionShape(ids[COLLIDER_B]);
|
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_B])->GetCollisionShape(ids[COLLIDER_B]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHCollisionEvent::State SHCollisionEvent::GetCollisionState() const noexcept
|
SHCollisionInfo::State SHCollisionInfo::GetCollisionState() const noexcept
|
||||||
{
|
{
|
||||||
return collisionState;
|
return collisionState;
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
* \file SHPhysicsUtils.h
|
* \file SHCollisionInfo.h
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
* \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
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
* disclosure of this file or its contents without the prior written consent
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
@ -11,8 +11,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
#include "Components/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -21,27 +21,14 @@ namespace SHADE
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
struct SHPhysicsColliderAddedEvent
|
class SH_API SHCollisionInfo
|
||||||
{
|
|
||||||
EntityID entityID;
|
|
||||||
SHCollisionShape::Type colliderType;
|
|
||||||
int colliderIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SHPhysicsColliderRemovedEvent
|
|
||||||
{
|
|
||||||
EntityID entityID;
|
|
||||||
int colliderIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SH_API SHCollisionEvent
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Friends */
|
/* Friends */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
friend class SHPhysicsSystem;
|
friend class SHCollisionListener;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -62,23 +49,23 @@ namespace SHADE
|
||||||
/* Constructors & Destructor */
|
/* Constructors & Destructor */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHCollisionEvent () noexcept;
|
SHCollisionInfo () noexcept;
|
||||||
SHCollisionEvent (EntityID entityA, EntityID entityB) noexcept;
|
SHCollisionInfo (EntityID entityA, EntityID entityB) noexcept;
|
||||||
|
|
||||||
|
|
||||||
SHCollisionEvent (const SHCollisionEvent& rhs) = default;
|
SHCollisionInfo (const SHCollisionInfo& rhs) = default;
|
||||||
SHCollisionEvent (SHCollisionEvent&& rhs) = default;
|
SHCollisionInfo (SHCollisionInfo&& rhs) = default;
|
||||||
~SHCollisionEvent () = default;
|
~SHCollisionInfo () = default;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Operator Overloads */
|
/* Operator Overloads */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
bool operator== (const SHCollisionEvent& rhs) const noexcept;
|
bool operator== (const SHCollisionInfo& rhs) const noexcept;
|
||||||
bool operator!= (const SHCollisionEvent& rhs) const noexcept;
|
bool operator!= (const SHCollisionInfo& rhs) const noexcept;
|
||||||
|
|
||||||
SHCollisionEvent& operator= (const SHCollisionEvent& rhs) = default;
|
SHCollisionInfo& operator= (const SHCollisionInfo& rhs) = default;
|
||||||
SHCollisionEvent& operator= (SHCollisionEvent&& rhs) = default;
|
SHCollisionInfo& operator= (SHCollisionInfo&& rhs) = default;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Getter Functions */
|
/* Getter Functions */
|
||||||
|
@ -112,5 +99,4 @@ namespace SHADE
|
||||||
State collisionState;
|
State collisionState;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -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 <SHpch.h>
|
||||||
|
|
||||||
|
// 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<uint32_t>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHCollisionListener::SHCollisionListener() noexcept
|
||||||
|
: system { nullptr }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
const std::vector<SHCollisionInfo>& SHCollisionListener::GetCollisionInfoContainer() const noexcept
|
||||||
|
{
|
||||||
|
return collisionInfoContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<SHCollisionInfo>& 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<SHCollisionInfo>& 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<SHCollisionInfo>& 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<SHCollisionInfo::State>(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<SHCollisionInfo::State>(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
|
|
@ -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 <reactphysics3d/reactphysics3d.h>
|
||||||
|
|
||||||
|
// 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<SHCollisionInfo>& GetCollisionInfoContainer () const noexcept;
|
||||||
|
[[nodiscard]] const std::vector<SHCollisionInfo>& 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<SHCollisionInfo> collisionInfoContainer;
|
||||||
|
std::vector<SHCollisionInfo> triggerInfoContainer;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void updateInfoContainers (const SHCollisionInfo& collisionEvent, std::vector<SHCollisionInfo>& container) noexcept;
|
||||||
|
|
||||||
|
SHCollisionInfo generateCollisionInfo (const rp3d::CollisionCallback::ContactPair& cp) const noexcept;
|
||||||
|
SHCollisionInfo generateTriggerInfo (const rp3d::OverlapCallback::OverlapPair& cp) const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -16,7 +16,7 @@
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "Math/SHMathHelpers.h"
|
#include "Math/SHMathHelpers.h"
|
||||||
#include "Physics/SHPhysicsSystem.h"
|
#include "Physics/System/SHPhysicsSystem.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -72,7 +72,14 @@ namespace SHADE
|
||||||
|
|
||||||
void SHColliderComponent::OnCreate()
|
void SHColliderComponent::OnCreate()
|
||||||
{
|
{
|
||||||
system = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||||
|
if (!physicsSystem)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Physics System does not exist to link with Physics Components!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
system = physicsSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHColliderComponent::OnDestroy()
|
void SHColliderComponent::OnDestroy()
|
||||||
|
@ -88,7 +95,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
case SHCollisionShape::Type::BOX:
|
case SHCollisionShape::Type::BOX:
|
||||||
{
|
{
|
||||||
auto* box = reinterpret_cast<SHBoundingBox*>(collisionShape.GetShape());
|
auto* box = reinterpret_cast<SHBoundingBox*>(collisionShape.shape);
|
||||||
const SHVec3& RELATIVE_EXTENTS = box->GetRelativeExtents();
|
const SHVec3& RELATIVE_EXTENTS = box->GetRelativeExtents();
|
||||||
|
|
||||||
// Recompute world extents based on new scale and fixed relative extents
|
// Recompute world extents based on new scale and fixed relative extents
|
||||||
|
@ -99,7 +106,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
case SHCollisionShape::Type::SPHERE:
|
case SHCollisionShape::Type::SPHERE:
|
||||||
{
|
{
|
||||||
auto* sphere = reinterpret_cast<SHBoundingSphere*>(collisionShape.GetShape());
|
auto* sphere = reinterpret_cast<SHBoundingSphere*>(collisionShape.shape);
|
||||||
const float RELATIVE_RADIUS = sphere->GetRelativeRadius();
|
const float RELATIVE_RADIUS = sphere->GetRelativeRadius();
|
||||||
|
|
||||||
// Recompute world radius based on new scale and fixed radius
|
// Recompute world radius based on new scale and fixed radius
|
||||||
|
@ -132,9 +139,10 @@ namespace SHADE
|
||||||
collider.SetBoundingBox(halfExtents);
|
collider.SetBoundingBox(halfExtents);
|
||||||
|
|
||||||
// Notify Physics System
|
// Notify Physics System
|
||||||
system->AddCollisionShape(GetEID(), &collider);
|
const int NEW_SHAPE_INDEX = static_cast<int>(collisionShapes.size()) - 1;
|
||||||
|
|
||||||
return static_cast<int>(collisionShapes.size()) - 1;
|
system->AddCollisionShape(GetEID(), NEW_SHAPE_INDEX);
|
||||||
|
return NEW_SHAPE_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept
|
int SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept
|
||||||
|
@ -154,9 +162,10 @@ namespace SHADE
|
||||||
collider.SetBoundingSphere(radius);
|
collider.SetBoundingSphere(radius);
|
||||||
|
|
||||||
// Notify Physics System
|
// Notify Physics System
|
||||||
system->AddCollisionShape(GetEID(), &collider);
|
const int NEW_SHAPE_INDEX = static_cast<int>(collisionShapes.size()) - 1;
|
||||||
|
|
||||||
return static_cast<int>(collisionShapes.size()) - 1;
|
system->AddCollisionShape(GetEID(), NEW_SHAPE_INDEX);
|
||||||
|
return NEW_SHAPE_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHColliderComponent::RemoveCollider(int index)
|
void SHColliderComponent::RemoveCollider(int index)
|
|
@ -14,9 +14,9 @@
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/Components/SHComponent.h"
|
#include "ECS_Base/Components/SHComponent.h"
|
||||||
#include "Physics/SHCollisionShape.h"
|
|
||||||
#include "Math/Geometry/SHBoundingBox.h"
|
#include "Math/Geometry/SHBoundingBox.h"
|
||||||
#include "Math/Geometry/SHBoundingSphere.h"
|
#include "Math/Geometry/SHBoundingSphere.h"
|
||||||
|
#include "SHCollisionShape.h"
|
||||||
|
|
||||||
//namespace SHADE
|
//namespace SHADE
|
||||||
//{
|
//{
|
|
@ -16,8 +16,8 @@
|
||||||
#include "Math/Geometry/SHBoundingBox.h"
|
#include "Math/Geometry/SHBoundingBox.h"
|
||||||
#include "Math/Geometry/SHBoundingSphere.h"
|
#include "Math/Geometry/SHBoundingSphere.h"
|
||||||
#include "Math/SHMathHelpers.h"
|
#include "Math/SHMathHelpers.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
|
||||||
#include "Reflection/SHReflectionMetadata.h"
|
#include "Reflection/SHReflectionMetadata.h"
|
||||||
|
#include "SHColliderComponent.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -164,9 +164,8 @@ namespace SHADE
|
||||||
return rotationOffset;
|
return rotationOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHShape* SHCollisionShape::GetShape() noexcept
|
const SHShape* SHCollisionShape::GetShape() const noexcept
|
||||||
{
|
{
|
||||||
dirty = true;
|
|
||||||
return shape;
|
return shape;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ namespace SHADE
|
||||||
[[nodiscard]] const SHVec3& GetPositionOffset () const noexcept;
|
[[nodiscard]] const SHVec3& GetPositionOffset () const noexcept;
|
||||||
[[nodiscard]] const SHVec3& GetRotationOffset () const noexcept;
|
[[nodiscard]] const SHVec3& GetRotationOffset () const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] SHShape* GetShape () noexcept;
|
[[nodiscard]] const SHShape* GetShape () const noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Setter Functions */
|
/* Setter Functions */
|
|
@ -19,7 +19,7 @@
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "Math/SHMathHelpers.h"
|
#include "Math/SHMathHelpers.h"
|
||||||
#include "Physics/SHPhysicsSystem.h"
|
#include "Physics/System/SHPhysicsSystem.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -30,8 +30,17 @@ namespace SHADE
|
||||||
SHRigidBodyComponent::SHRigidBodyComponent() noexcept
|
SHRigidBodyComponent::SHRigidBodyComponent() noexcept
|
||||||
: type { Type::DYNAMIC }
|
: type { Type::DYNAMIC }
|
||||||
, interpolate { true }
|
, interpolate { true }
|
||||||
, rp3dBody { nullptr }
|
, flags { 0 }
|
||||||
{}
|
, dirtyFlags { std::numeric_limits<uint16_t>::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 */
|
/* Getter Function Definitions */
|
||||||
|
@ -39,24 +48,14 @@ namespace SHADE
|
||||||
|
|
||||||
bool SHRigidBodyComponent::IsGravityEnabled() const noexcept
|
bool SHRigidBodyComponent::IsGravityEnabled() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 0;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->isGravityEnabled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept
|
bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 1;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->isAllowedToSleep();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::IsInterpolating() const noexcept
|
bool SHRigidBodyComponent::IsInterpolating() const noexcept
|
||||||
|
@ -71,151 +70,85 @@ namespace SHADE
|
||||||
|
|
||||||
float SHRigidBodyComponent::GetMass() const noexcept
|
float SHRigidBodyComponent::GetMass() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
return mass;
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->getMass();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float SHRigidBodyComponent::GetDrag() const noexcept
|
float SHRigidBodyComponent::GetDrag() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
return drag;
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->getLinearDamping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float SHRigidBodyComponent::GetAngularDrag() const noexcept
|
float SHRigidBodyComponent::GetAngularDrag() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
return angularDrag;
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->getAngularDamping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezePositionX() const noexcept
|
bool SHRigidBodyComponent::GetFreezePositionX() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 2;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
return SHMath::CompareFloat(LINEAR_CONSTRAINTS.x, 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezePositionY() const noexcept
|
bool SHRigidBodyComponent::GetFreezePositionY() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 3;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
return SHMath::CompareFloat(LINEAR_CONSTRAINTS.y, 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept
|
bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 4;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
return SHMath::CompareFloat(LINEAR_CONSTRAINTS.z, 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept
|
bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 5;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.x, 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept
|
bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 6;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.y, 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept
|
bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 7;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.z, 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHRigidBodyComponent::GetForce() const noexcept
|
SHVec3 SHRigidBodyComponent::GetForce() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||||
{
|
return physicsObject->GetRigidBody()->getForce();
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->getForce();
|
return SHVec3::Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHRigidBodyComponent::GetTorque() const noexcept
|
SHVec3 SHRigidBodyComponent::GetTorque() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||||
{
|
return physicsObject->GetRigidBody()->getTorque();
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return SHVec3::Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->getTorque();
|
return SHVec3::Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept
|
SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||||
{
|
return physicsObject->GetRigidBody()->getLinearVelocity();
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return SHVec3::Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->getLinearVelocity();
|
return SHVec3::Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHRigidBodyComponent::GetAngularVelocity() const noexcept
|
SHVec3 SHRigidBodyComponent::GetAngularVelocity() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||||
{
|
return physicsObject->GetRigidBody()->getAngularVelocity();
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return SHVec3::Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->getAngularVelocity();
|
return SHVec3::Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHVec3& SHRigidBodyComponent::GetPosition() const noexcept
|
const SHVec3& SHRigidBodyComponent::GetPosition() const noexcept
|
||||||
|
@ -239,18 +172,13 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetType(Type newType) noexcept
|
void SHRigidBodyComponent::SetType(Type newType) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 8;
|
||||||
|
|
||||||
if (type == newType)
|
if (type == newType)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
type = newType;
|
type = newType;
|
||||||
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
if (rp3dBody == nullptr)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->setType(static_cast<rp3d::BodyType>(type));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept
|
void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept
|
||||||
|
@ -263,13 +191,8 @@ namespace SHADE
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
enableGravity ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->enableGravity(enableGravity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept
|
void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept
|
||||||
|
@ -282,127 +205,92 @@ namespace SHADE
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
isAllowedToSleep ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->setIsAllowedToSleep(isAllowedToSleep);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept
|
void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 2;
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
freezePositionX ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto linearConstraints = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
linearConstraints.x = freezePositionX ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setLinearLockAxisFactor(linearConstraints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept
|
void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 3;
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
freezePositionY ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto linearConstraints = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
linearConstraints.y = freezePositionY ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setLinearLockAxisFactor(linearConstraints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept
|
void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 4;
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
freezePositionZ ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto linearConstraints = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
linearConstraints.z = freezePositionZ ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setLinearLockAxisFactor(linearConstraints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept
|
void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 5;
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
freezeRotationX ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto angularConstraints = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
angularConstraints.x = freezeRotationX ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setAngularLockAxisFactor(angularConstraints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept
|
void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 6;
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
freezeRotationY ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto angularConstraints = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
angularConstraints.y = freezeRotationY ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setAngularLockAxisFactor(angularConstraints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept
|
void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 7;
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
freezeRotationZ ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto angularConstraints = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
angularConstraints.z = freezeRotationZ ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setAngularLockAxisFactor(angularConstraints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept
|
void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept
|
||||||
|
@ -412,179 +300,127 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetMass(float newMass) noexcept
|
void SHRigidBodyComponent::SetMass(float newMass) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 9;
|
||||||
|
|
||||||
if (type != Type::DYNAMIC)
|
if (type != Type::DYNAMIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID())
|
SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
mass = newMass;
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->setMass(newMass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
|
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 10;
|
||||||
|
|
||||||
if (type != Type::DYNAMIC)
|
if (type != Type::DYNAMIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set drag of a non-dynamic object {}", GetEID())
|
SHLOG_WARNING("Cannot set drag of a non-dynamic object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
drag = newDrag;
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->setLinearDamping(newDrag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept
|
void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 11;
|
||||||
|
|
||||||
if (type != Type::DYNAMIC)
|
if (type != Type::DYNAMIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set angular drag of a non-dynamic object {}", GetEID())
|
SHLOG_WARNING("Cannot set angular drag of a non-dynamic object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
angularDrag = newAngularDrag;
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->setLinearDamping(newAngularDrag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
|
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
|
||||||
{
|
{
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set linear velocity of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set linear velocity of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
auto* physicsObject = system->GetPhysicsObject(GetEID());
|
||||||
{
|
physicsObject->GetRigidBody()->setLinearVelocity(newLinearVelocity);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->setLinearVelocity(newLinearVelocity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
|
void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 13;
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set angular velocity of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set angular velocity of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
auto* physicsObject = system->GetPhysicsObject(GetEID());
|
||||||
{
|
physicsObject->GetRigidBody()->setAngularVelocity(newAngularVelocity);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->setAngularVelocity(newAngularVelocity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Public Function Member Definitions */
|
/* Public Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept
|
void SHRigidBodyComponent::OnCreate()
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||||
|
if (!physicsSystem)
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
SHLOG_ERROR("Physics System does not exist to link with Physics Components!")
|
||||||
return;
|
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
|
void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
system->AddForceAtLocalPos(GetEID(), force, localPos);
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->applyWorldForceAtLocalPosition(force, localPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept
|
void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
system->AddForceAtWorldPos(GetEID(), force, worldPos);
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->applyWorldForceAtWorldPosition(force, worldPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept
|
void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
system->AddRelativeForce(GetEID(), relativeForce);
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->applyLocalForceAtCenterOfMass(relativeForce);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept
|
void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
system->AddRelativeForceAtLocalPos(GetEID(), relativeForce, localPos);
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->applyLocalForceAtLocalPosition(relativeForce, localPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept
|
void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
system->AddRelativeForceAtWorldPos(GetEID(), relativeForce, worldPos);
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->applyLocalForceAtWorldPosition(relativeForce, worldPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept
|
void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
system->AddTorque(GetEID(), torque);
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->applyWorldTorque(torque);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept
|
void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
system->AddRelativeTorque(GetEID(), relativeTorque);
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->applyLocalTorque(relativeTorque);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -17,16 +17,6 @@
|
||||||
#include "Math/Vector/SHVec3.h"
|
#include "Math/Vector/SHVec3.h"
|
||||||
#include "Math/SHQuaternion.h"
|
#include "Math/SHQuaternion.h"
|
||||||
|
|
||||||
//namespace SHADE
|
|
||||||
//{
|
|
||||||
// class SHPhysicsSystem;
|
|
||||||
//}
|
|
||||||
|
|
||||||
namespace reactphysics3d
|
|
||||||
{
|
|
||||||
class RigidBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -110,7 +100,7 @@ namespace SHADE
|
||||||
void SetType (Type newType) noexcept;
|
void SetType (Type newType) noexcept;
|
||||||
|
|
||||||
void SetGravityEnabled (bool enableGravity) noexcept;
|
void SetGravityEnabled (bool enableGravity) noexcept;
|
||||||
void SetIsAllowedToSleep(bool isAllowedToSleep) noexcept;
|
void SetIsAllowedToSleep (bool isAllowedToSleep) noexcept;
|
||||||
void SetFreezePositionX (bool freezePositionX) noexcept;
|
void SetFreezePositionX (bool freezePositionX) noexcept;
|
||||||
void SetFreezePositionY (bool freezePositionY) noexcept;
|
void SetFreezePositionY (bool freezePositionY) noexcept;
|
||||||
void SetFreezePositionZ (bool freezePositionZ) noexcept;
|
void SetFreezePositionZ (bool freezePositionZ) noexcept;
|
||||||
|
@ -130,6 +120,8 @@ namespace SHADE
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void OnCreate () override;
|
||||||
|
|
||||||
void AddForce (const SHVec3& force) const noexcept;
|
void AddForce (const SHVec3& force) const noexcept;
|
||||||
void AddForceAtLocalPos (const SHVec3& force, const SHVec3& localPos) const noexcept;
|
void AddForceAtLocalPos (const SHVec3& force, const SHVec3& localPos) const noexcept;
|
||||||
void AddForceAtWorldPos (const SHVec3& force, const SHVec3& worldPos) const noexcept;
|
void AddForceAtWorldPos (const SHVec3& force, const SHVec3& worldPos) const noexcept;
|
||||||
|
@ -147,12 +139,22 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static constexpr size_t NUM_FLAGS = 8;
|
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;
|
Type type;
|
||||||
bool interpolate;
|
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
float mass;
|
||||||
|
float drag;
|
||||||
|
float angularDrag;
|
||||||
|
|
||||||
|
SHVec3 linearVelocity;
|
||||||
|
SHVec3 angularVelocity;
|
||||||
|
|
||||||
|
SHPhysicsSystem* system;
|
||||||
|
|
||||||
SHVec3 position;
|
SHVec3 position;
|
||||||
SHQuaternion orientation;
|
SHQuaternion orientation;
|
|
@ -0,0 +1,359 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \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 <SHpch.h>
|
||||||
|
|
||||||
|
// 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<SHTransformComponent>(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<SHColliderComponent>(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
rp3dBody->updateLocalCenterOfMassFromColliders();
|
||||||
|
rp3dBody->updateLocalInertiaTensorFromColliders();
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObject::RemoveCollisionShape(int index) const
|
||||||
|
{
|
||||||
|
const int NUM_COLLIDERS = static_cast<int>(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<int>(rp3dBody->getNbColliders());
|
||||||
|
if (numColliders == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (numColliders - 1 >= 0)
|
||||||
|
{
|
||||||
|
auto* collider = rp3dBody->getCollider(numColliders - 1);
|
||||||
|
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<rp3d::BodyType>(component.type));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 9: // Mass
|
||||||
|
{
|
||||||
|
rp3dBody->setMass(component.mass);
|
||||||
|
rp3dBody->updateLocalCenterOfMassFromColliders();
|
||||||
|
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<const SHBoundingBox*>(boxShape.GetShape());
|
||||||
|
rp3d::BoxShape* newBox = factory->createBoxShape(BOX->GetWorldExtents());
|
||||||
|
|
||||||
|
rp3dBody->addCollider(newBox, OFFSETS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObject::syncBoxShape(int index, SHCollisionShape& boxShape) const noexcept
|
||||||
|
{
|
||||||
|
const auto* BOX = reinterpret_cast<const SHBoundingBox*>(boxShape.GetShape());
|
||||||
|
|
||||||
|
auto* rp3dCollider = rp3dBody->getCollider(index);
|
||||||
|
auto* rp3dBox = reinterpret_cast<rp3d::BoxShape*>(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<const SHBoundingSphere*>(sphereShape.GetShape());
|
||||||
|
rp3d::SphereShape* newSphere = factory->createSphereShape(SPHERE->GetWorldRadius());
|
||||||
|
|
||||||
|
rp3dBody->addCollider(newSphere, OFFSETS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObject::syncSphereShape(int index, SHCollisionShape& sphereShape) const noexcept
|
||||||
|
{
|
||||||
|
const auto* SPHERE = reinterpret_cast<const SHBoundingSphere*>(sphereShape.GetShape());
|
||||||
|
|
||||||
|
auto* rp3dCollider = rp3dBody->getCollider(index);
|
||||||
|
auto* rp3dSphere = reinterpret_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape());
|
||||||
|
|
||||||
|
const rp3d::Transform OFFSETS
|
||||||
|
{
|
||||||
|
sphereShape.GetPositionOffset()
|
||||||
|
, sphereShape.GetRotationOffset()
|
||||||
|
};
|
||||||
|
|
||||||
|
rp3dCollider->setIsTrigger(sphereShape.IsTrigger());
|
||||||
|
rp3dCollider->setLocalToBodyTransform(OFFSETS);
|
||||||
|
|
||||||
|
rp3dSphere->setRadius(SPHERE->GetWorldRadius());
|
||||||
|
}
|
||||||
|
} // namespace SHADE
|
|
@ -14,8 +14,8 @@
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
#include "Components/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
#include "Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -31,6 +31,7 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
friend class SHPhysicsSystem;
|
friend class SHPhysicsSystem;
|
||||||
|
friend class SHPhysicsObjectManager;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -57,22 +58,25 @@ namespace SHADE
|
||||||
[[nodiscard]] SHQuaternion GetOrientation () const noexcept;
|
[[nodiscard]] SHQuaternion GetOrientation () const noexcept;
|
||||||
[[nodiscard]] SHVec3 GetRotation () const noexcept;
|
[[nodiscard]] SHVec3 GetRotation () const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] rp3d::CollisionBody* GetCollisionBody () const noexcept;
|
||||||
|
[[nodiscard]] rp3d::RigidBody* GetRigidBody () const noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Setter Functions */
|
/* Setter Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SetPosition (const SHVec3& position) noexcept;
|
void SetStaticBody () const noexcept;
|
||||||
void SetOrientation (const SHQuaternion& orientation) noexcept;
|
|
||||||
void SetRotation (const SHVec3& rotation) noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int AddCollider (SHCollisionShape* collider);
|
int AddCollisionShape (int index) const;
|
||||||
void RemoveCollider (int index);
|
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:
|
private:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -83,7 +87,22 @@ namespace SHADE
|
||||||
|
|
||||||
rp3d::PhysicsCommon* factory;
|
rp3d::PhysicsCommon* factory;
|
||||||
rp3d::PhysicsWorld* world;
|
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
|
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
|
} // namespace SHADE
|
|
@ -0,0 +1,301 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \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 <SHpch.h>
|
||||||
|
|
||||||
|
// Primary Header
|
||||||
|
#include "SHPhysicsObjectManager.h"
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||||
|
#include "Tools/SHUtilities.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Static Data Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsObjectManager::CommandFunctionPtr SHPhysicsObjectManager::componentFunc[2][3]
|
||||||
|
{
|
||||||
|
addRigidBody , addCollider
|
||||||
|
, removeRigidBody , removeCollider
|
||||||
|
, addCollisionShape , removeCollisionShape
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
// Get physics components
|
||||||
|
const PhysicsComponentGroup COMPONENT_GROUP
|
||||||
|
{
|
||||||
|
.eid = COMMAND.eid
|
||||||
|
, .rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(COMMAND.eid)
|
||||||
|
, .colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(COMMAND.eid)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delete any object that is missing both components
|
||||||
|
// We infer that a remove command has been pushed for these, but we will ignore those if both components have already been removed.
|
||||||
|
if (!COMPONENT_GROUP.rigidBodyComponent && !COMPONENT_GROUP.colliderComponent)
|
||||||
|
{
|
||||||
|
destroyPhysicsObject(COMMAND.eid);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the physics Object. If none found and attempting to add, create an object.
|
||||||
|
SHPhysicsObject* physicsObject = GetPhysicsObject(COMMAND.eid);
|
||||||
|
if (!physicsObject && COMMAND.command == QueueCommand::Command::ADD)
|
||||||
|
physicsObject = createPhysicsObject(COMMAND.eid);
|
||||||
|
|
||||||
|
componentFunc[SHUtilities::ConvertEnum(COMMAND.command)][SHUtilities::ConvertEnum(COMMAND.component)](COMMAND, physicsObject, COMPONENT_GROUP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::RemoveAllObjects()
|
||||||
|
{
|
||||||
|
// Destroy all objects and clear
|
||||||
|
for (auto& physicsObject : physicsObjects | std::views::values)
|
||||||
|
{
|
||||||
|
world->destroyRigidBody(physicsObject.GetRigidBody());
|
||||||
|
physicsObject.rp3dBody = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
physicsObjects.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Private Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsObject* SHPhysicsObjectManager::createPhysicsObject(EntityID eid) noexcept
|
||||||
|
{
|
||||||
|
// Force transforms to sync
|
||||||
|
SHVec3 worldPos = SHVec3::Zero;
|
||||||
|
SHQuaternion worldRot = SHQuaternion::Identity;
|
||||||
|
|
||||||
|
const SHTransformComponent* TRANSFORM = nullptr;
|
||||||
|
if (SHEntityManager::IsValidEID(eid))
|
||||||
|
TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
||||||
|
|
||||||
|
if (TRANSFORM)
|
||||||
|
{
|
||||||
|
worldPos = TRANSFORM->GetWorldPosition();
|
||||||
|
worldRot = TRANSFORM->GetWorldOrientation();
|
||||||
|
}
|
||||||
|
|
||||||
|
const rp3d::Transform RP3D_TRANSFORM{ worldPos, worldRot };
|
||||||
|
|
||||||
|
auto& newPhysicsObject = physicsObjects.emplace(eid, SHPhysicsObject{ eid, factory, world }).first->second;
|
||||||
|
newPhysicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM);
|
||||||
|
newPhysicsObject.prevTransform = RP3D_TRANSFORM;
|
||||||
|
|
||||||
|
return &newPhysicsObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::destroyPhysicsObject(EntityID eid) noexcept
|
||||||
|
{
|
||||||
|
const auto ITER = physicsObjects.find(eid);
|
||||||
|
if (ITER == physicsObjects.end())
|
||||||
|
{
|
||||||
|
// Assume the object has already been successfully destroyed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
world->destroyRigidBody(ITER->second.GetRigidBody());
|
||||||
|
ITER->second.rp3dBody = nullptr;
|
||||||
|
|
||||||
|
physicsObjects.erase(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::addRigidBody(const QueueCommand&, 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(const QueueCommand&, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int NUM_SHAPES = static_cast<int>(componentGroup.colliderComponent->GetCollisionShapes().size());
|
||||||
|
for (int i = 0; i < NUM_SHAPES; ++i)
|
||||||
|
physicsObject->AddCollisionShape(i);
|
||||||
|
|
||||||
|
physicsObject->SyncColliders(*componentGroup.colliderComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::removeRigidBody(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup)
|
||||||
|
{
|
||||||
|
SHASSERT(physicsObject != nullptr, "Valid physics object required to remove body!")
|
||||||
|
|
||||||
|
if (componentGroup.colliderComponent)
|
||||||
|
physicsObject->SetStaticBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::removeCollider(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&)
|
||||||
|
{
|
||||||
|
SHASSERT(physicsObject != nullptr, "Valid physics object required to remove collider!")
|
||||||
|
|
||||||
|
physicsObject->RemoveAllCollisionShapes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::addCollisionShape(const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&)
|
||||||
|
{
|
||||||
|
SHASSERT(physicsObject != nullptr, "Valid physics object required to add collision shape!")
|
||||||
|
|
||||||
|
physicsObject->AddCollisionShape(command.shapeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::removeCollisionShape(const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&)
|
||||||
|
{
|
||||||
|
SHASSERT(physicsObject != nullptr, "Valid physics object required to remove collision shape!")
|
||||||
|
|
||||||
|
physicsObject->RemoveCollisionShape(command.shapeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -0,0 +1,177 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \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 <unordered_map>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
#include <reactphysics3d/reactphysics3d.h>
|
||||||
|
|
||||||
|
// 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<EntityID, SHPhysicsObject>;
|
||||||
|
|
||||||
|
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(*)(const QueueCommand&, SHPhysicsObject*, const PhysicsComponentGroup&);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static CommandFunctionPtr componentFunc[2][3]; // 2 commands, 3 components
|
||||||
|
|
||||||
|
rp3d::PhysicsCommon* factory = nullptr;
|
||||||
|
rp3d::PhysicsWorld* world = nullptr;
|
||||||
|
|
||||||
|
PhysicsObjectEntityMap physicsObjects;
|
||||||
|
std::queue<QueueCommand> commandQueue;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsObject* createPhysicsObject (EntityID eid) noexcept;
|
||||||
|
void destroyPhysicsObject (EntityID eid) noexcept;
|
||||||
|
|
||||||
|
static void addRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||||
|
static void addCollider (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||||
|
static void removeRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||||
|
static void removeCollider (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||||
|
|
||||||
|
static void addCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||||
|
static void removeCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -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
|
|
@ -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 <SHpch.h>
|
|
||||||
|
|
||||||
// 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<SHBoundingBox*>(collider->GetShape());
|
|
||||||
rp3d::BoxShape* newBox = factory->createBoxShape(box->GetWorldExtents());
|
|
||||||
|
|
||||||
rp3dBody->addCollider(newBox, OFFSETS);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SHCollisionShape::Type::SPHERE:
|
|
||||||
{
|
|
||||||
const auto* sphere = reinterpret_cast<SHBoundingSphere*>(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<int>(rp3dBody->getNbColliders()) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::RemoveCollider(int index)
|
|
||||||
{
|
|
||||||
const int NUM_COLLIDERS = static_cast<int>(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<SHBoundingBox*>(collider.GetShape());
|
|
||||||
|
|
||||||
auto* rp3dBoxShape = reinterpret_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape());
|
|
||||||
rp3dBoxShape->setHalfExtents(box->GetWorldExtents());
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SHCollisionShape::Type::SPHERE:
|
|
||||||
{
|
|
||||||
const auto* sphere = reinterpret_cast<SHBoundingSphere*>(collider.GetShape());
|
|
||||||
|
|
||||||
auto* rp3dSphereShape = reinterpret_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape());
|
|
||||||
rp3dSphereShape->setRadius(sphere->GetWorldRadius());
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(Diren): Update Material
|
|
||||||
|
|
||||||
collider.dirty = false;
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace SHADE
|
|
|
@ -1,856 +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 <SHpch.h>
|
|
||||||
|
|
||||||
// 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 }
|
|
||||||
, debugDrawFlags { 0 }
|
|
||||||
, 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 }
|
|
||||||
{}
|
|
||||||
|
|
||||||
SHPhysicsSystem::PhysicsDebugDraw::PhysicsDebugDraw()
|
|
||||||
: SHSystemRoutine { "Physics DebugDraw", true }
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SHPhysicsSystem::GetDrawColliders() const noexcept
|
|
||||||
{
|
|
||||||
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SHPhysicsSystem::GetDrawColliderAABBs() const noexcept
|
|
||||||
{
|
|
||||||
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SHPhysicsSystem::GetDrawBroadPhase() const noexcept
|
|
||||||
{
|
|
||||||
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SHPhysicsSystem::GetDrawContactPoints() const noexcept
|
|
||||||
{
|
|
||||||
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SHPhysicsSystem::GetDrawContactNormals() const noexcept
|
|
||||||
{
|
|
||||||
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_NORMALS);
|
|
||||||
}
|
|
||||||
|
|
||||||
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!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetDrawColliders(bool shouldDraw) noexcept
|
|
||||||
{
|
|
||||||
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER);
|
|
||||||
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
|
|
||||||
|
|
||||||
if (world == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
world->getDebugRenderer().setIsDebugItemDisplayed
|
|
||||||
(
|
|
||||||
rp3d::DebugRenderer::DebugItem::COLLISION_SHAPE,
|
|
||||||
shouldDraw
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetDrawColliderAABBs(bool shouldDraw) noexcept
|
|
||||||
{
|
|
||||||
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB);
|
|
||||||
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
|
|
||||||
|
|
||||||
if (world == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
world->getDebugRenderer().setIsDebugItemDisplayed
|
|
||||||
(
|
|
||||||
rp3d::DebugRenderer::DebugItem::COLLIDER_AABB,
|
|
||||||
shouldDraw
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetDrawBroadPhase(bool shouldDraw) noexcept
|
|
||||||
{
|
|
||||||
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB);
|
|
||||||
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
|
|
||||||
|
|
||||||
if (world == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
world->getDebugRenderer().setIsDebugItemDisplayed
|
|
||||||
(
|
|
||||||
rp3d::DebugRenderer::DebugItem::COLLIDER_BROADPHASE_AABB,
|
|
||||||
shouldDraw
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetDrawContactPoints(bool shouldDraw) noexcept
|
|
||||||
{
|
|
||||||
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS);
|
|
||||||
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
|
|
||||||
|
|
||||||
if (world == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
world->getDebugRenderer().setIsDebugItemDisplayed
|
|
||||||
(
|
|
||||||
rp3d::DebugRenderer::DebugItem::CONTACT_POINT,
|
|
||||||
shouldDraw
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetDrawContactNormals(bool shouldDraw) noexcept
|
|
||||||
{
|
|
||||||
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_NORMALS);
|
|
||||||
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
|
|
||||||
|
|
||||||
if (world == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
world->getDebugRenderer().setIsDebugItemDisplayed
|
|
||||||
(
|
|
||||||
rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL,
|
|
||||||
shouldDraw
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* 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<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::AddPhysicsComponent) };
|
|
||||||
const ReceiverPtr ADD_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ADD_COMPONENT_RECEIVER);
|
|
||||||
SHEventManager::SubscribeTo(SH_COMPONENT_ADDED_EVENT, ADD_COMPONENT_RECEIVER_PTR);
|
|
||||||
|
|
||||||
const std::shared_ptr REMOVE_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::RemovePhysicsComponent) };
|
|
||||||
const ReceiverPtr REMOVE_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(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<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::ResetWorld) };
|
|
||||||
const ReceiverPtr EDITOR_STOP_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(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<SHPhysicsColliderAddedEvent>(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<SHPhysicsColliderRemovedEvent>(COLLIDER_REMOVED_EVENT_DATA, SH_PHYSICS_COLLIDER_REMOVED_EVENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept
|
|
||||||
{
|
|
||||||
auto* system = reinterpret_cast<SHPhysicsSystem*>(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<SHTransformComponent>(entityID);
|
|
||||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(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<SHPhysicsSystem*>(GetSystem());
|
|
||||||
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
|
||||||
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<rp3d::decimal>(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<SHPhysicsSystem*>(GetSystem());
|
|
||||||
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
|
||||||
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::PhysicsDebugDraw::Execute(double) noexcept
|
|
||||||
{
|
|
||||||
const auto* PHYSICS_SYSTEM = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
|
||||||
if (PHYSICS_SYSTEM->debugDrawFlags == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
|
|
||||||
if (debugDrawSystem == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_ERROR("Unable to debug draw physics objects due to missing SHDebugDrawSystem!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& RP3D_DEBUG_RENDERER = PHYSICS_SYSTEM->world->getDebugRenderer();
|
|
||||||
|
|
||||||
const auto& LINES = RP3D_DEBUG_RENDERER.getLines();
|
|
||||||
const auto& TRIANGLES = RP3D_DEBUG_RENDERER.getTriangles();
|
|
||||||
|
|
||||||
// Draw all lines
|
|
||||||
for (uint32_t i = 0; i < RP3D_DEBUG_RENDERER.getNbLines(); ++i)
|
|
||||||
{
|
|
||||||
const auto& LINE = LINES[i];
|
|
||||||
debugDrawSystem->DrawLine(SHColour{ LINE.color1 }, LINE.point1, LINE.point2);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < RP3D_DEBUG_RENDERER.getNbTriangles(); ++i)
|
|
||||||
{
|
|
||||||
const auto& TRIANGLE = TRIANGLES[i];
|
|
||||||
SHColour triColour{ TRIANGLE.color1 };
|
|
||||||
triColour.a() = 1.0f;
|
|
||||||
debugDrawSystem->DrawTri(triColour, TRIANGLE.point1, TRIANGLE.point2, TRIANGLE.point3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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<SHRigidBodyComponent>(entityID);
|
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(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<rp3d::decimal>(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<SHTransformComponent>(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<const SHEventSpec<SHComponentAddedEvent>*>(addComponentEvent.get());
|
|
||||||
|
|
||||||
static const auto RIGID_BODY_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
|
||||||
static const auto COLLIDER_ID = ComponentFamily::GetID<SHColliderComponent>();
|
|
||||||
|
|
||||||
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<SHTransformComponent>(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<SHRigidBodyComponent>(ENTITY_ID);
|
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(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<rp3d::RigidBody*>(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<const SHEventSpec<SHComponentRemovedEvent>*>(removeComponentEvent.get());
|
|
||||||
|
|
||||||
static const auto RIGID_BODY_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
|
||||||
static const auto COLLIDER_ID = ComponentFamily::GetID<SHColliderComponent>();
|
|
||||||
|
|
||||||
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<SHRigidBodyComponent>(ENTITY_ID);
|
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(ENTITY_ID);
|
|
||||||
|
|
||||||
// Wake up all physics objects
|
|
||||||
for (auto& [entityID, object] : map)
|
|
||||||
{
|
|
||||||
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(entityID))
|
|
||||||
reinterpret_cast<rp3d::RigidBody*>(object.rp3dBody)->setIsSleeping(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (REMOVED_ID == RIGID_BODY_ID && physicsObject != nullptr)
|
|
||||||
{
|
|
||||||
world->destroyRigidBody(reinterpret_cast<rp3d::RigidBody*>(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<int>(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<SHRigidBodyComponent>(entityID))
|
|
||||||
{
|
|
||||||
auto* rp3dRigidBody = reinterpret_cast<rp3d::RigidBody*>(physicsObject.rp3dBody);
|
|
||||||
rp3dRigidBody->resetForce();
|
|
||||||
rp3dRigidBody->resetTorque();
|
|
||||||
rp3dRigidBody->setLinearVelocity(SHVec3::Zero);
|
|
||||||
rp3dRigidBody->setAngularVelocity(SHVec3::Zero);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return editorStopEvent->handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace SHADE
|
|
|
@ -1,207 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHPhysicsSystem.h
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Interface 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.
|
|
||||||
****************************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include <reactphysics3d/reactphysics3d.h>
|
|
||||||
|
|
||||||
// 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"
|
|
||||||
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class SH_API SHPhysicsSystem final : public SHSystem
|
|
||||||
, public rp3d::EventListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
struct WorldSettings
|
|
||||||
{
|
|
||||||
SHVec3 gravity;
|
|
||||||
uint16_t numVelocitySolverIterations;
|
|
||||||
uint16_t numPositionSolverIterations;
|
|
||||||
bool sleepingEnabled;
|
|
||||||
};
|
|
||||||
|
|
||||||
using CollisionEvents = std::vector<SHCollisionEvent>;
|
|
||||||
|
|
||||||
enum class DebugDrawFlags : uint8_t
|
|
||||||
{
|
|
||||||
COLLIDER = 1
|
|
||||||
, COLLIDER_AABB = 2
|
|
||||||
, BROAD_PHASE_AABB = 4
|
|
||||||
, CONTACT_POINTS = 8
|
|
||||||
, CONTACT_NORMALS = 16
|
|
||||||
};
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsSystem();
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
[[nodiscard]] double GetFixedDT () 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]] bool GetDrawColliders () const noexcept;
|
|
||||||
[[nodiscard]] bool GetDrawColliderAABBs () const noexcept;
|
|
||||||
[[nodiscard]] bool GetDrawBroadPhase () const noexcept;
|
|
||||||
[[nodiscard]] bool GetDrawContactPoints () const noexcept;
|
|
||||||
[[nodiscard]] bool GetDrawContactNormals () const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] const CollisionEvents& GetCollisionInfo () const noexcept;
|
|
||||||
[[nodiscard]] const CollisionEvents& GetTriggerInfo () 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;
|
|
||||||
|
|
||||||
// TODO(Diren): Can the debug draw flags be done through an enum?
|
|
||||||
void SetDrawColliders (bool shouldDraw) noexcept;
|
|
||||||
void SetDrawColliderAABBs (bool shouldDraw) noexcept;
|
|
||||||
void SetDrawBroadPhase (bool shouldDraw) noexcept;
|
|
||||||
void SetDrawContactPoints (bool shouldDraw) noexcept;
|
|
||||||
void SetDrawContactNormals (bool shouldDraw) noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void Init () override;
|
|
||||||
void Exit () override;
|
|
||||||
|
|
||||||
void AddCollisionShape (EntityID entityID, SHCollisionShape* collider);
|
|
||||||
void RemoveCollisionShape (EntityID entityID, int index);
|
|
||||||
|
|
||||||
void onContact (const rp3d::CollisionCallback::CallbackData& callbackData) override;
|
|
||||||
void onTrigger (const rp3d::OverlapCallback::CallbackData& callbackData) override;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* System Routines */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class SH_API PhysicsPreUpdate final : public SHSystemRoutine
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
PhysicsPreUpdate();
|
|
||||||
void Execute(double dt) noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
PhysicsFixedUpdate();
|
|
||||||
void Execute (double dt) noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SH_API PhysicsPostUpdate final : public SHSystemRoutine
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
PhysicsPostUpdate();
|
|
||||||
void Execute(double dt) noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SH_API PhysicsDebugDraw final : public SHSystemRoutine
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PhysicsDebugDraw();
|
|
||||||
void Execute(double dt) noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
using EntityObjectMap = std::unordered_map<EntityID, SHPhysicsObject>;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Data Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
bool worldUpdated;
|
|
||||||
uint8_t debugDrawFlags;
|
|
||||||
|
|
||||||
double interpolationFactor;
|
|
||||||
double fixedDT;
|
|
||||||
|
|
||||||
rp3d::PhysicsWorld* world;
|
|
||||||
rp3d::PhysicsCommon factory;
|
|
||||||
|
|
||||||
EntityObjectMap map;
|
|
||||||
CollisionEvents collisionInfo;
|
|
||||||
CollisionEvents triggerInfo;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept;
|
|
||||||
SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
|
|
||||||
void DestroyPhysicsObject (EntityID entityID) noexcept;
|
|
||||||
|
|
||||||
static void SyncActiveStates (SHPhysicsObject& physicsObject, bool componentActive) noexcept;
|
|
||||||
void SyncTransforms () noexcept;
|
|
||||||
|
|
||||||
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 <typename RP3DCollisionPair, typename = std::enable_if_t
|
|
||||||
<std::is_same_v<RP3DCollisionPair, rp3d::CollisionCallback::ContactPair>
|
|
||||||
|| std::is_same_v<RP3DCollisionPair, rp3d::OverlapCallback::OverlapPair>>>
|
|
||||||
SHCollisionEvent GenerateCollisionEvent (const RP3DCollisionPair& cp) noexcept;
|
|
||||||
};
|
|
||||||
} // namespace SHADE
|
|
||||||
|
|
||||||
#include "SHPhysicsSystem.hpp"
|
|
|
@ -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 <type_traits>
|
|
||||||
|
|
||||||
// Primary Header
|
|
||||||
#include "SHPhysicsSystem.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Private Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
template <typename RP3DCollisionPair, typename Condition>
|
|
||||||
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<uint32_t>::max();
|
|
||||||
};
|
|
||||||
|
|
||||||
SHCollisionEvent cInfo;
|
|
||||||
|
|
||||||
// Update collision state
|
|
||||||
cInfo.collisionState = static_cast<SHCollisionEvent::State>(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
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \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 <SHpch.h>
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// These are my preferred default values. QoL for modifying these.
|
||||||
|
rp3dWorldSettings.defaultBounciness = 0.0f;
|
||||||
|
rp3dWorldSettings.defaultFrictionCoefficient = 0.4f;
|
||||||
|
|
||||||
|
world = factory.createPhysicsWorld(rp3dWorldSettings);
|
||||||
|
world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
|
@ -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 <reactphysics3d/reactphysics3d.h>
|
||||||
|
|
||||||
|
// 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 = 15;
|
||||||
|
uint16_t numPositionSolverIterations = 8;
|
||||||
|
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
|
|
@ -0,0 +1,228 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsDebugDrawSystem.cpp
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Implementation for the Physics Debug Draw System
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include <SHpch.h>
|
||||||
|
|
||||||
|
// Primary Header
|
||||||
|
#include "SHPhysicsDebugDrawSystem.h"
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Static Data Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
const SHPhysicsDebugDrawSystem::DebugDrawFunction SHPhysicsDebugDrawSystem::drawFunctions[SHPhysicsDebugDrawSystem::NUM_FLAGS] =
|
||||||
|
{
|
||||||
|
SHPhysicsDebugDrawSystem::drawColliders
|
||||||
|
, SHPhysicsDebugDrawSystem::drawColliderAABBs
|
||||||
|
, SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs
|
||||||
|
, SHPhysicsDebugDrawSystem::drawContactPoints
|
||||||
|
, SHPhysicsDebugDrawSystem::drawContactNormals
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsDebugDrawSystem::SHPhysicsDebugDrawSystem() noexcept
|
||||||
|
: debugDrawFlags { 0 }
|
||||||
|
, physicsSystem { nullptr }
|
||||||
|
, rp3dDebugRenderer { nullptr }
|
||||||
|
{
|
||||||
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER)] =
|
||||||
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB)] = SHColour::YELLOW;
|
||||||
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB)] = SHColour::CYAN;
|
||||||
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS)] = SHColour::RED;
|
||||||
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_NORMALS)] = SHColour::RED;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine::PhysicsDebugDrawRoutine()
|
||||||
|
: SHSystemRoutine { "Physics Debug Draw", true }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool SHPhysicsDebugDrawSystem::GetDebugDrawFlag(DebugDrawFlags flag) const noexcept
|
||||||
|
{
|
||||||
|
const auto INT_FLAG = SHUtilities::ConvertEnum(flag);
|
||||||
|
if (INT_FLAG < 0 || INT_FLAG >= NUM_FLAGS)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Invalid Debug Draw Flag Passed {} in. Unable to get debug draw state!", INT_FLAG)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return debugDrawFlags & 1U << SHUtilities::ConvertEnum(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Setter Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::SetDebugDrawFlag(DebugDrawFlags flag, bool value) noexcept
|
||||||
|
{
|
||||||
|
const auto INT_FLAG = SHUtilities::ConvertEnum(flag);
|
||||||
|
if (INT_FLAG < 0 || INT_FLAG >= NUM_FLAGS)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Invalid Debug Draw Flag Passed {} in. Unable to set debug draw state!", INT_FLAG)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
value ? (debugDrawFlags |= 1U << INT_FLAG) : (debugDrawFlags &= ~(1U << INT_FLAG));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Public Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::Init()
|
||||||
|
{
|
||||||
|
SystemFamily::GetID<SHPhysicsDebugDrawSystem>();
|
||||||
|
|
||||||
|
SHASSERT(physicsSystem == nullptr, "Non-existent physics system attached to the physics debug draw system!")
|
||||||
|
physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::Exit()
|
||||||
|
{
|
||||||
|
physicsSystem = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine::Execute(double) noexcept
|
||||||
|
{
|
||||||
|
auto* system = reinterpret_cast<SHPhysicsDebugDrawSystem*>(GetSystem());
|
||||||
|
|
||||||
|
for (int i = 0; i < SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS); ++i)
|
||||||
|
{
|
||||||
|
const bool DRAW = (system->debugDrawFlags & (1U << i)) > 0;
|
||||||
|
if (DRAW)
|
||||||
|
drawFunctions[i](system->rp3dDebugRenderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Private Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::drawColliders(rp3d::DebugRenderer* debugRenderer) noexcept
|
||||||
|
{
|
||||||
|
const auto& COLLIDER_SET = SHComponentManager::GetDense<SHColliderComponent>();
|
||||||
|
for (const auto& COLLIDER : COLLIDER_SET)
|
||||||
|
{
|
||||||
|
for (auto& collisionShape : COLLIDER.GetCollisionShapes())
|
||||||
|
{
|
||||||
|
switch (collisionShape.GetType())
|
||||||
|
{
|
||||||
|
case SHCollisionShape::Type::BOX: debugDrawBox(COLLIDER, collisionShape); break;
|
||||||
|
case SHCollisionShape::Type::SPHERE: debugDrawSphere(COLLIDER, collisionShape); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::drawColliderAABBs(rp3d::DebugRenderer* debugRenderer) noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs(rp3d::DebugRenderer* debugRenderer) noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::drawContactPoints(rp3d::DebugRenderer* debugRenderer) noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::drawContactNormals(rp3d::DebugRenderer* debugRenderer) noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::debugDrawBox(const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept
|
||||||
|
{
|
||||||
|
static constexpr uint32_t NUM_BOX_VERTICES = 8;
|
||||||
|
static const SHVec3 boxVertices[NUM_BOX_VERTICES]
|
||||||
|
{
|
||||||
|
{ 0.5f, 0.5f, -0.5f } // TOP_RIGHT_BACK
|
||||||
|
, { -0.5f, 0.5f, -0.5f } // TOP_LEFT_BACK
|
||||||
|
, { 0.5f, -0.5f, -0.5f } // BTM_RIGHT_BACK
|
||||||
|
, { -0.5f, -0.5f, -0.5f } // BTM_LEFT_BACK
|
||||||
|
, { 0.5f, 0.5f, 0.5f } // TOP_RIGHT_FRONT
|
||||||
|
, { -0.5f, 0.5f, 0.5f } // TOP_LEFT_FRONT
|
||||||
|
, { 0.5f, -0.5f, 0.5f } // BTM_RIGHT_FRONT
|
||||||
|
, { -0.5f, -0.5f, 0.5f } // BTM_LEFT_FRONT
|
||||||
|
};
|
||||||
|
|
||||||
|
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
|
||||||
|
if (debugDrawSystem == nullptr)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to get a debug draw system for Physics Debug Drawing!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* BOX = reinterpret_cast<const SHBoundingBox*>(collisionShape.GetShape());
|
||||||
|
|
||||||
|
// Calculate final position & orientation
|
||||||
|
const SHVec3 FINAL_POS = colliderComponent.GetPosition() + collisionShape.GetPositionOffset();
|
||||||
|
const SHQuaternion FINAL_ROT = colliderComponent.GetOrientation() * SHQuaternion::FromEuler(collisionShape.GetRotationOffset());
|
||||||
|
|
||||||
|
const SHMatrix BOX_TRS = SHMatrix::Scale(BOX->GetWorldExtents() * 2.0f) * SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(FINAL_POS);
|
||||||
|
|
||||||
|
const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN;
|
||||||
|
|
||||||
|
std::array<SHVec3, NUM_BOX_VERTICES> transformedVertices;
|
||||||
|
for (uint32_t i = 0; i < NUM_BOX_VERTICES / 2; ++i)
|
||||||
|
{
|
||||||
|
const uint32_t IDX1 = i;
|
||||||
|
const uint32_t IDX2 = i + NUM_BOX_VERTICES / 2;
|
||||||
|
|
||||||
|
transformedVertices[IDX1] = SHVec3::Transform(boxVertices[IDX1], BOX_TRS);
|
||||||
|
transformedVertices[IDX2] = SHVec3::Transform(boxVertices[IDX2], BOX_TRS);
|
||||||
|
|
||||||
|
// Draw 4 line to connect the quads
|
||||||
|
debugDrawSystem->DrawLine(COLLIDER_COLOUR, transformedVertices[IDX1], transformedVertices[IDX2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A, B, C, D
|
||||||
|
std::array backQuad { transformedVertices[0], transformedVertices[1], transformedVertices[3], transformedVertices[2] };
|
||||||
|
debugDrawSystem->DrawPoly(COLLIDER_COLOUR, backQuad.begin(), backQuad.end());
|
||||||
|
// E, F, G, H
|
||||||
|
std::array frontQuad { transformedVertices[4], transformedVertices[5], transformedVertices[7], transformedVertices[6] };
|
||||||
|
debugDrawSystem->DrawPoly(COLLIDER_COLOUR, frontQuad.begin(), frontQuad.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::debugDrawSphere(const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept
|
||||||
|
{
|
||||||
|
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
|
||||||
|
if (debugDrawSystem == nullptr)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to get a debug draw system for Physics Debug Drawing!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* SPHERE = reinterpret_cast<const SHBoundingSphere*>(collisionShape.GetShape());
|
||||||
|
|
||||||
|
const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN;
|
||||||
|
|
||||||
|
// Calculate final position & orientation
|
||||||
|
const SHVec3 FINAL_POS = colliderComponent.GetPosition() + collisionShape.GetPositionOffset();
|
||||||
|
debugDrawSystem->DrawSphere(COLLIDER_COLOUR, FINAL_POS, SPHERE->GetWorldRadius());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -0,0 +1,123 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsDebugDrawSystem.h
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Interface for the Physics Debug Draw System
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <reactphysics3d/reactphysics3d.h>
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
|
#include "Math/SHColour.h"
|
||||||
|
#include "SHPhysicsSystem.h"
|
||||||
|
#include "Tools/SHUtilities.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class SH_API SHPhysicsDebugDrawSystem final : public SHSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
enum class DebugDrawFlags
|
||||||
|
{
|
||||||
|
COLLIDER
|
||||||
|
, COLLIDER_AABB
|
||||||
|
, BROAD_PHASE_AABB
|
||||||
|
, CONTACT_POINTS
|
||||||
|
, CONTACT_NORMALS
|
||||||
|
|
||||||
|
, NUM_FLAGS
|
||||||
|
};
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsDebugDrawSystem() noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool GetDebugDrawFlag(DebugDrawFlags flag) const noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Setter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SetDebugDrawFlag(DebugDrawFlags flag, bool value) noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void Init() override;
|
||||||
|
void Exit() override;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* System Routines */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class SH_API PhysicsDebugDrawRoutine final : public SHSystemRoutine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
PhysicsDebugDrawRoutine();
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
void Execute(double dt) noexcept override;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
using DebugDrawFunction = void(*)(rp3d::DebugRenderer*) noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static constexpr int NUM_FLAGS = SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS);
|
||||||
|
|
||||||
|
static const DebugDrawFunction drawFunctions[NUM_FLAGS];
|
||||||
|
|
||||||
|
uint8_t debugDrawFlags;
|
||||||
|
SHPhysicsSystem* physicsSystem;
|
||||||
|
rp3d::DebugRenderer* rp3dDebugRenderer;
|
||||||
|
SHColour debugColours[NUM_FLAGS];
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void drawColliders (rp3d::DebugRenderer* debugRenderer) noexcept;
|
||||||
|
static void drawColliderAABBs (rp3d::DebugRenderer* debugRenderer) noexcept;
|
||||||
|
static void drawBroadPhaseAABBs (rp3d::DebugRenderer* debugRenderer) noexcept;
|
||||||
|
static void drawContactPoints (rp3d::DebugRenderer* debugRenderer) noexcept;
|
||||||
|
static void drawContactNormals (rp3d::DebugRenderer* debugRenderer) noexcept;
|
||||||
|
|
||||||
|
static void debugDrawBox (const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
|
||||||
|
static void debugDrawSphere (const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -0,0 +1,343 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \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 <SHpch.h>
|
||||||
|
|
||||||
|
// 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 "Physics/SHPhysicsEvents.h"
|
||||||
|
#include "Scene/SHSceneManager.h"
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
/* Local Helper Functions */
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
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<SHCollisionInfo>& SHPhysicsSystem::GetAllCollisionInfo() const noexcept
|
||||||
|
{
|
||||||
|
return collisionListener.GetCollisionInfoContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<SHCollisionInfo>& 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<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::addPhysicsComponent) };
|
||||||
|
const ReceiverPtr ADD_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ADD_COMPONENT_RECEIVER);
|
||||||
|
SHEventManager::SubscribeTo(SH_COMPONENT_ADDED_EVENT, ADD_COMPONENT_RECEIVER_PTR);
|
||||||
|
|
||||||
|
const std::shared_ptr REMOVE_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::removePhysicsComponent) };
|
||||||
|
const ReceiverPtr REMOVE_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(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<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::onPlay) };
|
||||||
|
const ReceiverPtr ON_PLAY_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ON_PLAY_RECEIVER);
|
||||||
|
SHEventManager::SubscribeTo(SH_EDITOR_ON_PLAY_EVENT, ON_PLAY_RECEIVER_PTR);
|
||||||
|
|
||||||
|
const std::shared_ptr ON_STOP_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::onStop) };
|
||||||
|
const ReceiverPtr ON_STOP_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(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)
|
||||||
|
{
|
||||||
|
static const auto ADD_SHAPE = [&](EntityID entityID, int index)
|
||||||
|
{
|
||||||
|
objectManager.AddCollisionShape(entityID, index);
|
||||||
|
|
||||||
|
const SHPhysicsColliderAddedEvent COLLIDER_ADDED_EVENT_DATA
|
||||||
|
{
|
||||||
|
.entityID = entityID
|
||||||
|
, .colliderType = SHComponentManager::GetComponent<SHColliderComponent>(entityID)->GetCollisionShape(index).GetType()
|
||||||
|
, .colliderIndex = index
|
||||||
|
};
|
||||||
|
|
||||||
|
SHEventManager::BroadcastEvent<SHPhysicsColliderAddedEvent>(COLLIDER_ADDED_EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT);
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef SHEDITOR
|
||||||
|
|
||||||
|
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||||
|
ADD_SHAPE(eid, shapeIndex);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
ADD_SHAPE(eid, shapeIndex);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::RemoveCollisionShape(EntityID eid, int shapeIndex)
|
||||||
|
{
|
||||||
|
static const auto REMOVE_SHAPE = [&](EntityID entityID, int index)
|
||||||
|
{
|
||||||
|
objectManager.RemoveCollisionShape(entityID, index);
|
||||||
|
|
||||||
|
const SHPhysicsColliderRemovedEvent COLLIDER_REMOVED_EVENT_DATA
|
||||||
|
{
|
||||||
|
.entityID = entityID
|
||||||
|
, .colliderIndex = index
|
||||||
|
};
|
||||||
|
|
||||||
|
SHEventManager::BroadcastEvent<SHPhysicsColliderRemovedEvent>(COLLIDER_REMOVED_EVENT_DATA, SH_PHYSICS_COLLIDER_REMOVED_EVENT);
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef SHEDITOR
|
||||||
|
|
||||||
|
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||||
|
REMOVE_SHAPE(eid, shapeIndex);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
REMOVE_SHAPE(eid, shapeIndex);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
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<const SHEventSpec<SHComponentAddedEvent>*>(addComponentEvent.get());
|
||||||
|
|
||||||
|
static const auto RIGID_BODY_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
||||||
|
static const auto COLLIDER_ID = ComponentFamily::GetID<SHColliderComponent>();
|
||||||
|
|
||||||
|
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 SHEDITOR
|
||||||
|
|
||||||
|
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
|
||||||
|
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||||
|
ADDED_ID == RIGID_BODY_ID ? objectManager.AddRigidBody(EID) : objectManager.AddCollider(EID);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
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<const SHEventSpec<SHComponentRemovedEvent>*>(removeComponentEvent.get());
|
||||||
|
|
||||||
|
static const auto RIGID_BODY_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
||||||
|
static const auto COLLIDER_ID = ComponentFamily::GetID<SHColliderComponent>();
|
||||||
|
|
||||||
|
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 SHEDITOR
|
||||||
|
|
||||||
|
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
|
||||||
|
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||||
|
REMOVED_ID == RIGID_BODY_ID ? objectManager.RemoveRigidBody(EID) : objectManager.RemoveCollider(EID);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
REMOVED_ID == RIGID_BODY_ID ? objectManager.RemoveRigidBody(EID) : objectManager.RemoveCollider(EID);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return EVENT_DATA->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHEventHandle SHPhysicsSystem::onPlay(SHEventPtr onPlayEvent)
|
||||||
|
{
|
||||||
|
static const auto BUILD_PHYSICS_OBJECT = [&](SHSceneNode* node)
|
||||||
|
{
|
||||||
|
const EntityID EID = node->GetEntityID();
|
||||||
|
|
||||||
|
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(EID))
|
||||||
|
objectManager.AddRigidBody(EID);
|
||||||
|
|
||||||
|
if (SHComponentManager::HasComponent<SHColliderComponent>(EID))
|
||||||
|
objectManager.AddCollider(EID);
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
// 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& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
|
||||||
|
SCENE_GRAPH.Traverse(BUILD_PHYSICS_OBJECT);
|
||||||
|
|
||||||
|
return onPlayEvent->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHEventHandle SHPhysicsSystem::onStop(SHEventPtr onStopEvent)
|
||||||
|
{
|
||||||
|
// Remove all physics objects
|
||||||
|
objectManager.RemoveAllObjects();
|
||||||
|
objectManager.SetWorld(nullptr);
|
||||||
|
|
||||||
|
// 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
|
|
@ -0,0 +1,212 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsSystem.h
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Interface 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.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
// External Dependencies
|
||||||
|
#include <reactphysics3d/reactphysics3d.h>
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
|
#include "ECS_Base/System/SHFixedSystemRoutine.h"
|
||||||
|
|
||||||
|
#include "Math/Transform/SHTransformComponent.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
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Friends */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
friend class SHPhysicsDebugDrawSystem;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsSystem();
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
[[nodiscard]] double GetFixedDT () const noexcept;
|
||||||
|
[[nodiscard]] const SHPhysicsWorldState::WorldSettings& GetWorldSettings () const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] const std::vector<SHCollisionInfo>& GetAllCollisionInfo () const noexcept;
|
||||||
|
[[nodiscard]] const std::vector<SHCollisionInfo>& 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 SetWorldSettings (const SHPhysicsWorldState::WorldSettings& settings) noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void Init () override;
|
||||||
|
void Exit () override;
|
||||||
|
|
||||||
|
// Specific Handling for Collision Shapes as they are not under the Component System
|
||||||
|
|
||||||
|
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 */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class SH_API PhysicsPreUpdate final : public SHSystemRoutine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
PhysicsPreUpdate();
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
PhysicsFixedUpdate();
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void Execute (double dt) noexcept override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SH_API PhysicsPostUpdate final : public SHSystemRoutine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
PhysicsPostUpdate();
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void Execute(double dt) noexcept override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void postUpdateSyncTransforms
|
||||||
|
(
|
||||||
|
SHPhysicsObject& physicsObject
|
||||||
|
, SHTransformComponent& transformComponent
|
||||||
|
, SHRigidBodyComponent* rigidBodyComponent
|
||||||
|
, SHColliderComponent* colliderComponent
|
||||||
|
, double interpolationFactor
|
||||||
|
) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// System data
|
||||||
|
|
||||||
|
bool worldUpdated;
|
||||||
|
double interpolationFactor;
|
||||||
|
double fixedDT;
|
||||||
|
|
||||||
|
// rp3d
|
||||||
|
|
||||||
|
rp3d::PhysicsCommon factory;
|
||||||
|
|
||||||
|
// Interface objects
|
||||||
|
|
||||||
|
SHPhysicsWorldState worldState;
|
||||||
|
SHPhysicsObjectManager objectManager;
|
||||||
|
SHCollisionListener collisionListener;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHEventHandle addPhysicsComponent (SHEventPtr addComponentEvent) noexcept;
|
||||||
|
SHEventHandle removePhysicsComponent (SHEventPtr removeComponentEvent) noexcept;
|
||||||
|
|
||||||
|
SHEventHandle onPlay (SHEventPtr onPlayEvent);
|
||||||
|
SHEventHandle onStop (SHEventPtr onStopEvent);
|
||||||
|
|
||||||
|
};
|
||||||
|
} // namespace SHADE
|
|
@ -16,35 +16,34 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "SHPhysicsSystemInterface.h"
|
#include "SHPhysicsSystemInterface.h"
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "Physics/SHPhysicsSystem.h"
|
#include "Physics/System/SHPhysicsSystem.h"
|
||||||
#include "Physics/SHPhysicsUtils.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Static Usage Functions */
|
/* Static Usage Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
const std::vector<SHCollisionEvent>& SHPhysicsSystemInterface::GetCollisionInfo() noexcept
|
const std::vector<SHCollisionInfo>& SHPhysicsSystemInterface::GetCollisionInfo() noexcept
|
||||||
{
|
{
|
||||||
static std::vector<SHCollisionEvent> emptyVec;
|
static std::vector<SHCollisionInfo> emptyVec;
|
||||||
|
|
||||||
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||||
if (phySystem)
|
if (phySystem)
|
||||||
{
|
{
|
||||||
return phySystem->GetCollisionInfo();
|
return phySystem->GetAllCollisionInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get collision events. Empty vector returned instead.");
|
SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get collision events. Empty vector returned instead.");
|
||||||
return emptyVec;
|
return emptyVec;
|
||||||
}
|
}
|
||||||
const std::vector<SHCollisionEvent>& SHPhysicsSystemInterface::GetTriggerInfo() noexcept
|
const std::vector<SHCollisionInfo>& SHPhysicsSystemInterface::GetTriggerInfo() noexcept
|
||||||
{
|
{
|
||||||
static std::vector<SHCollisionEvent> emptyVec;
|
static std::vector<SHCollisionInfo> emptyVec;
|
||||||
|
|
||||||
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||||
if (phySystem)
|
if (phySystem)
|
||||||
{
|
{
|
||||||
return phySystem->GetTriggerInfo();
|
return phySystem->GetAllTriggerInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get trigger events. Empty vector returned instead.");
|
SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get trigger events. Empty vector returned instead.");
|
|
@ -19,7 +19,7 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Forward Declarations */
|
/* Forward Declarations */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
class SHCollisionEvent;
|
class SHCollisionInfo;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
|
@ -39,8 +39,8 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Static Usage Functions */
|
/* Static Usage Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
[[nodiscard]] static const std::vector<SHCollisionEvent>& GetCollisionInfo() noexcept;
|
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetCollisionInfo() noexcept;
|
||||||
[[nodiscard]] static const std::vector<SHCollisionEvent>& GetTriggerInfo() noexcept;
|
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetTriggerInfo() noexcept;
|
||||||
[[nodiscard]] static double GetFixedDT() noexcept;
|
[[nodiscard]] static double GetFixedDT() noexcept;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,315 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \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 <SHpch.h>
|
||||||
|
|
||||||
|
// 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<SHPhysicsSystem*>(GetSystem());
|
||||||
|
|
||||||
|
#ifdef SHEDITOR
|
||||||
|
|
||||||
|
auto* editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
|
||||||
|
// 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<SHRigidBodyComponent>();
|
||||||
|
auto& colliderDense = SHComponentManager::GetDense<SHColliderComponent>();
|
||||||
|
|
||||||
|
for (auto& rigidBodyComponent : rigidBodyDense)
|
||||||
|
{
|
||||||
|
const auto* TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(rigidBodyComponent.GetEID());
|
||||||
|
|
||||||
|
if (TRANSFORM && TRANSFORM->HasChanged())
|
||||||
|
{
|
||||||
|
rigidBodyComponent.position = TRANSFORM->GetWorldPosition();
|
||||||
|
rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& colliderComponent : colliderDense)
|
||||||
|
{
|
||||||
|
const auto* TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(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<SHPhysicsSystem*>(GetSystem());
|
||||||
|
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
||||||
|
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<rp3d::decimal>(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<SHPhysicsSystem*>(GetSystem());
|
||||||
|
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
||||||
|
|
||||||
|
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<SHTransformComponent>(entityID);
|
||||||
|
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
||||||
|
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(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
|
||||||
|
physicsSystem->collisionListener.CleanContainers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Private Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsSystem::PhysicsPreUpdate::syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept
|
||||||
|
{
|
||||||
|
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
||||||
|
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(eid);
|
||||||
|
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(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<rp3d::decimal>(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
|
|
@ -25,7 +25,10 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Events/SHEvent.h"
|
#include "Events/SHEvent.h"
|
||||||
#include "Events/SHEventReceiver.h"
|
#include "Events/SHEventReceiver.h"
|
||||||
#include "Events/SHEventManager.hpp"
|
#include "Events/SHEventManager.hpp"
|
||||||
#include "Physics/SHPhysicsSystem.h"
|
#include "Physics/System/SHPhysicsSystem.h"
|
||||||
|
#include "Physics/SHPhysicsEvents.h"
|
||||||
|
#include "Scene/SHSceneGraphEvents.h"
|
||||||
|
|
||||||
#include "Assets/SHAssetMacros.h"
|
#include "Assets/SHAssetMacros.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "Camera/SHCameraComponent.h"
|
#include "Camera/SHCameraComponent.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
||||||
#include "Math/Geometry/SHBoundingBox.h"
|
#include "Math/Geometry/SHBoundingBox.h"
|
||||||
#include "Math/Geometry/SHBoundingSphere.h"
|
#include "Math/Geometry/SHBoundingSphere.h"
|
||||||
#include "Physics/SHCollisionShape.h"
|
#include "Physics/Interface/SHCollisionShape.h"
|
||||||
#include "Resource/SHResourceManager.h"
|
#include "Resource/SHResourceManager.h"
|
||||||
#include "Math/Vector/SHVec2.h"
|
#include "Math/Vector/SHVec2.h"
|
||||||
#include "Math/Vector/SHVec3.h"
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
|
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||||
#include "SHSerializationTools.h"
|
#include "SHSerializationTools.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
using namespace SHADE;
|
using namespace SHADE;
|
||||||
|
@ -130,14 +130,14 @@ namespace YAML
|
||||||
{
|
{
|
||||||
case SHCollisionShape::Type::BOX:
|
case SHCollisionShape::Type::BOX:
|
||||||
{
|
{
|
||||||
auto const bb = reinterpret_cast<SHBoundingBox*>(rhs.GetShape());
|
const auto* BOX = reinterpret_cast<const SHBoundingBox*>(rhs.GetShape());
|
||||||
node[HalfExtents] = bb->GetRelativeExtents();
|
node[HalfExtents] = BOX->GetRelativeExtents();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SHCollisionShape::Type::SPHERE:
|
case SHCollisionShape::Type::SPHERE:
|
||||||
{
|
{
|
||||||
auto const bs = reinterpret_cast<SHBoundingSphere*>(rhs.GetShape());
|
const auto* SPHERE = reinterpret_cast<const SHBoundingSphere*>(rhs.GetShape());
|
||||||
node[Radius] = bs->GetRelativeRadius();
|
node[Radius] = SPHERE->GetRelativeRadius();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SHCollisionShape::Type::CAPSULE: break;
|
case SHCollisionShape::Type::CAPSULE: break;
|
||||||
|
|
|
@ -35,22 +35,12 @@ namespace SHADE
|
||||||
/**
|
/**
|
||||||
* @brief Converts an enum class member from it's type to any other type.
|
* @brief Converts an enum class member from it's type to any other type.
|
||||||
* @tparam InputType Restricted to an enum class
|
* @tparam InputType Restricted to an enum class
|
||||||
* @tparam OutputType The type to convert the enum class member to. Defaults to int.
|
* @tparam OutputType The type to convert the enum class member to. Defaults to the underlying type.
|
||||||
* @param[in] enumClassMember A member of the specified enum class.
|
* @param[in] enumClassMember A member of the specified enum class.
|
||||||
* @returns The value of the enum class member in the output type.
|
* @returns The value of the enum class member in the output type.
|
||||||
*/
|
*/
|
||||||
template <IsEnum InputType, IsIntegral OutputType = std::underlying_type_t<InputType>>
|
template <IsEnum InputType, IsIntegral OutputType = std::underlying_type_t<InputType>>
|
||||||
static constexpr OutputType ConvertEnum(InputType enumClassMember) noexcept;
|
static constexpr OutputType ConvertEnum(InputType enumClassMember) noexcept;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Converts an enum class member from it's type to the underlying type.
|
|
||||||
* @tparam Enum Restricted to an enum class
|
|
||||||
* @param[in] value A member of the specified enum class.
|
|
||||||
* @returns The value of the enum class member in the output type.
|
|
||||||
*/
|
|
||||||
template<typename Enum>
|
|
||||||
static constexpr typename std::underlying_type_t<Enum> ToUnderlying (Enum value) noexcept;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
||||||
|
|
|
@ -24,11 +24,4 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
return static_cast<OutputType>(enumClassMember);
|
return static_cast<OutputType>(enumClassMember);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Enum>
|
|
||||||
constexpr typename std::underlying_type_t<Enum> SHUtilities::ToUnderlying(Enum value) noexcept
|
|
||||||
{
|
|
||||||
return static_cast<typename std::underlying_type_t<Enum>>(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -15,7 +15,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// External Dependencies
|
// External Dependencies
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "Components/Component.hxx"
|
#include "Components/Component.hxx"
|
||||||
#include "Math/Vector3.hxx"
|
#include "Math/Vector3.hxx"
|
||||||
|
|
|
@ -15,7 +15,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// External Dependencies
|
// External Dependencies
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "Components/Component.hxx"
|
#include "Components/Component.hxx"
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
// External Dependencies
|
// External Dependencies
|
||||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
#include "Scene/SHSceneManager.h"
|
#include "Scene/SHSceneManager.h"
|
||||||
#include "Scene/SHSceneGraph.h"
|
#include "Scene/SHSceneGraph.h"
|
||||||
#include "Tools/SHLog.h"
|
#include "Tools/SHLog.h"
|
||||||
|
|
|
@ -16,7 +16,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
// External Dependencies
|
// External Dependencies
|
||||||
#include "FRC/SHFramerateController.h"
|
#include "FRC/SHFramerateController.h"
|
||||||
#include "Physics/SHPhysicsSystemInterface.h"
|
#include "Physics/System/SHPhysicsSystemInterface.h"
|
||||||
// Primary Header
|
// Primary Header
|
||||||
#include "Time.hxx"
|
#include "Time.hxx"
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,9 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Engine/Entity.hxx"
|
#include "Engine/Entity.hxx"
|
||||||
#include "Serialisation/SerialisationUtilities.hxx"
|
#include "Serialisation/SerialisationUtilities.hxx"
|
||||||
#include "Engine/Application.hxx"
|
#include "Engine/Application.hxx"
|
||||||
#include "Physics/SHPhysicsSystemInterface.h"
|
#include "Physics/System/SHPhysicsSystemInterface.h"
|
||||||
#include "Physics/SHPhysicsUtils.h"
|
#include "Physics/SHPhysicsEvents.h"
|
||||||
|
#include "Physics/Collision/SHCollisionInfo.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -555,13 +556,13 @@ namespace SHADE
|
||||||
Script^ script = entityScripts[i];
|
Script^ script = entityScripts[i];
|
||||||
switch (collisionInfo.GetCollisionState())
|
switch (collisionInfo.GetCollisionState())
|
||||||
{
|
{
|
||||||
case SHCollisionEvent::State::ENTER:
|
case SHCollisionInfo::State::ENTER:
|
||||||
script->OnCollisionEnter(info);
|
script->OnCollisionEnter(info);
|
||||||
break;
|
break;
|
||||||
case SHCollisionEvent::State::STAY:
|
case SHCollisionInfo::State::STAY:
|
||||||
script->OnCollisionStay(info);
|
script->OnCollisionStay(info);
|
||||||
break;
|
break;
|
||||||
case SHCollisionEvent::State::EXIT:
|
case SHCollisionInfo::State::EXIT:
|
||||||
script->OnCollisionExit(info);
|
script->OnCollisionExit(info);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -597,13 +598,13 @@ namespace SHADE
|
||||||
Script^ script = entityScripts[i];
|
Script^ script = entityScripts[i];
|
||||||
switch (triggerInfo.GetCollisionState())
|
switch (triggerInfo.GetCollisionState())
|
||||||
{
|
{
|
||||||
case SHCollisionEvent::State::ENTER:
|
case SHCollisionInfo::State::ENTER:
|
||||||
script->OnTriggerEnter(info);
|
script->OnTriggerEnter(info);
|
||||||
break;
|
break;
|
||||||
case SHCollisionEvent::State::STAY:
|
case SHCollisionInfo::State::STAY:
|
||||||
script->OnTriggerStay(info);
|
script->OnTriggerStay(info);
|
||||||
break;
|
break;
|
||||||
case SHCollisionEvent::State::EXIT:
|
case SHCollisionInfo::State::EXIT:
|
||||||
script->OnTriggerExit(info);
|
script->OnTriggerExit(info);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue