Physics Component Synchronisation is now done through events

This commit is contained in:
Diren D Bharwani 2022-10-25 23:09:46 +08:00
parent 3c5a1b73d6
commit 0defa58c77
8 changed files with 143 additions and 147 deletions

View File

@ -61,9 +61,9 @@ namespace SHADE
void SHTransformSystem::Init()
{
std::shared_ptr thisChangeParentReceiver { std::make_shared<SHEventReceiverSpec<SHTransformSystem>>(this, &SHTransformSystem::ChangeParent) };
ReceiverPtr changeParentReceiver = std::dynamic_pointer_cast<SHEventReceiver>(thisChangeParentReceiver);
SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, changeParentReceiver);
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()
@ -258,16 +258,16 @@ namespace SHADE
SHEventHandle SHTransformSystem::ChangeParent(SHEventPtr changeParentEvent)
{
const auto& eventData = reinterpret_cast<const SHEventSpec<SHSceneGraphChangeParentEvent>*>(changeParentEvent.get());
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHSceneGraphChangeParentEvent>*>(changeParentEvent.get());
auto* node = eventData->data->node;
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 = eventData->data->newParent;
auto* newParent = EVENT_DATA->data->newParent;
const auto* PARENT_TF = SHComponentManager::GetComponent_s<SHTransformComponent>(newParent->GetEntityID());
if (PARENT_TF != nullptr) // Not the root
{
@ -297,7 +297,8 @@ namespace SHADE
// Propagate maintaining world transform down the branch
UpdateChildrenLocalTransforms(node);
return eventData->handle;
return EVENT_DATA->handle;
}
} // namespace SHADE

View File

@ -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 */

View File

@ -69,13 +69,13 @@ namespace SHADE
void SHColliderComponent::OnCreate()
{
system = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (!system)
{
SHLOG_ERROR("Physics system does not exist, Collider Component not added!")
return;
}
//if (!system)
//{
// SHLOG_ERROR("Physics system does not exist, Collider Component not added!")
// return;
//}
system->AddCollider(GetEID());
//system->AddCollider(GetEID());
}
void SHColliderComponent::OnDestroy()

View File

@ -265,14 +265,14 @@ namespace SHADE
void SHRigidBodyComponent::OnCreate()
{
system = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (!system)
{
SHLOG_ERROR("Physics system does not exist, Rigid Body Component not added!")
return;
}
//if (!system)
//{
// SHLOG_ERROR("Physics system does not exist, Rigid Body Component not added!")
// return;
//}
// Notify Physics System
system->AddRigidBody(GetEID());
//// Notify Physics System
//system->AddRigidBody(GetEID());
}
void SHRigidBodyComponent::OnDestroy()

View File

@ -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 (c != nullptr)
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 (c != nullptr)
{
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())
@ -205,8 +167,6 @@ namespace SHADE
for (auto& collider : c->colliders | std::views::keys)
AddCollider(&collider);
}
isRigidBody = false;
}
void SHPhysicsObject::DestroyCollisionBody() noexcept

View File

@ -69,8 +69,8 @@ namespace SHADE
/* Function Members */
/*---------------------------------------------------------------------------------*/
void CreateRigidBody (const SHTransformComponent* tf, SHRigidBodyComponent* rb, SHColliderComponent* c);
void CreateCollisionBody (const SHTransformComponent* tf, SHColliderComponent* c);
void CreateRigidBody (const SHVec3& pos, const SHQuaternion& orientation);
void CreateCollisionBody (const SHVec3& pos, const SHQuaternion& orientation);
int AddCollider (SHCollider* collider);
void DestroyRigidBody (SHColliderComponent* c) noexcept;
@ -86,8 +86,6 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
EntityID entityID;
bool isRigidBody;
bool hasColliders;
rp3d::PhysicsCommon* factory;
rp3d::PhysicsWorld* world;

View File

@ -175,11 +175,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 +188,12 @@ 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);
}
void SHPhysicsSystem::Exit()
@ -197,36 +201,29 @@ namespace SHADE
factory.destroyPhysicsWorld(world);
}
void SHPhysicsSystem::AddRigidBody(EntityID entityID) noexcept
{
//#ifdef _DEBUG
// SHLOG_INFO("Adding a Rigidbody to the Physics World.")
//#endif
//void SHPhysicsSystem::AddRigidBody(EntityID entityID) noexcept
//{
// //#ifdef _DEBUG
// // SHLOG_INFO("Adding a Rigidbody to the Physics World.")
// //#endif
auto* physicsObject = EnsurePhysicsObject(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
void SHPhysicsSystem::AddCollider(EntityID entityID) noexcept
{
//#ifdef _DEBUG
// SHLOG_INFO("Adding a Collider to the Physics World.")
//#endif
// auto* physicsObject = EnsurePhysicsObject(entityID);
auto* physicsObject = EnsurePhysicsObject(entityID);
physicsObject->CreateCollisionBody
(
EnsureTransform(entityID),
SHComponentManager::GetComponent<SHColliderComponent>(entityID)
);
}
// physicsObject->CreateCollisionBody
// (
// SHComponentManager::GetComponent<SHTransformComponent>(entityID),
// SHComponentManager::GetComponent<SHColliderComponent>(entityID)
// );
//}
void SHPhysicsSystem::RemoveRigidBody(EntityID entityID) noexcept
{
@ -415,15 +412,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));
@ -438,12 +438,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();
}
@ -457,26 +457,89 @@ namespace SHADE
// Convert RP3D Transform to SHADE
auto* tfComponent = SHComponentManager::GetComponent<SHTransformComponent>(entityID);
tfComponent->SetWorldPosition(rp3dPos);
tfComponent->SetWorldOrientation(SHQuaternion{ rp3dRot });
tfComponent->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 COMPONENT_ADDED_ID = EVENT_DATA->data->addedComponentType;
const bool IS_PHYSICS_COMPONENT = COMPONENT_ADDED_ID == RIGID_BODY_ID || COMPONENT_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 (COMPONENT_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 }
);
// Add collision shapes back into the body
if (colliderComponent != nullptr)
{
for (auto& collider : colliderComponent->colliders | std::views::keys)
physicsObject->AddCollider(&collider);
}
}
if (COMPONENT_ADDED_ID == COLLIDER_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());
return EVENT_DATA->handle;
}
} // namespace SHADE

View File

@ -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
@ -85,8 +85,8 @@ namespace SHADE
void Init () override;
void Exit () override;
void AddRigidBody (EntityID entityID) noexcept;
void AddCollider (EntityID entityID) noexcept;
//void AddRigidBody (EntityID entityID) noexcept;
//void AddCollider (EntityID entityID) noexcept;
void RemoveRigidBody (EntityID entityID) noexcept;
void RemoveCollider (EntityID entityID) noexcept;
@ -97,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:
/*-------------------------------------------------------------------------------*/
@ -116,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:
/*-------------------------------------------------------------------------------*/
@ -132,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:
/*-------------------------------------------------------------------------------*/
@ -182,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);
};