Merge pull request #120 from SHADE-DP/SP3-2-Physics
SP3-2 Physics Bugfixes NEW Forces can be added to the rigid body. BUGFIXES Rigidbody transforms can be modified while the editor is in play. Deleting a rigid body no longer causes a crash (please let me know if it does happen again and how to replicate it) Deleting a collider actually gets rid of the collider On editor stop, forces and velocities are cleared from rigid bodies.
This commit is contained in:
commit
29dccf77b3
|
@ -35,6 +35,23 @@ namespace SHADE
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ComponentType, typename EnforcedComponent, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true, std::enable_if_t<std::is_base_of_v<SHComponent, EnforcedComponent>, bool> = true>
|
||||||
|
bool DrawAddComponentWithEnforcedComponentButton(EntityID const& eid)
|
||||||
|
{
|
||||||
|
bool selected = false;
|
||||||
|
if (!SHComponentManager::HasComponent<ComponentType>(eid))
|
||||||
|
{
|
||||||
|
if(selected = ImGui::Selectable(std::format("Add {}", rttr::type::get<ComponentType>().get_name().data()).data()); selected)
|
||||||
|
{
|
||||||
|
if(SHComponentManager::GetComponent_s<EnforcedComponent>(eid) == nullptr)
|
||||||
|
SHComponentManager::AddComponent<EnforcedComponent>(eid);
|
||||||
|
|
||||||
|
SHComponentManager::AddComponent<ComponentType>(eid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
SHEditorInspector::SHEditorInspector()
|
SHEditorInspector::SHEditorInspector()
|
||||||
:SHEditorWindow("Inspector", ImGuiWindowFlags_MenuBar)
|
:SHEditorWindow("Inspector", ImGuiWindowFlags_MenuBar)
|
||||||
{
|
{
|
||||||
|
@ -90,15 +107,13 @@ namespace SHADE
|
||||||
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
|
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
|
||||||
{
|
{
|
||||||
DrawAddComponentButton<SHTransformComponent>(eid);
|
DrawAddComponentButton<SHTransformComponent>(eid);
|
||||||
DrawAddComponentButton<SHRenderable>(eid);
|
|
||||||
DrawAddComponentButton<SHColliderComponent>(eid);
|
// Components that require Transforms
|
||||||
if(DrawAddComponentButton<SHRigidBodyComponent>(eid))
|
|
||||||
{
|
DrawAddComponentWithEnforcedComponentButton<SHRenderable, SHTransformComponent>(eid);
|
||||||
if(SHComponentManager::GetComponent_s<SHTransformComponent>(eid) == nullptr)
|
DrawAddComponentWithEnforcedComponentButton<SHRigidBodyComponent, SHTransformComponent>(eid);
|
||||||
{
|
DrawAddComponentWithEnforcedComponentButton<SHColliderComponent, SHTransformComponent>(eid);
|
||||||
SHComponentManager::AddComponent<SHTransformComponent>(eid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
#include "SHEvent.h"
|
#include "SHEvent.h"
|
||||||
#include "SHEventReceiver.h"
|
#include "SHEventReceiver.h"
|
||||||
|
#include "SH_API.h"
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
INSTRUCTIONS FOR USE:
|
INSTRUCTIONS FOR USE:
|
||||||
|
@ -67,7 +68,7 @@ namespace SHADE
|
||||||
using EventManagerListener = std::function<void(SHEvent)>;
|
using EventManagerListener = std::function<void(SHEvent)>;
|
||||||
|
|
||||||
|
|
||||||
class SHEventManager
|
class SH_API SHEventManager
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -61,9 +61,9 @@ namespace SHADE
|
||||||
|
|
||||||
void SHTransformSystem::Init()
|
void SHTransformSystem::Init()
|
||||||
{
|
{
|
||||||
std::shared_ptr thisReceiver { std::make_shared<SHEventReceiverSpec<SHTransformSystem>>(this, &SHTransformSystem::ChangeParent) };
|
const std::shared_ptr CHANGE_PARENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHTransformSystem>>(this, &SHTransformSystem::ChangeParent) };
|
||||||
ReceiverPtr receiver = std::dynamic_pointer_cast<SHEventReceiver>(thisReceiver);
|
const ReceiverPtr CHANGE_PARENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(CHANGE_PARENT_RECEIVER);
|
||||||
SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, receiver);
|
SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, CHANGE_PARENT_RECEIVER_PTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHTransformSystem::Exit()
|
void SHTransformSystem::Exit()
|
||||||
|
@ -75,50 +75,6 @@ namespace SHADE
|
||||||
/* Private Function Member Definitions */
|
/* Private Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHEventHandle SHTransformSystem::ChangeParent(SHEventPtr changeParentEvent)
|
|
||||||
{
|
|
||||||
const auto& eventData = reinterpret_cast<const SHEventSpec<SHSceneGraphChangeParentEvent>*>(changeParentEvent.get());
|
|
||||||
|
|
||||||
auto* node = eventData->data->node;
|
|
||||||
auto* tf = SHComponentManager::GetComponent_s<SHTransformComponent>(node->GetEntityID());
|
|
||||||
|
|
||||||
// Recompute local transform and store localToWorld Matrix
|
|
||||||
SHMatrix localToWorld = SHMatrix::Identity;
|
|
||||||
SHMatrix worldToLocal = SHMatrix::Identity;
|
|
||||||
|
|
||||||
auto* newParent = eventData->data->newParent;
|
|
||||||
const auto* PARENT_TF = SHComponentManager::GetComponent_s<SHTransformComponent>(newParent->GetEntityID());
|
|
||||||
if (PARENT_TF != nullptr) // Not the root
|
|
||||||
{
|
|
||||||
localToWorld = PARENT_TF->GetTRS();
|
|
||||||
worldToLocal = SHMatrix::Inverse(localToWorld);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maintain World Transform and recompute Local Transform
|
|
||||||
|
|
||||||
// Compute Local Position
|
|
||||||
tf->local.position = SHVec3::Transform(tf->world.position, worldToLocal);
|
|
||||||
|
|
||||||
|
|
||||||
tf->localRotation = tf->worldRotation;
|
|
||||||
tf->local.scale = tf->world.scale;
|
|
||||||
|
|
||||||
if (PARENT_TF != nullptr)
|
|
||||||
{
|
|
||||||
// Compute Local Rotation
|
|
||||||
tf->localRotation -= PARENT_TF->GetLocalRotation();
|
|
||||||
|
|
||||||
// Compute Local Scale
|
|
||||||
tf->local.scale /= PARENT_TF->GetLocalScale();
|
|
||||||
}
|
|
||||||
|
|
||||||
tf->local.trs = localToWorld;
|
|
||||||
|
|
||||||
// Propagate maintaining world transform down the branch
|
|
||||||
UpdateChildrenLocalTransforms(node);
|
|
||||||
return eventData->handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHTransformSystem::UpdateChildrenLocalTransforms(SHSceneNode* node)
|
void SHTransformSystem::UpdateChildrenLocalTransforms(SHSceneNode* node)
|
||||||
{
|
{
|
||||||
// Structure is similar to update entity, albeit without a queue to do being a forced update
|
// Structure is similar to update entity, albeit without a queue to do being a forced update
|
||||||
|
@ -300,4 +256,49 @@ namespace SHADE
|
||||||
tf.world.ComputeTRS();
|
tf.world.ComputeTRS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHEventHandle SHTransformSystem::ChangeParent(SHEventPtr changeParentEvent)
|
||||||
|
{
|
||||||
|
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHSceneGraphChangeParentEvent>*>(changeParentEvent.get());
|
||||||
|
|
||||||
|
auto* node = EVENT_DATA->data->node;
|
||||||
|
auto* tf = SHComponentManager::GetComponent_s<SHTransformComponent>(node->GetEntityID());
|
||||||
|
|
||||||
|
// Recompute local transform and store localToWorld Matrix
|
||||||
|
SHMatrix localToWorld = SHMatrix::Identity;
|
||||||
|
SHMatrix worldToLocal = SHMatrix::Identity;
|
||||||
|
|
||||||
|
auto* newParent = EVENT_DATA->data->newParent;
|
||||||
|
const auto* PARENT_TF = SHComponentManager::GetComponent_s<SHTransformComponent>(newParent->GetEntityID());
|
||||||
|
if (PARENT_TF != nullptr) // Not the root
|
||||||
|
{
|
||||||
|
localToWorld = PARENT_TF->GetTRS();
|
||||||
|
worldToLocal = SHMatrix::Inverse(localToWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maintain World Transform and recompute Local Transform
|
||||||
|
|
||||||
|
// Compute Local Position
|
||||||
|
tf->local.position = SHVec3::Transform(tf->world.position, worldToLocal);
|
||||||
|
|
||||||
|
|
||||||
|
tf->localRotation = tf->worldRotation;
|
||||||
|
tf->local.scale = tf->world.scale;
|
||||||
|
|
||||||
|
if (PARENT_TF != nullptr)
|
||||||
|
{
|
||||||
|
// Compute Local Rotation
|
||||||
|
tf->localRotation -= PARENT_TF->GetLocalRotation();
|
||||||
|
|
||||||
|
// Compute Local Scale
|
||||||
|
tf->local.scale /= PARENT_TF->GetLocalScale();
|
||||||
|
}
|
||||||
|
|
||||||
|
tf->local.trs = localToWorld;
|
||||||
|
|
||||||
|
// Propagate maintaining world transform down the branch
|
||||||
|
UpdateChildrenLocalTransforms(node);
|
||||||
|
|
||||||
|
return EVENT_DATA->handle;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -11,9 +11,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "SHTransformComponent.h"
|
|
||||||
#include "Scene/SHSceneGraph.h"
|
|
||||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
|
#include "Scene/SHSceneGraph.h"
|
||||||
|
#include "SHTransformComponent.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -53,17 +53,6 @@ namespace SHADE
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
TransformPostLogicUpdate ();
|
TransformPostLogicUpdate ();
|
||||||
~TransformPostLogicUpdate () = default;
|
|
||||||
|
|
||||||
TransformPostLogicUpdate (const TransformPostLogicUpdate&) = delete;
|
|
||||||
TransformPostLogicUpdate (TransformPostLogicUpdate&&) = delete;
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
/* Operator Overloads */
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
TransformPostLogicUpdate& operator= (const TransformPostLogicUpdate&) = delete;
|
|
||||||
TransformPostLogicUpdate& operator= (TransformPostLogicUpdate&&) = delete;
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
|
@ -80,17 +69,6 @@ namespace SHADE
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
TransformPostPhysicsUpdate ();
|
TransformPostPhysicsUpdate ();
|
||||||
~TransformPostPhysicsUpdate () = default;
|
|
||||||
|
|
||||||
TransformPostPhysicsUpdate (const TransformPostPhysicsUpdate&) = delete;
|
|
||||||
TransformPostPhysicsUpdate (TransformPostPhysicsUpdate&&) = delete;
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
/* Operator Overloads */
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
TransformPostPhysicsUpdate& operator= (const TransformPostPhysicsUpdate&) = delete;
|
|
||||||
TransformPostPhysicsUpdate& operator= (TransformPostPhysicsUpdate&&) = delete;
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
|
@ -111,11 +89,14 @@ namespace SHADE
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHEventHandle ChangeParent (SHEventPtr changeParentEvent);
|
|
||||||
static void UpdateChildrenLocalTransforms (SHSceneNode* node);
|
static void UpdateChildrenLocalTransforms (SHSceneNode* node);
|
||||||
|
|
||||||
static void UpdateEntity (const SHSceneNode* node, bool clearDirtyFlag);
|
static void UpdateEntity (const SHSceneNode* node, bool clearDirtyFlag);
|
||||||
static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr);
|
static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr);
|
||||||
|
|
||||||
|
// Event Handlers
|
||||||
|
|
||||||
|
SHEventHandle ChangeParent (SHEventPtr changeParentEvent);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ namespace SHADE
|
||||||
|
|
||||||
SHColliderComponent::SHColliderComponent() noexcept
|
SHColliderComponent::SHColliderComponent() noexcept
|
||||||
: system { nullptr }
|
: system { nullptr }
|
||||||
, colliders {}
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -69,31 +68,24 @@ namespace SHADE
|
||||||
void SHColliderComponent::OnCreate()
|
void SHColliderComponent::OnCreate()
|
||||||
{
|
{
|
||||||
system = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
system = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||||
if (!system)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Physics system does not exist, Collider Component not added!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
system->AddCollider(GetEID());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHColliderComponent::OnDestroy()
|
void SHColliderComponent::OnDestroy()
|
||||||
{
|
{
|
||||||
if (!system)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to remove Collider component!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
system->RemoveCollider(GetEID());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHBoundingBox* SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset) noexcept
|
SHBoundingBox* SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset) noexcept
|
||||||
{
|
{
|
||||||
const auto TYPE = SHCollider::Type::BOX;
|
if (!system)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Physics system does not exist, unable to add Box Collider!")
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
auto boxPair = std::make_pair(SHCollider{TYPE}, true);
|
static constexpr auto TYPE = SHCollider::Type::BOX;
|
||||||
|
|
||||||
|
auto boxPair = std::make_pair(SHCollider{ TYPE }, true);
|
||||||
auto& collider = colliders.emplace_back(boxPair).first;
|
auto& collider = colliders.emplace_back(boxPair).first;
|
||||||
|
|
||||||
const auto* tf = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
const auto* tf = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
||||||
|
@ -101,12 +93,6 @@ namespace SHADE
|
||||||
collider.SetPositionOffset(posOffset);
|
collider.SetPositionOffset(posOffset);
|
||||||
collider.SetAsBoundingBox(tf->GetWorldScale() * halfExtents);
|
collider.SetAsBoundingBox(tf->GetWorldScale() * halfExtents);
|
||||||
|
|
||||||
if (!system)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to add Box Collider!")
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify Physics System
|
// Notify Physics System
|
||||||
system->AddCollisionShape(GetEID(), &collider);
|
system->AddCollisionShape(GetEID(), &collider);
|
||||||
|
|
||||||
|
@ -115,7 +101,13 @@ namespace SHADE
|
||||||
|
|
||||||
SHBoundingSphere* SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept
|
SHBoundingSphere* SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept
|
||||||
{
|
{
|
||||||
const auto TYPE = SHCollider::Type::SPHERE;
|
if (!system)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!")
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto TYPE = SHCollider::Type::SPHERE;
|
||||||
|
|
||||||
auto spherePair = std::make_pair(SHCollider{ TYPE }, true);
|
auto spherePair = std::make_pair(SHCollider{ TYPE }, true);
|
||||||
auto& collider = colliders.emplace_back(spherePair).first;
|
auto& collider = colliders.emplace_back(spherePair).first;
|
||||||
|
@ -126,13 +118,7 @@ namespace SHADE
|
||||||
|
|
||||||
const SHVec3 TF_WORLD_SCALE = tf->GetWorldScale();
|
const SHVec3 TF_WORLD_SCALE = tf->GetWorldScale();
|
||||||
const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z });
|
const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z });
|
||||||
collider.SetAsBoundingSphere(MAX_SCALE * 0.5f);
|
collider.SetAsBoundingSphere(MAX_SCALE * 0.5f * radius);
|
||||||
|
|
||||||
if (!system)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!")
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify Physics System
|
// Notify Physics System
|
||||||
system->AddCollisionShape(GetEID(), &collider);
|
system->AddCollisionShape(GetEID(), &collider);
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
using ColliderDirtyPair = std::pair<SHCollider, bool>;
|
using ColliderDirtyPair = std::pair<SHCollider, bool>;
|
||||||
using Colliders = std::vector<ColliderDirtyPair>;
|
using Colliders = std::vector<ColliderDirtyPair>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -81,10 +81,10 @@ namespace SHADE
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void OnCreate () override;
|
void OnCreate () override;
|
||||||
void OnDestroy () override;
|
void OnDestroy () override;
|
||||||
|
|
||||||
void RemoveCollider (int index);
|
void RemoveCollider (int index);
|
||||||
|
|
||||||
SHBoundingBox* AddBoundingBox (const SHVec3& halfExtents = SHVec3::One, const SHVec3& posOffset = SHVec3::Zero) noexcept;
|
SHBoundingBox* AddBoundingBox (const SHVec3& halfExtents = SHVec3::One, const SHVec3& posOffset = SHVec3::Zero) noexcept;
|
||||||
SHBoundingSphere* AddBoundingSphere (float radius = 1.0f, const SHVec3& posOffset = SHVec3::Zero) noexcept;
|
SHBoundingSphere* AddBoundingSphere (float radius = 1.0f, const SHVec3& posOffset = SHVec3::Zero) noexcept;
|
||||||
|
|
|
@ -28,11 +28,10 @@ namespace SHADE
|
||||||
, flags { 0 }
|
, flags { 0 }
|
||||||
, dirtyFlags { 0 }
|
, dirtyFlags { 0 }
|
||||||
, interpolate { true }
|
, interpolate { true }
|
||||||
, system { nullptr }
|
, rp3dBody { nullptr }
|
||||||
, mass { 1.0f }
|
, mass { 1.0f }
|
||||||
, drag { 0.01f }
|
, drag { 0.01f }
|
||||||
, angularDrag { 0.01f }
|
, angularDrag { 0.01f }
|
||||||
|
|
||||||
{
|
{
|
||||||
// Set default flags: Gravity & Sleeping enabled
|
// Set default flags: Gravity & Sleeping enabled
|
||||||
flags |= 1U << 0;
|
flags |= 1U << 0;
|
||||||
|
@ -161,7 +160,13 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept
|
void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept
|
||||||
{
|
{
|
||||||
constexpr int FLAG_POS = 0;
|
static constexpr int FLAG_POS = 0;
|
||||||
|
|
||||||
|
if (type != Type::DYNAMIC)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Cannot enable gravity of a non-dynamic object {}", GetEID())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dirtyFlags |= 1U << FLAG_POS;
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
enableGravity ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
enableGravity ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||||
|
@ -169,7 +174,13 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept
|
void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept
|
||||||
{
|
{
|
||||||
constexpr int FLAG_POS = 1;
|
static constexpr int FLAG_POS = 1;
|
||||||
|
|
||||||
|
if (type != Type::DYNAMIC)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Cannot enable sleeping of a non-dynamic object {}", GetEID())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dirtyFlags |= 1U << 1;
|
dirtyFlags |= 1U << 1;
|
||||||
isAllowedToSleep ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
isAllowedToSleep ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||||
|
@ -177,7 +188,13 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept
|
void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept
|
||||||
{
|
{
|
||||||
constexpr int FLAG_POS = 2;
|
static constexpr int FLAG_POS = 2;
|
||||||
|
|
||||||
|
if (type == Type::STATIC)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dirtyFlags |= 1U << 2;
|
dirtyFlags |= 1U << 2;
|
||||||
freezePositionX ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
freezePositionX ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||||
|
@ -185,7 +202,13 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept
|
void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept
|
||||||
{
|
{
|
||||||
constexpr int FLAG_POS = 3;
|
static constexpr int FLAG_POS = 3;
|
||||||
|
|
||||||
|
if (type == Type::STATIC)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dirtyFlags |= 1U << 2;
|
dirtyFlags |= 1U << 2;
|
||||||
freezePositionY ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
freezePositionY ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||||
|
@ -193,7 +216,13 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept
|
void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept
|
||||||
{
|
{
|
||||||
constexpr int FLAG_POS = 4;
|
static constexpr int FLAG_POS = 4;
|
||||||
|
|
||||||
|
if (type == Type::STATIC)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dirtyFlags |= 1U << 2;
|
dirtyFlags |= 1U << 2;
|
||||||
freezePositionZ ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
freezePositionZ ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||||
|
@ -201,7 +230,13 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept
|
void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept
|
||||||
{
|
{
|
||||||
constexpr int FLAG_POS = 5;
|
static constexpr int FLAG_POS = 5;
|
||||||
|
|
||||||
|
if (type == Type::STATIC)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dirtyFlags |= 1U << 3;
|
dirtyFlags |= 1U << 3;
|
||||||
freezeRotationX ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
freezeRotationX ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||||
|
@ -209,7 +244,13 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept
|
void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept
|
||||||
{
|
{
|
||||||
constexpr int FLAG_POS = 6;
|
static constexpr int FLAG_POS = 6;
|
||||||
|
|
||||||
|
if (type == Type::STATIC)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dirtyFlags |= 1U << 3;
|
dirtyFlags |= 1U << 3;
|
||||||
freezeRotationY ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
freezeRotationY ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||||
|
@ -217,7 +258,13 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept
|
void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept
|
||||||
{
|
{
|
||||||
constexpr int FLAG_POS = 7;
|
static constexpr int FLAG_POS = 7;
|
||||||
|
|
||||||
|
if (type == Type::STATIC)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dirtyFlags |= 1U << 3;
|
dirtyFlags |= 1U << 3;
|
||||||
freezeRotationZ ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
freezeRotationZ ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||||
|
@ -230,30 +277,60 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetMass(float newMass) noexcept
|
void SHRigidBodyComponent::SetMass(float newMass) noexcept
|
||||||
{
|
{
|
||||||
|
if (type != Type::DYNAMIC)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dirtyFlags |= 1U << 5;
|
dirtyFlags |= 1U << 5;
|
||||||
mass = newMass;
|
mass = newMass;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
|
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
|
||||||
{
|
{
|
||||||
|
if (type != Type::DYNAMIC)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Cannot set drag of a non-dynamic object {}", GetEID())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dirtyFlags |= 1U << 6;
|
dirtyFlags |= 1U << 6;
|
||||||
drag = newDrag;
|
drag = newDrag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept
|
void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept
|
||||||
{
|
{
|
||||||
|
if (type != Type::DYNAMIC)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Cannot set angular drag of a non-dynamic object {}", GetEID())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dirtyFlags |= 1U << 7;
|
dirtyFlags |= 1U << 7;
|
||||||
angularDrag = newAngularDrag;
|
angularDrag = newAngularDrag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
|
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
|
||||||
{
|
{
|
||||||
|
if (type == Type::STATIC)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Cannot set linear velocity of a static object {}", GetEID())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dirtyFlags |= 1U << 8;
|
dirtyFlags |= 1U << 8;
|
||||||
linearVelocity = newLinearVelocity;
|
linearVelocity = newLinearVelocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
|
void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
|
||||||
{
|
{
|
||||||
|
if (type == Type::STATIC)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Cannot set angular velocity of a static object {}", GetEID())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dirtyFlags |= 1U << 9;
|
dirtyFlags |= 1U << 9;
|
||||||
angularVelocity = newAngularVelocity;
|
angularVelocity = newAngularVelocity;
|
||||||
}
|
}
|
||||||
|
@ -262,125 +339,92 @@ namespace SHADE
|
||||||
/* Public Function Member Definitions */
|
/* Public Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SHRigidBodyComponent::OnCreate()
|
|
||||||
{
|
|
||||||
system = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
|
||||||
if (!system)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Physics system does not exist, Rigid Body Component not added!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify Physics System
|
|
||||||
system->AddRigidBody(GetEID());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHRigidBodyComponent::OnDestroy()
|
|
||||||
{
|
|
||||||
// Notify Physics System
|
|
||||||
if (!system)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to remove Rigid Body Component!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
system->RemoveRigidBody(GetEID());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept
|
void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept
|
||||||
{
|
{
|
||||||
if (!system)
|
if (rp3dBody == nullptr)
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
|
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify Physics Systems
|
rp3dBody->applyWorldForceAtCenterOfMass(force);
|
||||||
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 (!system)
|
if (rp3dBody == nullptr)
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
|
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify Physics Systems
|
rp3dBody->applyWorldForceAtLocalPosition(force, localPos);
|
||||||
system->AddForceAtLocalPos(GetEID(), 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 (!system)
|
if (rp3dBody == nullptr)
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
|
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify Physics Systems
|
rp3dBody->applyWorldForceAtWorldPosition(force, worldPos);
|
||||||
system->AddForceAtWorldPos(GetEID(), force, worldPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept
|
void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept
|
||||||
{
|
{
|
||||||
if (!system)
|
if (rp3dBody == nullptr)
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
|
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify Physics Systems
|
rp3dBody->applyLocalForceAtCenterOfMass(relativeForce);
|
||||||
system->AddRelativeForce(GetEID(), force);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept
|
void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept
|
||||||
{
|
{
|
||||||
if (!system)
|
if (rp3dBody == nullptr)
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
|
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify Physics Systems
|
rp3dBody->applyLocalForceAtLocalPosition(relativeForce, localPos);
|
||||||
system->AddRelativeForceAtLocalPos(GetEID(), force, localPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept
|
void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept
|
||||||
{
|
{
|
||||||
if (!system)
|
if (rp3dBody == nullptr)
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
|
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify Physics Systems
|
rp3dBody->applyLocalForceAtWorldPosition(relativeForce, worldPos);
|
||||||
system->AddRelativeForceAtWorldPos(GetEID(), force, worldPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept
|
void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept
|
||||||
{
|
{
|
||||||
if (!system)
|
if (rp3dBody == nullptr)
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
|
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify Physics Systems
|
rp3dBody->applyWorldTorque(torque);
|
||||||
system->AddTorque(GetEID(), torque);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept
|
void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept
|
||||||
{
|
{
|
||||||
if (!system)
|
if (rp3dBody == nullptr)
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
|
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify Physics Systems
|
rp3dBody->applyLocalTorque(relativeTorque);
|
||||||
system->AddRelativeTorque(GetEID(), relativeTorque);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <reactphysics3d/reactphysics3d.h>
|
||||||
#include <rttr/registration>
|
#include <rttr/registration>
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
|
@ -125,9 +126,6 @@ namespace SHADE
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void OnCreate () override;
|
|
||||||
void OnDestroy () 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;
|
||||||
|
@ -155,7 +153,7 @@ namespace SHADE
|
||||||
uint16_t dirtyFlags;
|
uint16_t dirtyFlags;
|
||||||
bool interpolate;
|
bool interpolate;
|
||||||
|
|
||||||
SHPhysicsSystem* system;
|
rp3d::RigidBody* rp3dBody;
|
||||||
|
|
||||||
float mass;
|
float mass;
|
||||||
float drag;
|
float drag;
|
||||||
|
@ -167,8 +165,6 @@ namespace SHADE
|
||||||
SHVec3 torque;
|
SHVec3 torque;
|
||||||
SHVec3 angularVelocity;
|
SHVec3 angularVelocity;
|
||||||
|
|
||||||
// TODO(Diren): Once quaternions have replaced euler angles in transforms, store it for the rigidbody.
|
|
||||||
|
|
||||||
SHVec3 position;
|
SHVec3 position;
|
||||||
SHQuaternion orientation;
|
SHQuaternion orientation;
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,6 @@ namespace SHADE
|
||||||
|
|
||||||
SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept
|
SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept
|
||||||
: entityID { eid }
|
: entityID { eid }
|
||||||
, isRigidBody { false }
|
|
||||||
, hasColliders{ false }
|
|
||||||
, factory { physicsFactory }
|
, factory { physicsFactory }
|
||||||
, world { physicsWorld }
|
, world { physicsWorld }
|
||||||
, rp3dBody { nullptr }
|
, rp3dBody { nullptr }
|
||||||
|
@ -130,42 +128,6 @@ namespace SHADE
|
||||||
/* Public Function Member Definitions */
|
/* Public Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SHPhysicsObject::CreateRigidBody(const SHTransformComponent* tf, SHRigidBodyComponent* rb, SHColliderComponent* c)
|
|
||||||
{
|
|
||||||
// If collider already exists, recreate the collision body as a rigid body
|
|
||||||
if (hasColliders)
|
|
||||||
world->destroyCollisionBody(rp3dBody);
|
|
||||||
|
|
||||||
rp3dBody = world->createRigidBody(rp3d::Transform{ tf->GetWorldPosition(), tf->GetWorldRotation() });
|
|
||||||
isRigidBody = true;
|
|
||||||
|
|
||||||
rb->position = tf->GetWorldPosition();
|
|
||||||
rb->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation());
|
|
||||||
|
|
||||||
if (hasColliders)
|
|
||||||
{
|
|
||||||
c->position = tf->GetWorldPosition();
|
|
||||||
c->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation());
|
|
||||||
// Get array of colliders and add them back into the rigidbody
|
|
||||||
for (auto& collider : c->colliders | std::views::keys)
|
|
||||||
AddCollider(&collider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::CreateCollisionBody(const SHTransformComponent* tf, SHColliderComponent* c)
|
|
||||||
{
|
|
||||||
if (rp3dBody == nullptr)
|
|
||||||
rp3dBody = world->createCollisionBody(rp3d::Transform{ tf->GetWorldPosition(), tf->GetWorldRotation() });
|
|
||||||
|
|
||||||
hasColliders = true;
|
|
||||||
|
|
||||||
c->position = tf->GetWorldPosition();
|
|
||||||
c->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation());
|
|
||||||
|
|
||||||
for (auto& collider : c->colliders | std::views::keys)
|
|
||||||
AddCollider(&collider);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SHPhysicsObject::AddCollider(SHCollider* collider)
|
int SHPhysicsObject::AddCollider(SHCollider* collider)
|
||||||
{
|
{
|
||||||
switch (collider->GetType())
|
switch (collider->GetType())
|
||||||
|
@ -193,31 +155,6 @@ namespace SHADE
|
||||||
return static_cast<int>(rp3dBody->getNbColliders()) - 1;
|
return static_cast<int>(rp3dBody->getNbColliders()) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsObject::DestroyRigidBody(SHColliderComponent* c) noexcept
|
|
||||||
{
|
|
||||||
world->destroyRigidBody(reinterpret_cast<rp3d::RigidBody*>(rp3dBody));
|
|
||||||
|
|
||||||
if (hasColliders)
|
|
||||||
{
|
|
||||||
// Preserve colliders as a collision body
|
|
||||||
rp3dBody = world->createCollisionBody(rp3d::Transform{ c->position, c->orientation });
|
|
||||||
for (auto& collider : c->colliders | std::views::keys)
|
|
||||||
AddCollider(&collider);
|
|
||||||
}
|
|
||||||
|
|
||||||
isRigidBody = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::DestroyCollisionBody() noexcept
|
|
||||||
{
|
|
||||||
// Remove all colliders
|
|
||||||
for (uint32_t i = 0; i < rp3dBody->getNbColliders(); ++i)
|
|
||||||
{
|
|
||||||
auto* collider = rp3dBody->getCollider(i);
|
|
||||||
rp3dBody->removeCollider(collider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::RemoveCollider(int index)
|
void SHPhysicsObject::RemoveCollider(int index)
|
||||||
{
|
{
|
||||||
const int NUM_COLLIDERS = static_cast<int>(rp3dBody->getNbColliders());
|
const int NUM_COLLIDERS = static_cast<int>(rp3dBody->getNbColliders());
|
||||||
|
|
|
@ -69,13 +69,8 @@ namespace SHADE
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void CreateRigidBody (const SHTransformComponent* tf, SHRigidBodyComponent* rb, SHColliderComponent* c);
|
|
||||||
void CreateCollisionBody (const SHTransformComponent* tf, SHColliderComponent* c);
|
|
||||||
int AddCollider (SHCollider* collider);
|
int AddCollider (SHCollider* collider);
|
||||||
|
|
||||||
void DestroyRigidBody (SHColliderComponent* c) noexcept;
|
|
||||||
void RemoveCollider (int index);
|
void RemoveCollider (int index);
|
||||||
void DestroyCollisionBody () noexcept;
|
|
||||||
|
|
||||||
void SyncRigidBody (SHRigidBodyComponent* rb) const noexcept;
|
void SyncRigidBody (SHRigidBodyComponent* rb) const noexcept;
|
||||||
void SyncColliders (SHColliderComponent* c) const noexcept;
|
void SyncColliders (SHColliderComponent* c) const noexcept;
|
||||||
|
@ -86,8 +81,6 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
EntityID entityID;
|
EntityID entityID;
|
||||||
bool isRigidBody;
|
|
||||||
bool hasColliders;
|
|
||||||
|
|
||||||
rp3d::PhysicsCommon* factory;
|
rp3d::PhysicsCommon* factory;
|
||||||
rp3d::PhysicsWorld* world;
|
rp3d::PhysicsWorld* world;
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||||
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
#include "Editor/SHEditor.hpp"
|
||||||
#include "Math/SHMathHelpers.h"
|
#include "Math/SHMathHelpers.h"
|
||||||
#include "Scene/SHSceneManager.h"
|
#include "Scene/SHSceneManager.h"
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
|
@ -175,11 +177,9 @@ namespace SHADE
|
||||||
|
|
||||||
void SHPhysicsSystem::Init()
|
void SHPhysicsSystem::Init()
|
||||||
{
|
{
|
||||||
using namespace rp3d;
|
|
||||||
|
|
||||||
// Create a physics world with the default settings
|
// Create a physics world with the default settings
|
||||||
PhysicsWorld::WorldSettings settings;
|
rp3d::PhysicsWorld::WorldSettings settings;
|
||||||
settings.gravity = Vector3{ 0.0f, -9.81f, 0.0f };
|
settings.gravity = SHVec3{ 0.0f, -9.81f, 0.0f };
|
||||||
settings.isSleepingEnabled = true;
|
settings.isSleepingEnabled = true;
|
||||||
settings.defaultVelocitySolverNbIterations = 8;
|
settings.defaultVelocitySolverNbIterations = 8;
|
||||||
settings.defaultPositionSolverNbIterations = 3;
|
settings.defaultPositionSolverNbIterations = 3;
|
||||||
|
@ -190,6 +190,16 @@ namespace SHADE
|
||||||
|
|
||||||
// Set up solvers
|
// Set up solvers
|
||||||
world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::Exit()
|
void SHPhysicsSystem::Exit()
|
||||||
|
@ -197,99 +207,6 @@ namespace SHADE
|
||||||
factory.destroyPhysicsWorld(world);
|
factory.destroyPhysicsWorld(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::AddRigidBody(EntityID entityID) noexcept
|
|
||||||
{
|
|
||||||
//#ifdef _DEBUG
|
|
||||||
// SHLOG_INFO("Adding a Rigidbody to the Physics World.")
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
auto* physicsObject = CreatePhysicsObject(entityID);
|
|
||||||
|
|
||||||
physicsObject->CreateRigidBody
|
|
||||||
(
|
|
||||||
EnsureTransform(entityID),
|
|
||||||
SHComponentManager::GetComponent<SHRigidBodyComponent>(entityID),
|
|
||||||
SHComponentManager::GetComponent_s<SHColliderComponent>(entityID)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::AddCollider(EntityID entityID) noexcept
|
|
||||||
{
|
|
||||||
//#ifdef _DEBUG
|
|
||||||
// SHLOG_INFO("Adding a Collider to the Physics World.")
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
auto* physicsObject = CreatePhysicsObject(entityID);
|
|
||||||
|
|
||||||
physicsObject->CreateCollisionBody
|
|
||||||
(
|
|
||||||
EnsureTransform(entityID),
|
|
||||||
SHComponentManager::GetComponent<SHColliderComponent>(entityID)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::RemoveRigidBody(EntityID entityID) noexcept
|
|
||||||
{
|
|
||||||
#ifdef _DEBUG
|
|
||||||
SHLOG_INFO("Removing a Rigidbody from the Physics World.")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto* physicsObject = GetPhysicsObject(entityID);
|
|
||||||
SHASSERT(physicsObject != nullptr, "Physics object has been lost from the world!")
|
|
||||||
|
|
||||||
physicsObject->DestroyRigidBody(SHComponentManager::GetComponent_s<SHColliderComponent>(entityID));
|
|
||||||
|
|
||||||
if (physicsObject->rp3dBody == nullptr)
|
|
||||||
DestroyPhysicsObject(entityID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::RemoveCollider(EntityID entityID) noexcept
|
|
||||||
{
|
|
||||||
#ifdef _DEBUG
|
|
||||||
SHLOG_INFO("Removing a Collider from the Physics World.")
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::AddForce(EntityID entityID, const SHVec3& force) const noexcept
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::AddForceAtLocalPos(EntityID entityID, const SHVec3& force, const SHVec3& localPos) const noexcept
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::AddForceAtWorldPos(EntityID entityID, const SHVec3& force, const SHVec3& worldPos) const noexcept
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::AddRelativeForce(EntityID entityID, const SHVec3& relativeForce) const noexcept
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::AddRelativeForceAtLocalPos(EntityID entityID, const SHVec3& relativeForce, const SHVec3& localPos) const noexcept
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::AddRelativeForceAtWorldPos(EntityID entityID, const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::AddTorque(EntityID entityID, const SHVec3& torque) const noexcept
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::AddRelativeTorque(EntityID entityID, const SHVec3& relativeTorque) const noexcept
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHCollider* collider)
|
void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHCollider* collider)
|
||||||
{
|
{
|
||||||
auto* physicsObject = GetPhysicsObject(entityID);
|
auto* physicsObject = GetPhysicsObject(entityID);
|
||||||
|
@ -298,27 +215,63 @@ namespace SHADE
|
||||||
|
|
||||||
void SHPhysicsSystem::RemoveCollisionShape(EntityID entityID, int index)
|
void SHPhysicsSystem::RemoveCollisionShape(EntityID entityID, int index)
|
||||||
{
|
{
|
||||||
|
auto* physicsObject = GetPhysicsObject(entityID);
|
||||||
|
physicsObject->RemoveCollider(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept
|
void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept
|
||||||
{
|
{
|
||||||
auto* system = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
auto* system = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||||
|
|
||||||
|
// Sync transforms
|
||||||
|
for (auto& [entityID, physicsObject] : system->map)
|
||||||
|
{
|
||||||
|
// Ensure a valid physics Object
|
||||||
|
if (physicsObject.rp3dBody == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
||||||
|
|
||||||
|
// Clear all forces and velocities if editor is not in play
|
||||||
|
if (SHSystemManager::GetSystem<SHEditor>()->editorState == SHEditor::State::STOP)
|
||||||
|
{
|
||||||
|
if (rigidBodyComponent)
|
||||||
|
{
|
||||||
|
auto* rp3dRigidBody = reinterpret_cast<rp3d::RigidBody*>(physicsObject.rp3dBody);
|
||||||
|
rp3dRigidBody->resetForce();
|
||||||
|
rp3dRigidBody->resetTorque();
|
||||||
|
rp3dRigidBody->setLinearVelocity(SHVec3::Zero);
|
||||||
|
rp3dRigidBody->setAngularVelocity(SHVec3::Zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
||||||
|
if (transformComponent && transformComponent->HasChanged())
|
||||||
|
{
|
||||||
|
const auto WORLD_POS = transformComponent->GetWorldPosition();
|
||||||
|
const auto WORLD_ROT = transformComponent->GetWorldOrientation();
|
||||||
|
|
||||||
|
physicsObject.SetPosition(WORLD_POS);
|
||||||
|
physicsObject.SetOrientation(WORLD_ROT);
|
||||||
|
|
||||||
|
if (rigidBodyComponent)
|
||||||
|
{
|
||||||
|
rigidBodyComponent->position = WORLD_POS;
|
||||||
|
rigidBodyComponent->orientation = WORLD_ROT;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
|
||||||
|
if (colliderComponent)
|
||||||
|
{
|
||||||
|
colliderComponent->position = WORLD_POS;
|
||||||
|
colliderComponent->orientation = WORLD_ROT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update bodies and colliders if component is dirty
|
// Update bodies and colliders if component is dirty
|
||||||
system->SyncRigidBodyComponents(SHComponentManager::GetDense<SHRigidBodyComponent>());
|
system->SyncRigidBodyComponents(SHComponentManager::GetDense<SHRigidBodyComponent>());
|
||||||
system->SyncColliderComponents(SHComponentManager::GetDense<SHColliderComponent>());
|
system->SyncColliderComponents(SHComponentManager::GetDense<SHColliderComponent>());
|
||||||
|
|
||||||
// Sync transforms
|
|
||||||
for (auto& physicsObject : system->map | std::views::values)
|
|
||||||
{
|
|
||||||
const auto* TF = SHComponentManager::GetComponent<SHTransformComponent>(physicsObject.entityID);
|
|
||||||
if (TF->HasChanged())
|
|
||||||
{
|
|
||||||
physicsObject.SetPosition(TF->GetWorldPosition());
|
|
||||||
physicsObject.SetOrientation(TF->GetWorldOrientation());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept
|
void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept
|
||||||
|
@ -359,7 +312,7 @@ namespace SHADE
|
||||||
/* Private Function Member Definitions */
|
/* Private Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHPhysicsObject* SHPhysicsSystem::CreatePhysicsObject(EntityID entityID) noexcept
|
SHPhysicsObject* SHPhysicsSystem::EnsurePhysicsObject(EntityID entityID) noexcept
|
||||||
{
|
{
|
||||||
const auto it = map.find(entityID);
|
const auto it = map.find(entityID);
|
||||||
if (it == map.end())
|
if (it == map.end())
|
||||||
|
@ -451,15 +404,18 @@ namespace SHADE
|
||||||
|
|
||||||
const rp3d::Transform CURRENT_TF = physicsObject.rp3dBody->getTransform();
|
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
|
// Check if transform should be interpolated
|
||||||
|
|
||||||
if (physicsObject.isRigidBody)
|
if (rigidBodyComponent != nullptr)
|
||||||
{
|
{
|
||||||
auto* rbComponent = SHComponentManager::GetComponent<SHRigidBodyComponent>(entityID);
|
|
||||||
if (rbComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
|
if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (rbComponent->IsInterpolating())
|
if (rigidBodyComponent->IsInterpolating())
|
||||||
{
|
{
|
||||||
const rp3d::Transform PREV_TF = physicsObject.prevTransform;
|
const rp3d::Transform PREV_TF = physicsObject.prevTransform;
|
||||||
const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast<rp3d::decimal>(interpolationFactor));
|
const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast<rp3d::decimal>(interpolationFactor));
|
||||||
|
@ -474,12 +430,12 @@ namespace SHADE
|
||||||
rp3dRot = CURRENT_TF.getOrientation();
|
rp3dRot = CURRENT_TF.getOrientation();
|
||||||
}
|
}
|
||||||
|
|
||||||
rbComponent->position = CURRENT_TF.getPosition();
|
rigidBodyComponent->position = CURRENT_TF.getPosition();
|
||||||
rbComponent->orientation = CURRENT_TF.getOrientation();
|
rigidBodyComponent->orientation = CURRENT_TF.getOrientation();
|
||||||
|
|
||||||
if (physicsObject.hasColliders)
|
if (colliderComponent != nullptr)
|
||||||
{
|
{
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
|
|
||||||
colliderComponent->position = CURRENT_TF.getPosition();
|
colliderComponent->position = CURRENT_TF.getPosition();
|
||||||
colliderComponent->orientation = CURRENT_TF.getOrientation();
|
colliderComponent->orientation = CURRENT_TF.getOrientation();
|
||||||
}
|
}
|
||||||
|
@ -491,28 +447,146 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert RP3D Transform to SHADE
|
// Convert RP3D Transform to SHADE
|
||||||
auto* tfComponent = SHComponentManager::GetComponent<SHTransformComponent>(entityID);
|
auto* transformComponent = SHComponentManager::GetComponent<SHTransformComponent>(entityID);
|
||||||
tfComponent->SetWorldPosition(rp3dPos);
|
transformComponent->SetWorldPosition(rp3dPos);
|
||||||
tfComponent->SetWorldOrientation(SHQuaternion{ rp3dRot });
|
transformComponent->SetWorldOrientation(rp3dRot);
|
||||||
|
|
||||||
// Cache transforms
|
// Cache transforms
|
||||||
physicsObject.prevTransform = CURRENT_TF;
|
physicsObject.prevTransform = CURRENT_TF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SHTransformComponent* SHPhysicsSystem::EnsureTransform(EntityID entityID)
|
SHEventHandle SHPhysicsSystem::AddPhysicsComponent(SHEventPtr addComponentEvent)
|
||||||
{
|
{
|
||||||
auto* tf = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentAddedEvent>*>(addComponentEvent.get());
|
||||||
|
|
||||||
// Possibly redundant
|
static const auto RIGID_BODY_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
||||||
if (!tf)
|
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)
|
||||||
{
|
{
|
||||||
SHComponentManager::AddComponent<SHTransformComponent>(entityID);
|
const EntityID ENTITY_ID = EVENT_DATA->data->eid;
|
||||||
tf = SHComponentManager::GetComponent<SHTransformComponent>(entityID);
|
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->colliders | std::views::keys)
|
||||||
|
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();
|
||||||
|
|
||||||
|
if (physicsObject->rp3dBody == nullptr)
|
||||||
|
{
|
||||||
|
physicsObject->rp3dBody = world->createCollisionBody
|
||||||
|
(
|
||||||
|
rp3d::Transform{ colliderComponent->position, colliderComponent->orientation }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add Collision Shapes
|
||||||
|
for (auto& collider : colliderComponent->colliders | std::views::keys)
|
||||||
|
physicsObject->AddCollider(&collider);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tf;
|
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);
|
||||||
|
|
||||||
|
SHASSERT(physicsObject != nullptr, "Physics object has been lost from the world!")
|
||||||
|
|
||||||
|
if (REMOVED_ID == RIGID_BODY_ID)
|
||||||
|
{
|
||||||
|
world->destroyRigidBody(reinterpret_cast<rp3d::RigidBody*>(physicsObject->rp3dBody));
|
||||||
|
physicsObject->rp3dBody = nullptr;
|
||||||
|
|
||||||
|
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(ENTITY_ID);
|
||||||
|
if (colliderComponent != nullptr)
|
||||||
|
{
|
||||||
|
// Preserve colliders as a collision body
|
||||||
|
physicsObject->rp3dBody = world->createCollisionBody
|
||||||
|
(
|
||||||
|
rp3d::Transform{ colliderComponent->position, colliderComponent->orientation }
|
||||||
|
);
|
||||||
|
|
||||||
|
for (auto& collider : colliderComponent->colliders | std::views::keys)
|
||||||
|
physicsObject->AddCollider(&collider);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 == COLLIDER_ID)
|
||||||
|
{
|
||||||
|
// Remove all colliders
|
||||||
|
for (uint32_t i = 0; i < physicsObject->rp3dBody->getNbColliders(); ++i)
|
||||||
|
{
|
||||||
|
auto* collider = physicsObject->rp3dBody->getCollider(i);
|
||||||
|
physicsObject->rp3dBody->removeCollider(collider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (physicsObject->rp3dBody == nullptr)
|
||||||
|
DestroyPhysicsObject(ENTITY_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EVENT_DATA->handle;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -16,14 +16,14 @@
|
||||||
#include <reactphysics3d/reactphysics3d.h>
|
#include <reactphysics3d/reactphysics3d.h>
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "SHPhysicsObject.h"
|
|
||||||
#include "Components/SHRigidBodyComponent.h"
|
#include "Components/SHRigidBodyComponent.h"
|
||||||
#include "Components/SHColliderComponent.h"
|
#include "Components/SHColliderComponent.h"
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
|
||||||
|
|
||||||
#include "Scene/SHSceneGraph.h"
|
|
||||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
#include "ECS_Base/System/SHFixedSystemRoutine.h"
|
#include "ECS_Base/System/SHFixedSystemRoutine.h"
|
||||||
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
|
#include "Scene/SHSceneGraph.h"
|
||||||
|
#include "SHPhysicsObject.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -32,7 +32,7 @@ namespace SHADE
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class SH_API SHPhysicsSystem : public SHSystem
|
class SH_API SHPhysicsSystem final : public SHSystem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -85,21 +85,10 @@ namespace SHADE
|
||||||
void Init () override;
|
void Init () override;
|
||||||
void Exit () override;
|
void Exit () override;
|
||||||
|
|
||||||
void AddRigidBody (EntityID entityID) noexcept;
|
//void AddRigidBody (EntityID entityID) noexcept;
|
||||||
void AddCollider (EntityID entityID) noexcept;
|
//void AddCollider (EntityID entityID) noexcept;
|
||||||
void RemoveRigidBody (EntityID entityID) noexcept;
|
//void RemoveRigidBody (EntityID entityID) noexcept;
|
||||||
void RemoveCollider (EntityID entityID) noexcept;
|
//void RemoveCollider (EntityID entityID) noexcept;
|
||||||
|
|
||||||
void AddForce (EntityID entityID, const SHVec3& force) const noexcept;
|
|
||||||
void AddForceAtLocalPos (EntityID entityID, const SHVec3& force, const SHVec3& localPos) const noexcept;
|
|
||||||
void AddForceAtWorldPos (EntityID entityID, const SHVec3& force, const SHVec3& worldPos) const noexcept;
|
|
||||||
|
|
||||||
void AddRelativeForce (EntityID entityID, const SHVec3& relativeForce) const noexcept;
|
|
||||||
void AddRelativeForceAtLocalPos (EntityID entityID, const SHVec3& relativeForce, const SHVec3& localPos) const noexcept;
|
|
||||||
void AddRelativeForceAtWorldPos (EntityID entityID, const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept;
|
|
||||||
|
|
||||||
void AddTorque (EntityID entityID, const SHVec3& torque) const noexcept;
|
|
||||||
void AddRelativeTorque (EntityID entityID, const SHVec3& relativeTorque) const noexcept;
|
|
||||||
|
|
||||||
void AddCollisionShape (EntityID entityID, SHCollider* collider);
|
void AddCollisionShape (EntityID entityID, SHCollider* collider);
|
||||||
void RemoveCollisionShape (EntityID entityID, int index);
|
void RemoveCollisionShape (EntityID entityID, int index);
|
||||||
|
@ -108,10 +97,7 @@ namespace SHADE
|
||||||
/* System Routines */
|
/* System Routines */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
class SH_API PhysicsPreUpdate final : public SHSystemRoutine
|
||||||
* @brief Synchronises RP3D with SHADE
|
|
||||||
*/
|
|
||||||
class SH_API PhysicsPreUpdate : public SHSystemRoutine
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
@ -127,7 +113,7 @@ namespace SHADE
|
||||||
void Execute(double dt) noexcept override;
|
void Execute(double dt) noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SH_API PhysicsFixedUpdate : public SHFixedSystemRoutine
|
class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
@ -143,7 +129,7 @@ namespace SHADE
|
||||||
void Execute (double dt) noexcept override;
|
void Execute (double dt) noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SH_API PhysicsPostUpdate : public SHSystemRoutine
|
class SH_API PhysicsPostUpdate final : public SHSystemRoutine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
@ -170,15 +156,14 @@ namespace SHADE
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
// TODO(Diren): Store interpFactor
|
|
||||||
|
|
||||||
bool worldUpdated;
|
bool worldUpdated;
|
||||||
|
|
||||||
double interpolationFactor;
|
double interpolationFactor;
|
||||||
double fixedDT;
|
double fixedDT;
|
||||||
rp3d::PhysicsWorld* world;
|
|
||||||
|
|
||||||
|
rp3d::PhysicsWorld* world;
|
||||||
rp3d::PhysicsCommon factory;
|
rp3d::PhysicsCommon factory;
|
||||||
|
|
||||||
EntityObjectMap map;
|
EntityObjectMap map;
|
||||||
|
|
||||||
|
|
||||||
|
@ -186,7 +171,7 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
SHPhysicsObject* CreatePhysicsObject (EntityID entityID) noexcept;
|
SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept;
|
||||||
SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
|
SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
|
||||||
void DestroyPhysicsObject (EntityID entityID) noexcept;
|
void DestroyPhysicsObject (EntityID entityID) noexcept;
|
||||||
|
|
||||||
|
@ -194,10 +179,9 @@ namespace SHADE
|
||||||
void SyncRigidBodyComponents (std::vector<SHRigidBodyComponent>& denseArray) noexcept;
|
void SyncRigidBodyComponents (std::vector<SHRigidBodyComponent>& denseArray) noexcept;
|
||||||
void SyncColliderComponents (std::vector<SHColliderComponent>& denseArray) noexcept;
|
void SyncColliderComponents (std::vector<SHColliderComponent>& denseArray) noexcept;
|
||||||
void SyncTransforms () noexcept;
|
void SyncTransforms () noexcept;
|
||||||
// TODO(Diren): Trigger handling
|
|
||||||
|
|
||||||
// TODO(Diren): Remove when responsibility shifted to editor
|
SHEventHandle AddPhysicsComponent (SHEventPtr addComponentEvent);
|
||||||
SHTransformComponent* EnsureTransform (EntityID entityID);
|
SHEventHandle RemovePhysicsComponent (SHEventPtr removeComponentEvent);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue