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;
|
||||
}
|
||||
|
||||
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()
|
||||
:SHEditorWindow("Inspector", ImGuiWindowFlags_MenuBar)
|
||||
{
|
||||
|
@ -90,15 +107,13 @@ namespace SHADE
|
|||
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
|
||||
{
|
||||
DrawAddComponentButton<SHTransformComponent>(eid);
|
||||
DrawAddComponentButton<SHRenderable>(eid);
|
||||
DrawAddComponentButton<SHColliderComponent>(eid);
|
||||
if(DrawAddComponentButton<SHRigidBodyComponent>(eid))
|
||||
{
|
||||
if(SHComponentManager::GetComponent_s<SHTransformComponent>(eid) == nullptr)
|
||||
{
|
||||
SHComponentManager::AddComponent<SHTransformComponent>(eid);
|
||||
}
|
||||
}
|
||||
|
||||
// Components that require Transforms
|
||||
|
||||
DrawAddComponentWithEnforcedComponentButton<SHRenderable, SHTransformComponent>(eid);
|
||||
DrawAddComponentWithEnforcedComponentButton<SHRigidBodyComponent, SHTransformComponent>(eid);
|
||||
DrawAddComponentWithEnforcedComponentButton<SHColliderComponent, SHTransformComponent>(eid);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHEvent.h"
|
||||
#include "SHEventReceiver.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
/******************************************************************************
|
||||
INSTRUCTIONS FOR USE:
|
||||
|
@ -67,7 +68,7 @@ namespace SHADE
|
|||
using EventManagerListener = std::function<void(SHEvent)>;
|
||||
|
||||
|
||||
class SHEventManager
|
||||
class SH_API SHEventManager
|
||||
{
|
||||
private:
|
||||
|
||||
|
|
|
@ -61,9 +61,9 @@ namespace SHADE
|
|||
|
||||
void SHTransformSystem::Init()
|
||||
{
|
||||
std::shared_ptr thisReceiver { std::make_shared<SHEventReceiverSpec<SHTransformSystem>>(this, &SHTransformSystem::ChangeParent) };
|
||||
ReceiverPtr receiver = std::dynamic_pointer_cast<SHEventReceiver>(thisReceiver);
|
||||
SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, receiver);
|
||||
const std::shared_ptr CHANGE_PARENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHTransformSystem>>(this, &SHTransformSystem::ChangeParent) };
|
||||
const ReceiverPtr CHANGE_PARENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(CHANGE_PARENT_RECEIVER);
|
||||
SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, CHANGE_PARENT_RECEIVER_PTR);
|
||||
}
|
||||
|
||||
void SHTransformSystem::Exit()
|
||||
|
@ -75,50 +75,6 @@ namespace SHADE
|
|||
/* 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)
|
||||
{
|
||||
// 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();
|
||||
}
|
||||
|
||||
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
|
|
@ -11,9 +11,9 @@
|
|||
#pragma once
|
||||
|
||||
// Project Headers
|
||||
#include "SHTransformComponent.h"
|
||||
#include "Scene/SHSceneGraph.h"
|
||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||
#include "Scene/SHSceneGraph.h"
|
||||
#include "SHTransformComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -53,17 +53,6 @@ namespace SHADE
|
|||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
TransformPostLogicUpdate ();
|
||||
~TransformPostLogicUpdate () = default;
|
||||
|
||||
TransformPostLogicUpdate (const TransformPostLogicUpdate&) = delete;
|
||||
TransformPostLogicUpdate (TransformPostLogicUpdate&&) = delete;
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
TransformPostLogicUpdate& operator= (const TransformPostLogicUpdate&) = delete;
|
||||
TransformPostLogicUpdate& operator= (TransformPostLogicUpdate&&) = delete;
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
|
@ -80,17 +69,6 @@ namespace SHADE
|
|||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
TransformPostPhysicsUpdate ();
|
||||
~TransformPostPhysicsUpdate () = default;
|
||||
|
||||
TransformPostPhysicsUpdate (const TransformPostPhysicsUpdate&) = delete;
|
||||
TransformPostPhysicsUpdate (TransformPostPhysicsUpdate&&) = delete;
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
TransformPostPhysicsUpdate& operator= (const TransformPostPhysicsUpdate&) = delete;
|
||||
TransformPostPhysicsUpdate& operator= (TransformPostPhysicsUpdate&&) = delete;
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
|
@ -111,11 +89,14 @@ namespace SHADE
|
|||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHEventHandle ChangeParent (SHEventPtr changeParentEvent);
|
||||
static void UpdateChildrenLocalTransforms (SHSceneNode* node);
|
||||
|
||||
static void UpdateEntity (const SHSceneNode* node, bool clearDirtyFlag);
|
||||
static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr);
|
||||
|
||||
// Event Handlers
|
||||
|
||||
SHEventHandle ChangeParent (SHEventPtr changeParentEvent);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ namespace SHADE
|
|||
|
||||
SHColliderComponent::SHColliderComponent() noexcept
|
||||
: system { nullptr }
|
||||
, colliders {}
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -69,31 +68,24 @@ namespace SHADE
|
|||
void SHColliderComponent::OnCreate()
|
||||
{
|
||||
system = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (!system)
|
||||
{
|
||||
SHLOG_ERROR("Physics system does not exist, Collider Component not added!")
|
||||
return;
|
||||
}
|
||||
|
||||
system->AddCollider(GetEID());
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
|
||||
const auto* tf = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
||||
|
@ -101,12 +93,6 @@ namespace SHADE
|
|||
collider.SetPositionOffset(posOffset);
|
||||
collider.SetAsBoundingBox(tf->GetWorldScale() * halfExtents);
|
||||
|
||||
if (!system)
|
||||
{
|
||||
SHLOG_ERROR("Physics system does not exist, unable to add Box Collider!")
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Notify Physics System
|
||||
system->AddCollisionShape(GetEID(), &collider);
|
||||
|
||||
|
@ -115,7 +101,13 @@ namespace SHADE
|
|||
|
||||
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& collider = colliders.emplace_back(spherePair).first;
|
||||
|
@ -126,13 +118,7 @@ namespace SHADE
|
|||
|
||||
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 });
|
||||
collider.SetAsBoundingSphere(MAX_SCALE * 0.5f);
|
||||
|
||||
if (!system)
|
||||
{
|
||||
SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!")
|
||||
return nullptr;
|
||||
}
|
||||
collider.SetAsBoundingSphere(MAX_SCALE * 0.5f * radius);
|
||||
|
||||
// Notify Physics System
|
||||
system->AddCollisionShape(GetEID(), &collider);
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
using ColliderDirtyPair = std::pair<SHCollider, bool>;
|
||||
using Colliders = std::vector<ColliderDirtyPair>;
|
||||
using Colliders = std::vector<ColliderDirtyPair>;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -81,10 +81,10 @@ namespace SHADE
|
|||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void OnCreate () override;
|
||||
void OnDestroy () override;
|
||||
void OnCreate () 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;
|
||||
SHBoundingSphere* AddBoundingSphere (float radius = 1.0f, const SHVec3& posOffset = SHVec3::Zero) noexcept;
|
||||
|
|
|
@ -28,11 +28,10 @@ namespace SHADE
|
|||
, flags { 0 }
|
||||
, dirtyFlags { 0 }
|
||||
, interpolate { true }
|
||||
, system { nullptr }
|
||||
, rp3dBody { nullptr }
|
||||
, mass { 1.0f }
|
||||
, drag { 0.01f }
|
||||
, angularDrag { 0.01f }
|
||||
|
||||
{
|
||||
// Set default flags: Gravity & Sleeping enabled
|
||||
flags |= 1U << 0;
|
||||
|
@ -161,7 +160,13 @@ namespace SHADE
|
|||
|
||||
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;
|
||||
enableGravity ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||
|
@ -169,7 +174,13 @@ namespace SHADE
|
|||
|
||||
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;
|
||||
isAllowedToSleep ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||
|
@ -177,7 +188,13 @@ namespace SHADE
|
|||
|
||||
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;
|
||||
freezePositionX ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||
|
@ -185,7 +202,13 @@ namespace SHADE
|
|||
|
||||
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;
|
||||
freezePositionY ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||
|
@ -193,7 +216,13 @@ namespace SHADE
|
|||
|
||||
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;
|
||||
freezePositionZ ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||
|
@ -201,7 +230,13 @@ namespace SHADE
|
|||
|
||||
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;
|
||||
freezeRotationX ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||
|
@ -209,7 +244,13 @@ namespace SHADE
|
|||
|
||||
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;
|
||||
freezeRotationY ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||
|
@ -217,7 +258,13 @@ namespace SHADE
|
|||
|
||||
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;
|
||||
freezeRotationZ ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
|
||||
|
@ -230,30 +277,60 @@ namespace SHADE
|
|||
|
||||
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;
|
||||
mass = newMass;
|
||||
}
|
||||
|
||||
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;
|
||||
drag = newDrag;
|
||||
}
|
||||
|
||||
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;
|
||||
angularDrag = newAngularDrag;
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
|
||||
{
|
||||
if (type == Type::STATIC)
|
||||
{
|
||||
SHLOG_WARNING("Cannot set linear velocity of a static object {}", GetEID())
|
||||
return;
|
||||
}
|
||||
|
||||
dirtyFlags |= 1U << 8;
|
||||
linearVelocity = newLinearVelocity;
|
||||
}
|
||||
|
||||
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;
|
||||
angularVelocity = newAngularVelocity;
|
||||
}
|
||||
|
@ -262,125 +339,92 @@ namespace SHADE
|
|||
/* 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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// Notify Physics Systems
|
||||
system->AddForce(GetEID(), force);
|
||||
rp3dBody->applyWorldForceAtCenterOfMass(force);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Notify Physics Systems
|
||||
system->AddForceAtLocalPos(GetEID(), force, localPos);
|
||||
rp3dBody->applyWorldForceAtLocalPosition(force, localPos);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Notify Physics Systems
|
||||
system->AddForceAtWorldPos(GetEID(), force, worldPos);
|
||||
rp3dBody->applyWorldForceAtWorldPosition(force, worldPos);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Notify Physics Systems
|
||||
system->AddRelativeForce(GetEID(), force);
|
||||
rp3dBody->applyLocalForceAtCenterOfMass(relativeForce);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Notify Physics Systems
|
||||
system->AddRelativeForceAtLocalPos(GetEID(), force, localPos);
|
||||
rp3dBody->applyLocalForceAtLocalPosition(relativeForce, localPos);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Notify Physics Systems
|
||||
system->AddRelativeForceAtWorldPos(GetEID(), force, worldPos);
|
||||
rp3dBody->applyLocalForceAtWorldPosition(relativeForce, worldPos);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Notify Physics Systems
|
||||
system->AddTorque(GetEID(), torque);
|
||||
rp3dBody->applyWorldTorque(torque);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Notify Physics Systems
|
||||
system->AddRelativeTorque(GetEID(), relativeTorque);
|
||||
rp3dBody->applyLocalTorque(relativeTorque);
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <reactphysics3d/reactphysics3d.h>
|
||||
#include <rttr/registration>
|
||||
|
||||
// Project Headers
|
||||
|
@ -125,9 +126,6 @@ namespace SHADE
|
|||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void OnCreate () override;
|
||||
void OnDestroy () override;
|
||||
|
||||
void AddForce (const SHVec3& force) const noexcept;
|
||||
void AddForceAtLocalPos (const SHVec3& force, const SHVec3& localPos) const noexcept;
|
||||
void AddForceAtWorldPos (const SHVec3& force, const SHVec3& worldPos) const noexcept;
|
||||
|
@ -155,7 +153,7 @@ namespace SHADE
|
|||
uint16_t dirtyFlags;
|
||||
bool interpolate;
|
||||
|
||||
SHPhysicsSystem* system;
|
||||
rp3d::RigidBody* rp3dBody;
|
||||
|
||||
float mass;
|
||||
float drag;
|
||||
|
@ -167,8 +165,6 @@ namespace SHADE
|
|||
SHVec3 torque;
|
||||
SHVec3 angularVelocity;
|
||||
|
||||
// TODO(Diren): Once quaternions have replaced euler angles in transforms, store it for the rigidbody.
|
||||
|
||||
SHVec3 position;
|
||||
SHQuaternion orientation;
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@ namespace SHADE
|
|||
|
||||
SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept
|
||||
: entityID { eid }
|
||||
, isRigidBody { false }
|
||||
, hasColliders{ false }
|
||||
, factory { physicsFactory }
|
||||
, world { physicsWorld }
|
||||
, rp3dBody { nullptr }
|
||||
|
@ -130,42 +128,6 @@ namespace SHADE
|
|||
/* 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)
|
||||
{
|
||||
switch (collider->GetType())
|
||||
|
@ -193,31 +155,6 @@ namespace SHADE
|
|||
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)
|
||||
{
|
||||
const int NUM_COLLIDERS = static_cast<int>(rp3dBody->getNbColliders());
|
||||
|
|
|
@ -69,13 +69,8 @@ namespace SHADE
|
|||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void CreateRigidBody (const SHTransformComponent* tf, SHRigidBodyComponent* rb, SHColliderComponent* c);
|
||||
void CreateCollisionBody (const SHTransformComponent* tf, SHColliderComponent* c);
|
||||
int AddCollider (SHCollider* collider);
|
||||
|
||||
void DestroyRigidBody (SHColliderComponent* c) noexcept;
|
||||
void RemoveCollider (int index);
|
||||
void DestroyCollisionBody () noexcept;
|
||||
|
||||
void SyncRigidBody (SHRigidBodyComponent* rb) const noexcept;
|
||||
void SyncColliders (SHColliderComponent* c) const noexcept;
|
||||
|
@ -86,8 +81,6 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
EntityID entityID;
|
||||
bool isRigidBody;
|
||||
bool hasColliders;
|
||||
|
||||
rp3d::PhysicsCommon* factory;
|
||||
rp3d::PhysicsWorld* world;
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Editor/SHEditor.hpp"
|
||||
#include "Math/SHMathHelpers.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
|
@ -175,11 +177,9 @@ namespace SHADE
|
|||
|
||||
void SHPhysicsSystem::Init()
|
||||
{
|
||||
using namespace rp3d;
|
||||
|
||||
// Create a physics world with the default settings
|
||||
PhysicsWorld::WorldSettings settings;
|
||||
settings.gravity = Vector3{ 0.0f, -9.81f, 0.0f };
|
||||
rp3d::PhysicsWorld::WorldSettings settings;
|
||||
settings.gravity = SHVec3{ 0.0f, -9.81f, 0.0f };
|
||||
settings.isSleepingEnabled = true;
|
||||
settings.defaultVelocitySolverNbIterations = 8;
|
||||
settings.defaultPositionSolverNbIterations = 3;
|
||||
|
@ -190,6 +190,16 @@ namespace SHADE
|
|||
|
||||
// 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);
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::Exit()
|
||||
|
@ -197,99 +207,6 @@ namespace SHADE
|
|||
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)
|
||||
{
|
||||
auto* physicsObject = GetPhysicsObject(entityID);
|
||||
|
@ -298,27 +215,63 @@ namespace SHADE
|
|||
|
||||
void SHPhysicsSystem::RemoveCollisionShape(EntityID entityID, int index)
|
||||
{
|
||||
|
||||
auto* physicsObject = GetPhysicsObject(entityID);
|
||||
physicsObject->RemoveCollider(index);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
system->SyncRigidBodyComponents(SHComponentManager::GetDense<SHRigidBodyComponent>());
|
||||
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
|
||||
|
@ -359,7 +312,7 @@ namespace SHADE
|
|||
/* Private Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObject* SHPhysicsSystem::CreatePhysicsObject(EntityID entityID) noexcept
|
||||
SHPhysicsObject* SHPhysicsSystem::EnsurePhysicsObject(EntityID entityID) noexcept
|
||||
{
|
||||
const auto it = map.find(entityID);
|
||||
if (it == map.end())
|
||||
|
@ -451,15 +404,18 @@ namespace SHADE
|
|||
|
||||
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 (physicsObject.isRigidBody)
|
||||
if (rigidBodyComponent != nullptr)
|
||||
{
|
||||
auto* rbComponent = SHComponentManager::GetComponent<SHRigidBodyComponent>(entityID);
|
||||
if (rbComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
|
||||
|
||||
if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
|
||||
continue;
|
||||
|
||||
if (rbComponent->IsInterpolating())
|
||||
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));
|
||||
|
@ -474,12 +430,12 @@ namespace SHADE
|
|||
rp3dRot = CURRENT_TF.getOrientation();
|
||||
}
|
||||
|
||||
rbComponent->position = CURRENT_TF.getPosition();
|
||||
rbComponent->orientation = CURRENT_TF.getOrientation();
|
||||
rigidBodyComponent->position = CURRENT_TF.getPosition();
|
||||
rigidBodyComponent->orientation = CURRENT_TF.getOrientation();
|
||||
|
||||
if (physicsObject.hasColliders)
|
||||
if (colliderComponent != nullptr)
|
||||
{
|
||||
auto* colliderComponent = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
|
||||
|
||||
colliderComponent->position = CURRENT_TF.getPosition();
|
||||
colliderComponent->orientation = CURRENT_TF.getOrientation();
|
||||
}
|
||||
|
@ -491,28 +447,146 @@ namespace SHADE
|
|||
}
|
||||
|
||||
// Convert RP3D Transform to SHADE
|
||||
auto* tfComponent = SHComponentManager::GetComponent<SHTransformComponent>(entityID);
|
||||
tfComponent->SetWorldPosition(rp3dPos);
|
||||
tfComponent->SetWorldOrientation(SHQuaternion{ rp3dRot });
|
||||
auto* transformComponent = SHComponentManager::GetComponent<SHTransformComponent>(entityID);
|
||||
transformComponent->SetWorldPosition(rp3dPos);
|
||||
transformComponent->SetWorldOrientation(rp3dRot);
|
||||
|
||||
// Cache transforms
|
||||
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
|
||||
if (!tf)
|
||||
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)
|
||||
{
|
||||
SHComponentManager::AddComponent<SHTransformComponent>(entityID);
|
||||
tf = SHComponentManager::GetComponent<SHTransformComponent>(entityID);
|
||||
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->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
|
|
@ -16,14 +16,14 @@
|
|||
#include <reactphysics3d/reactphysics3d.h>
|
||||
|
||||
// Project Headers
|
||||
#include "SHPhysicsObject.h"
|
||||
#include "Components/SHRigidBodyComponent.h"
|
||||
#include "Components/SHColliderComponent.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
|
||||
#include "Scene/SHSceneGraph.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"
|
||||
|
||||
|
||||
|
||||
namespace SHADE
|
||||
|
@ -32,7 +32,7 @@ namespace SHADE
|
|||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API SHPhysicsSystem : public SHSystem
|
||||
class SH_API SHPhysicsSystem final : public SHSystem
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -85,21 +85,10 @@ namespace SHADE
|
|||
void Init () override;
|
||||
void Exit () override;
|
||||
|
||||
void AddRigidBody (EntityID entityID) noexcept;
|
||||
void AddCollider (EntityID entityID) noexcept;
|
||||
void RemoveRigidBody (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 AddRigidBody (EntityID entityID) noexcept;
|
||||
//void AddCollider (EntityID entityID) noexcept;
|
||||
//void RemoveRigidBody (EntityID entityID) noexcept;
|
||||
//void RemoveCollider (EntityID entityID) noexcept;
|
||||
|
||||
void AddCollisionShape (EntityID entityID, SHCollider* collider);
|
||||
void RemoveCollisionShape (EntityID entityID, int index);
|
||||
|
@ -108,10 +97,7 @@ namespace SHADE
|
|||
/* System Routines */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Synchronises RP3D with SHADE
|
||||
*/
|
||||
class SH_API PhysicsPreUpdate : public SHSystemRoutine
|
||||
class SH_API PhysicsPreUpdate final : public SHSystemRoutine
|
||||
{
|
||||
public:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
@ -127,7 +113,7 @@ namespace SHADE
|
|||
void Execute(double dt) noexcept override;
|
||||
};
|
||||
|
||||
class SH_API PhysicsFixedUpdate : public SHFixedSystemRoutine
|
||||
class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine
|
||||
{
|
||||
public:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
@ -143,7 +129,7 @@ namespace SHADE
|
|||
void Execute (double dt) noexcept override;
|
||||
};
|
||||
|
||||
class SH_API PhysicsPostUpdate : public SHSystemRoutine
|
||||
class SH_API PhysicsPostUpdate final : public SHSystemRoutine
|
||||
{
|
||||
public:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
@ -170,15 +156,14 @@ namespace SHADE
|
|||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
// TODO(Diren): Store interpFactor
|
||||
|
||||
bool worldUpdated;
|
||||
|
||||
double interpolationFactor;
|
||||
double fixedDT;
|
||||
rp3d::PhysicsWorld* world;
|
||||
|
||||
rp3d::PhysicsWorld* world;
|
||||
rp3d::PhysicsCommon factory;
|
||||
|
||||
EntityObjectMap map;
|
||||
|
||||
|
||||
|
@ -186,7 +171,7 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHPhysicsObject* CreatePhysicsObject (EntityID entityID) noexcept;
|
||||
SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept;
|
||||
SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
|
||||
void DestroyPhysicsObject (EntityID entityID) noexcept;
|
||||
|
||||
|
@ -194,10 +179,9 @@ namespace SHADE
|
|||
void SyncRigidBodyComponents (std::vector<SHRigidBodyComponent>& denseArray) noexcept;
|
||||
void SyncColliderComponents (std::vector<SHColliderComponent>& denseArray) noexcept;
|
||||
void SyncTransforms () noexcept;
|
||||
// TODO(Diren): Trigger handling
|
||||
|
||||
// TODO(Diren): Remove when responsibility shifted to editor
|
||||
SHTransformComponent* EnsureTransform (EntityID entityID);
|
||||
SHEventHandle AddPhysicsComponent (SHEventPtr addComponentEvent);
|
||||
SHEventHandle RemovePhysicsComponent (SHEventPtr removeComponentEvent);
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue