Merge branch 'main' into SP3-1-SerialisedRenderable

This commit is contained in:
Kah Wei 2022-10-31 17:48:02 +08:00
commit 33431d71a6
22 changed files with 880 additions and 229 deletions

View File

@ -108,13 +108,10 @@ namespace Sandbox
SHComponentManager::CreateComponentSparseSet<SHColliderComponent>(); SHComponentManager::CreateComponentSparseSet<SHColliderComponent>();
SHComponentManager::CreateComponentSparseSet<SHTransformComponent>(); SHComponentManager::CreateComponentSparseSet<SHTransformComponent>();
SHComponentManager::CreateComponentSparseSet<SHRenderable>(); SHComponentManager::CreateComponentSparseSet<SHRenderable>();
SHComponentManager::CreateComponentSparseSet<SHCameraComponent>(); //SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
SHAssetManager::Load(); SHAssetManager::Load();
auto id = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
auto id2 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
auto id3 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
SHSystemManager::RegisterRoutine<SHAudioSystem, SHAudioSystem::AudioRoutine>(); SHSystemManager::RegisterRoutine<SHAudioSystem, SHAudioSystem::AudioRoutine>();

View File

@ -0,0 +1,68 @@
#include "SHpch.h"
#include "SHCameraArmComponent.h"
namespace SHADE
{
SHCameraArmComponent::SHCameraArmComponent()
:pitch(0.0f), yaw(0.0f), armLength(1.0f),offset(), dirty(true), lookAtCameraOrigin(true)
{
}
SHVec3 const& SHCameraArmComponent::GetOffset() const noexcept
{
return offset;
}
float SHCameraArmComponent::GetPitch() const noexcept
{
return pitch;
}
float SHCameraArmComponent::GetYaw() const noexcept
{
return yaw;
}
float SHCameraArmComponent::GetArmLength() const noexcept
{
return armLength;
}
void SHCameraArmComponent::SetPitch(float pitch) noexcept
{
this->pitch = pitch;
dirty = true;
}
void SHCameraArmComponent::SetYaw(float yaw) noexcept
{
this->yaw = yaw;
dirty = true;
}
void SHCameraArmComponent::SetArmLength(float length) noexcept
{
this->armLength = length;
dirty = true;
}
}//namespace SHADE
RTTR_REGISTRATION
{
using namespace SHADE;
using namespace rttr;
registration::class_<SHCameraArmComponent>("Camera Arm Component")
.property("Arm Pitch", &SHCameraArmComponent::GetPitch, &SHCameraArmComponent::SetPitch)
.property("Arm Yaw", &SHCameraArmComponent::GetYaw, &SHCameraArmComponent::SetYaw)
.property("Arm Length", &SHCameraArmComponent::GetArmLength, &SHCameraArmComponent::SetArmLength)
.property("Look At Camera Origin", &SHCameraArmComponent::lookAtCameraOrigin);
}

View File

@ -0,0 +1,44 @@
#pragma once
#include <rttr/registration>
#include "ECS_Base/Components/SHComponent.h"
#include "Math/SHMatrix.h"
#include "SH_API.h"
namespace SHADE
{
class SH_API SHCameraArmComponent final: public SHComponent
{
private:
float pitch;
float yaw;
float armLength;
bool dirty;
SHVec3 offset;
public:
friend class SHCameraSystem;
SHCameraArmComponent();
virtual ~SHCameraArmComponent() = default;
bool lookAtCameraOrigin;
//Getters
//SHMatrix const& GetMatrix() const noexcept;
SHVec3 const& GetOffset() const noexcept;
float GetPitch() const noexcept;
float GetYaw() const noexcept;
float GetArmLength() const noexcept;
//Setters
void SetPitch(float pitch) noexcept;
void SetYaw(float yaw) noexcept;
void SetArmLength(float length) noexcept;
protected:
};
}//namespace SHADE

View File

@ -13,7 +13,7 @@ namespace SHADE
, width(1920.0f), height(1080.0f), zNear(0.01f), zFar(10000.0f), fov(90.0f), movementSpeed(1.0f), turnSpeed(0.5f) , width(1920.0f), height(1080.0f), zNear(0.01f), zFar(10000.0f), fov(90.0f), movementSpeed(1.0f), turnSpeed(0.5f)
, perspProj(true), dirtyView(true), dirtyProj(true) , perspProj(true), dirtyView(true), dirtyProj(true)
, viewMatrix(), projMatrix() , viewMatrix(), projMatrix()
, position() , position(), offset()
{ {
ComponentFamily::GetID<SHCameraComponent>(); ComponentFamily::GetID<SHCameraComponent>();
} }

View File

@ -33,7 +33,7 @@ namespace SHADE
SHVec3 position; SHVec3 position;
bool perspProj; bool perspProj;
SHVec3 offset;
@ -41,7 +41,7 @@ namespace SHADE
friend class SHCameraSystem; friend class SHCameraSystem;
SHCameraComponent(); SHCameraComponent();
~SHCameraComponent(); virtual ~SHCameraComponent();
//Getters and setters. //Getters and setters.

View File

@ -1,6 +1,7 @@
#include "SHpch.h" #include "SHpch.h"
#include "SHCameraDirector.h" #include "SHCameraDirector.h"
#include "SHCameraComponent.h" #include "SHCameraComponent.h"
#include "SHCameraArmComponent.h"
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/SHECSMacros.h" #include "ECS_Base/SHECSMacros.h"
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
@ -48,6 +49,7 @@ namespace SHADE
viewMatrix = camComponent->GetViewMatrix(); viewMatrix = camComponent->GetViewMatrix();
projMatrix = camComponent->GetProjMatrix(); projMatrix = camComponent->GetProjMatrix();
} }
} }
void SHCameraDirector::SetMainCamera(SHCameraComponent& camera) noexcept void SHCameraDirector::SetMainCamera(SHCameraComponent& camera) noexcept

View File

@ -21,6 +21,7 @@ namespace SHADE
EntityID mainCameraEID; EntityID mainCameraEID;
EntityID transitionCameraEID; EntityID transitionCameraEID;
SHMatrix GetViewMatrix() const noexcept; SHMatrix GetViewMatrix() const noexcept;
SHMatrix GetProjMatrix() const noexcept; SHMatrix GetProjMatrix() const noexcept;
@ -35,7 +36,7 @@ namespace SHADE
protected: protected:
SHMatrix viewMatrix; SHMatrix viewMatrix;
SHMatrix projMatrix; SHMatrix projMatrix;
}; };
typedef Handle<SHCameraDirector> DirectorHandle; typedef Handle<SHCameraDirector> DirectorHandle;

View File

@ -1,10 +1,12 @@
#include "SHpch.h" #include "SHpch.h"
#include "SHCameraSystem.h" #include "SHCameraSystem.h"
#include "SHCameraArmComponent.h"
#include "Math/SHMathHelpers.h" #include "Math/SHMathHelpers.h"
#include "Input/SHInputManager.h" #include "Input/SHInputManager.h"
#include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec2.h"
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include <math.h>
namespace SHADE namespace SHADE
@ -59,6 +61,7 @@ namespace SHADE
} }
UpdateCameraComponent(editorCamera); UpdateCameraComponent(editorCamera);
} }
void SHCameraSystem::EditorCameraUpdate::Execute(double dt) noexcept void SHCameraSystem::EditorCameraUpdate::Execute(double dt) noexcept
{ {
@ -112,6 +115,8 @@ namespace SHADE
//std::cout << "Camera position: " << camera.position.x << " " << camera.position.y << std::endl; //std::cout << "Camera position: " << camera.position.x << " " << camera.position.y << std::endl;
system->UpdateCameraComponent(system->editorCamera); system->UpdateCameraComponent(system->editorCamera);
system->DecomposeViewMatrix(camera.viewMatrix, camera.pitch, camera.yaw, camera.roll, camera.position);
} }
void SHCameraSystem::Init(void) void SHCameraSystem::Init(void)
@ -121,6 +126,9 @@ namespace SHADE
editorCamera.SetYaw(0.0f); editorCamera.SetYaw(0.0f);
editorCamera.SetRoll(0.0f); editorCamera.SetRoll(0.0f);
editorCamera.movementSpeed = 2.0f; editorCamera.movementSpeed = 2.0f;
SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
SHComponentManager::CreateComponentSparseSet<SHCameraArmComponent>();
} }
@ -134,6 +142,26 @@ namespace SHADE
return &editorCamera; return &editorCamera;
} }
void SHCameraSystem::UpdatePivotArmComponent(SHCameraArmComponent& pivot) noexcept
{
if (pivot.dirty)
{
SHVec3 offset{ 0.0f,0.0f, pivot.GetArmLength() };
offset = SHVec3::RotateX(offset, -(SHMath::DegreesToRadians(pivot.GetPitch())));
offset = SHVec3::RotateY(offset, (SHMath::DegreesToRadians(pivot.GetYaw())));
//pivot.rtMatrix = SHMatrix::RotateX(SHMath::DegreesToRadians(pivot.GetPitch()))
// * SHMatrix::RotateY(SHMath::DegreesToRadians(pivot.GetYaw()))
// * SHMatrix::Translate(SHVec3(0.0f , 0.0f, pivot.GetArmLength()));
pivot.offset = offset;
// pivot.rtMatrix = SHMatrix::Inverse(pivot.rtMatrix);
}
}
void SHCameraSystem::UpdateCameraComponent(SHCameraComponent& camera) noexcept void SHCameraSystem::UpdateCameraComponent(SHCameraComponent& camera) noexcept
{ {
if (SHComponentManager::HasComponent<SHTransformComponent>(camera.GetEID()) == true && &camera != &editorCamera) if (SHComponentManager::HasComponent<SHTransformComponent>(camera.GetEID()) == true && &camera != &editorCamera)
@ -151,6 +179,15 @@ namespace SHADE
if (camera.dirtyView) if (camera.dirtyView)
{ {
camera.offset = SHVec3{ 0.0f };
if (SHComponentManager::HasComponent<SHCameraArmComponent>(camera.GetEID()))
{
auto arm = SHComponentManager::GetComponent<SHCameraArmComponent>(camera.GetEID());
camera.offset = arm->GetOffset();
if(arm->lookAtCameraOrigin)
CameraLookAt(camera, camera.position);
}
SHVec3 view, right, UP; SHVec3 view, right, UP;
@ -171,9 +208,12 @@ namespace SHADE
camera.viewMatrix(2, 1) = view[1]; camera.viewMatrix(2, 1) = view[1];
camera.viewMatrix(2, 2) = view[2]; camera.viewMatrix(2, 2) = view[2];
camera.viewMatrix(0, 3) = -right.Dot(camera.position); camera.viewMatrix(0, 3) = -right.Dot(camera.position + camera.offset);
camera.viewMatrix(1, 3) = -UP.Dot(camera.position); camera.viewMatrix(1, 3) = -UP.Dot(camera.position + camera.offset);
camera.viewMatrix(2, 3) = -view.Dot(camera.position); camera.viewMatrix(2, 3) = -view.Dot(camera.position + camera.offset);
camera.dirtyView = false; camera.dirtyView = false;
} }
@ -221,6 +261,8 @@ namespace SHADE
SHVec3 up = { 0.0f,1.0f,0.0f }; SHVec3 up = { 0.0f,1.0f,0.0f };
target = SHVec3::RotateX(target, SHMath::DegreesToRadians(camera.pitch)); target = SHVec3::RotateX(target, SHMath::DegreesToRadians(camera.pitch));
target = SHVec3::RotateY(target, SHMath::DegreesToRadians(camera.yaw)); target = SHVec3::RotateY(target, SHMath::DegreesToRadians(camera.yaw));
target += camera.position; target += camera.position;
@ -241,6 +283,13 @@ namespace SHADE
{ {
SHCameraSystem* system = static_cast<SHCameraSystem*>(GetSystem()); SHCameraSystem* system = static_cast<SHCameraSystem*>(GetSystem());
auto& dense = SHComponentManager::GetDense<SHCameraComponent>(); auto& dense = SHComponentManager::GetDense<SHCameraComponent>();
auto& pivotDense = SHComponentManager::GetDense<SHCameraArmComponent>();
for (auto& pivot : pivotDense)
{
system->UpdatePivotArmComponent(pivot);
}
for (auto& cam : dense) for (auto& cam : dense)
{ {
system->UpdateCameraComponent(cam); system->UpdateCameraComponent(cam);
@ -274,18 +323,115 @@ namespace SHADE
} }
void SHCameraSystem::ClampCameraRotation(SHCameraComponent& camera) noexcept void SHCameraSystem::ClampCameraRotation(SHCameraComponent& camera) noexcept
{ {
constexpr float clampVal = 85.0f;
if (camera.pitch > clampVal)
camera.SetPitch(clampVal);
if (camera.pitch < -clampVal)
camera.SetPitch(-clampVal);
if (camera.roll > clampVal)
camera.SetRoll(clampVal);
if (camera.roll < -clampVal)
camera.SetRoll(-clampVal);
if (camera.pitch > 85) while (camera.yaw > 360)
camera.SetPitch(85); camera.yaw -= 360;
if (camera.pitch < -85) while (camera.yaw < -360)
camera.SetPitch(-85); camera.yaw += 360;
if (camera.roll > 85)
camera.SetRoll(85);
if (camera.roll < -85)
camera.SetRoll(-85);
} }
void SHCameraSystem::SetMainCamera(EntityID eid, size_t directorIndex) noexcept
{
if (SHComponentManager::HasComponent<SHCameraComponent>(eid) && directorIndex < directorHandleList.size())
directorHandleList[directorIndex]->SetMainCamera(*SHComponentManager::GetComponent<SHCameraComponent>(eid));
else
{
SHLOG_WARNING("Set Main Camera warning: Entity does not have camera component or director does not exist.")
}
}
void SHCameraSystem::DecomposeViewMatrix(SHMatrix const& viewMatrix, float& pitch, float& yaw, float& roll, SHVec3& pos) noexcept
{
float initPitch = pitch;
SHVec3 initPos = pos;
SHVec3 translate3, scale;
SHQuaternion quat;
//SHMatrix viewInverse = viewMatrix;
viewMatrix.Decompose(translate3, quat, scale);
yaw = 180+ SHMath::RadiansToDegrees(quat.ToEuler().y);
pitch = -SHMath::RadiansToDegrees(quat.ToEuler().x);
SHVec4 dotPos{ -viewMatrix(0,3),-viewMatrix(1,3), -viewMatrix(2,3), 1.0f };
SHMatrix mtx = viewMatrix;
mtx(0, 3) = 0.0f;
mtx(1, 3) = 0.0f;
mtx(2, 3) = 0.0f;
mtx.Transpose();
mtx = SHMatrix::Inverse(mtx);
SHVec4 translate = mtx* dotPos;
pos.x = translate.x;
pos.y = translate.y;
pos.z = translate.z;
}
void SHCameraSystem::SetCameraViewMatrix(SHCameraComponent& camera, SHMatrix const& viewMatrix) noexcept
{
DecomposeViewMatrix(viewMatrix, camera.pitch, camera.yaw, camera.roll, camera.position);
camera.dirtyView = true;
}
void SHCameraSystem::CameraLookAt(SHCameraComponent& camera, SHVec3 target) noexcept
{
if (camera.position == target)
{
//lets off set it abit so the view is nt fked
target.z -= 0.0001f;
}
SHVec3 forward, right, upVec;
SHVec3 up = { 0.0f,1.0f,0.0f };
////SHVec3::RotateZ(target, SHMath::DegreesToRadians(camera.roll));
//target = SHVec3::Normalise(target);
SHVec3::RotateZ(up, camera.roll);
up = SHVec3::Normalise(up);
forward = target - (camera.position + camera.offset); forward = SHVec3::Normalise(forward);
right = SHVec3::Cross(forward, up); right = SHVec3::Normalise(right);
upVec = SHVec3::Cross(forward, right);
SHMatrix viewMtx;
viewMtx = SHMatrix::Identity;
viewMtx(0, 0) = right[0];
viewMtx(0, 1) = right[1];
viewMtx(0, 2) = right[2];
viewMtx(1, 0) = upVec[0];
viewMtx(1, 1) = upVec[1];
viewMtx(1, 2) = upVec[2];
viewMtx(2, 0) = forward[0];
viewMtx(2, 1) = forward[1];
viewMtx(2, 2) = forward[2];
viewMtx(0, 3) = -right.Dot(camera.position + camera.offset);
viewMtx(1, 3) = -upVec.Dot(camera.position + camera.offset);
viewMtx(2, 3) = -forward.Dot(camera.position + camera.offset);
SetCameraViewMatrix(camera, viewMtx);
}
} }

View File

@ -9,6 +9,9 @@
namespace SHADE namespace SHADE
{ {
class SHCameraArmComponent;
class SH_API SHCameraSystem final : public SHSystem class SH_API SHCameraSystem final : public SHSystem
{ {
private: private:
@ -19,6 +22,11 @@ namespace SHADE
SHResourceLibrary<SHCameraDirector> directorLibrary; SHResourceLibrary<SHCameraDirector> directorLibrary;
std::vector<DirectorHandle> directorHandleList; std::vector<DirectorHandle> directorHandleList;
void UpdateCameraComponent(SHCameraComponent& camera) noexcept;
void UpdatePivotArmComponent(SHCameraArmComponent& pivot) noexcept;
public: public:
SHCameraSystem(void) = default; SHCameraSystem(void) = default;
virtual ~SHCameraSystem(void) = default; virtual ~SHCameraSystem(void) = default;
@ -39,7 +47,7 @@ namespace SHADE
class SH_API CameraSystemUpdate final: public SHSystemRoutine class SH_API CameraSystemUpdate final: public SHSystemRoutine
{ {
public: public:
CameraSystemUpdate() : SHSystemRoutine("Camera System Update", false) {}; CameraSystemUpdate() : SHSystemRoutine("Camera System Update", true) {};
virtual void Execute(double dt)noexcept override final; virtual void Execute(double dt)noexcept override final;
}; };
friend class CameraSystemUpdate; friend class CameraSystemUpdate;
@ -51,12 +59,10 @@ namespace SHADE
DirectorHandle GetDirector(size_t index) noexcept; DirectorHandle GetDirector(size_t index) noexcept;
void ClampCameraRotation(SHCameraComponent& camera) noexcept; void ClampCameraRotation(SHCameraComponent& camera) noexcept;
void UpdateEditorCamera(double dt) noexcept; void UpdateEditorCamera(double dt) noexcept;
protected: void SetMainCamera(EntityID eid, size_t directorIndex) noexcept;
void DecomposeViewMatrix(SHMatrix const& matrix, float& pitch, float& yaw, float& roll, SHVec3& pos) noexcept;
void UpdateCameraComponent(SHCameraComponent& camera) noexcept; void SetCameraViewMatrix(SHCameraComponent& camera, SHMatrix const& viewMatrix) noexcept;
void CameraLookAt(SHCameraComponent& camera, SHVec3 target) noexcept;
}; };

View File

@ -40,6 +40,12 @@ namespace SHADE
{ {
comp->OnDestroy(); comp->OnDestroy();
} }
SHComponentRemovedEvent eventData;
eventData.eid = entityID;
eventData.removedComponentType = i;
SHEventManager::BroadcastEvent<SHComponentRemovedEvent>(eventData, SH_COMPONENT_REMOVED_EVENT);
} }
@ -53,6 +59,7 @@ namespace SHADE
//entityHandle.RemoveHandle(entityID); //entityHandle.RemoveHandle(entityID);
} }

View File

@ -17,6 +17,7 @@
#include "Physics/Components/SHRigidBodyComponent.h" #include "Physics/Components/SHRigidBodyComponent.h"
#include "Physics/Components/SHColliderComponent.h" #include "Physics/Components/SHColliderComponent.h"
#include "Camera/SHCameraComponent.h" #include "Camera/SHCameraComponent.h"
#include "Camera/SHCameraArmComponent.h"
#include "SHEditorComponentView.h" #include "SHEditorComponentView.h"
namespace SHADE namespace SHADE
@ -126,6 +127,9 @@ namespace SHADE
if (auto cameraComponent = SHComponentManager::GetComponent_s<SHCameraComponent>(eid)) if (auto cameraComponent = SHComponentManager::GetComponent_s<SHCameraComponent>(eid))
{ {
DrawComponent(cameraComponent); DrawComponent(cameraComponent);
}if (auto cameraArmComponent = SHComponentManager::GetComponent_s<SHCameraArmComponent>(eid))
{
DrawComponent(cameraArmComponent);
} }
ImGui::Separator(); ImGui::Separator();
// Render Scripts // Render Scripts
@ -136,6 +140,7 @@ namespace SHADE
{ {
DrawAddComponentButton<SHTransformComponent>(eid); DrawAddComponentButton<SHTransformComponent>(eid);
DrawAddComponentButton<SHCameraComponent>(eid); DrawAddComponentButton<SHCameraComponent>(eid);
DrawAddComponentButton<SHCameraArmComponent>(eid);
DrawAddComponentButton<SHLightComponent>(eid); DrawAddComponentButton<SHLightComponent>(eid);
// Components that require Transforms // Components that require Transforms

View File

@ -47,16 +47,14 @@ namespace SHADE
{ {
// Get the current scene graph to traverse and update // Get the current scene graph to traverse and update
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
UpdateEntity(SCENE_GRAPH.GetRoot(), !IsRunInEditorPause);
// TODO(Diren): Consider how to clear dirty in pause / stop mode and update physics, but do not clear in play mode.
UpdateEntity(SCENE_GRAPH.GetRoot(), false);
} }
void SHTransformSystem::TransformPostPhysicsUpdate::Execute(double) noexcept void SHTransformSystem::TransformPostPhysicsUpdate::Execute(double) noexcept
{ {
// Get the current scene graph to traverse and update // Get the current scene graph to traverse and update
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
UpdateEntity(SCENE_GRAPH.GetRoot(), true); UpdateEntity(SCENE_GRAPH.GetRoot(), IsRunInEditorPause);
} }
void SHTransformSystem::Init() void SHTransformSystem::Init()

View File

@ -96,7 +96,7 @@ namespace SHADE
void SetDensity (float density) noexcept; void SetDensity (float density) noexcept;
void SetMaterial (const SHPhysicsMaterial& newMaterial) noexcept; void SetMaterial (const SHPhysicsMaterial& newMaterial) noexcept;
void SetPositionOffset (const SHVec3& positionOffset) noexcept; void SetPositionOffset (const SHVec3& posOffset) noexcept;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -172,90 +172,94 @@ namespace SHADE
{ {
SHASSERT(rp3dBody != nullptr, "ReactPhysics body does not exist!") SHASSERT(rp3dBody != nullptr, "ReactPhysics body does not exist!")
if (rb->dirtyFlags == 0)
return;
auto* rigidBody = reinterpret_cast<rp3d::RigidBody*>(rp3dBody); auto* rigidBody = reinterpret_cast<rp3d::RigidBody*>(rp3dBody);
if (rb->dirtyFlags != 0)
const uint16_t RB_FLAGS = rb->dirtyFlags;
for (size_t i = 0; i < SHRigidBodyComponent::NUM_DIRTY_FLAGS; ++i)
{ {
// Check if current dirty flag has been set to true const uint16_t RB_FLAGS = rb->dirtyFlags;
if (RB_FLAGS & 1U << i) for (size_t i = 0; i < SHRigidBodyComponent::NUM_DIRTY_FLAGS; ++i)
{ {
switch (i) // Check if current dirty flag has been set to true
if (RB_FLAGS & 1U << i)
{ {
case 0: // Gravity switch (i)
{ {
rigidBody->enableGravity(rb->IsGravityEnabled()); case 0: // Gravity
break;
}
case 1: // Sleeping
{
rigidBody->setIsAllowedToSleep(rb->IsAllowedToSleep());
break;
}
case 2: // Linear Constraints
{
const rp3d::Vector3 CONSTRAINTS
{ {
rb->flags & 1U << 2 ? 0.0f : 1.0f, rigidBody->enableGravity(rb->IsGravityEnabled());
rb->flags & 1U << 3 ? 0.0f : 1.0f, break;
rb->flags & 1U << 4 ? 0.0f : 1.0f }
}; case 1: // Sleeping
{
rigidBody->setIsAllowedToSleep(rb->IsAllowedToSleep());
break;
}
case 2: // Linear Constraints
{
const rp3d::Vector3 CONSTRAINTS
{
rb->flags & 1U << 2 ? 0.0f : 1.0f,
rb->flags & 1U << 3 ? 0.0f : 1.0f,
rb->flags & 1U << 4 ? 0.0f : 1.0f
};
rigidBody->setLinearLockAxisFactor(CONSTRAINTS); rigidBody->setLinearLockAxisFactor(CONSTRAINTS);
break; break;
} }
case 3: // Angular Constraints case 3: // Angular Constraints
{
const rp3d::Vector3 CONSTRAINTS
{ {
rb->flags & 1U << 5 ? 0.0f : 1.0f, const rp3d::Vector3 CONSTRAINTS
rb->flags & 1U << 6 ? 0.0f : 1.0f, {
rb->flags & 1U << 7 ? 0.0f : 1.0f rb->flags & 1U << 5 ? 0.0f : 1.0f,
}; rb->flags & 1U << 6 ? 0.0f : 1.0f,
rb->flags & 1U << 7 ? 0.0f : 1.0f
};
rigidBody->setAngularLockAxisFactor(CONSTRAINTS); rigidBody->setAngularLockAxisFactor(CONSTRAINTS);
break; break;
}
case 4: // Type
{
rigidBody->setType(static_cast<rp3d::BodyType>(rb->GetType()));
break;
}
case 5: // Mass
{
rigidBody->setMass(rb->GetMass());
break;
}
case 6: // Drag
{
rigidBody->setLinearDamping(rb->GetDrag());
break;
}
case 7: // Angular Drag
{
rigidBody->setAngularDamping(rb->GetAngularDrag());
break;
}
case 8: // Linear Velocity
{
rigidBody->setLinearVelocity(rb->GetLinearVelocity());
break;
}
case 9: // Angular Velocity
{
rigidBody->setAngularVelocity(rb->GetAngularVelocity());
break;
}
default: break;
} }
case 4: // Type
{
rigidBody->setType(static_cast<rp3d::BodyType>(rb->GetType()));
break;
}
case 5: // Mass
{
rigidBody->setMass(rb->GetMass());
break;
}
case 6: // Drag
{
rigidBody->setLinearDamping(rb->GetDrag());
break;
}
case 7: // Angular Drag
{
rigidBody->setAngularDamping(rb->GetAngularDrag());
break;
}
case 8: // Linear Velocity
{
rigidBody->setLinearVelocity(rb->GetLinearVelocity());
break;
}
case 9: // Angular Velocity
{
rigidBody->setAngularVelocity(rb->GetAngularVelocity());
break;
}
default: break;
} }
} }
}
rb->dirtyFlags = 0; rb->dirtyFlags = 0;
}
else
{
rb->linearVelocity = rigidBody->getLinearVelocity();
rb->angularVelocity = rigidBody->getAngularVelocity();
}
} }
void SHPhysicsObject::SyncColliders(SHColliderComponent* c) const noexcept void SHPhysicsObject::SyncColliders(SHColliderComponent* c) const noexcept
@ -266,8 +270,12 @@ namespace SHADE
if (!collider.dirty) if (!collider.dirty)
continue; continue;
// Update offsets
auto* rp3dCollider = rp3dBody->getCollider(index); auto* rp3dCollider = rp3dBody->getCollider(index);
// Update trigger flag
rp3dCollider->setIsTrigger(collider.IsTrigger());
// Update offsets
rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), SHQuaternion::Identity)); rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), SHQuaternion::Identity));
switch (collider.GetType()) switch (collider.GetType())
@ -293,6 +301,8 @@ namespace SHADE
default: break; default: break;
} }
// TODO(Diren): Update Material
collider.dirty = false; collider.dirty = false;
++index; ++index;
} }

View File

@ -99,6 +99,16 @@ namespace SHADE
return 0; return 0;
} }
const SHPhysicsSystem::CollisionEvents& SHPhysicsSystem::GetCollisionInfo() const noexcept
{
return collisionInfo;
}
const SHPhysicsSystem::CollisionEvents& SHPhysicsSystem::GetTriggerInfo() const noexcept
{
return triggerInfo;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */ /* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -187,6 +197,7 @@ namespace SHADE
settings.defaultBounciness = 0.0f; settings.defaultBounciness = 0.0f;
world = factory.createPhysicsWorld(settings); world = factory.createPhysicsWorld(settings);
world->setEventListener(this);
// Set up solvers // Set up solvers
world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES); world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES);
@ -246,7 +257,10 @@ namespace SHADE
if (physicsObject.rp3dBody == nullptr) if (physicsObject.rp3dBody == nullptr)
continue; continue;
const auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID); const auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
if (transformComponent && transformComponent->HasChanged()) if (transformComponent && transformComponent->HasChanged())
{ {
const auto WORLD_POS = transformComponent->GetWorldPosition(); const auto WORLD_POS = transformComponent->GetWorldPosition();
@ -255,35 +269,58 @@ namespace SHADE
physicsObject.SetPosition(WORLD_POS); physicsObject.SetPosition(WORLD_POS);
physicsObject.SetOrientation(WORLD_ROT); physicsObject.SetOrientation(WORLD_ROT);
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID); // Sync physics component transforms
if (rigidBodyComponent) if (rigidBodyComponent)
{ {
rigidBodyComponent->position = WORLD_POS; rigidBodyComponent->position = WORLD_POS;
rigidBodyComponent->orientation = WORLD_ROT; rigidBodyComponent->orientation = WORLD_ROT;
// Clear all forces and velocities if editor is stopped
if (SHSystemManager::GetSystem<SHEditor>()->editorState == SHEditor::State::STOP)
{
auto* rp3dRigidBody = reinterpret_cast<rp3d::RigidBody*>(physicsObject.rp3dBody);
rp3dRigidBody->resetForce();
rp3dRigidBody->resetTorque();
rp3dRigidBody->setLinearVelocity(SHVec3::Zero);
rp3dRigidBody->setAngularVelocity(SHVec3::Zero);
}
} }
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
if (colliderComponent) if (colliderComponent)
{ {
colliderComponent->position = WORLD_POS; colliderComponent->position = WORLD_POS;
colliderComponent->orientation = WORLD_ROT; colliderComponent->orientation = WORLD_ROT;
} }
} }
}
// Update bodies and colliders if component is dirty // Sync rigid bodies
system->SyncRigidBodyComponents(SHComponentManager::GetDense<SHRigidBodyComponent>());
system->SyncColliderComponents(SHComponentManager::GetDense<SHColliderComponent>()); if (rigidBodyComponent)
{
// Clear all forces and velocities if editor is stopped
if (SHSystemManager::GetSystem<SHEditor>()->editorState == SHEditor::State::STOP)
{
auto* rp3dRigidBody = reinterpret_cast<rp3d::RigidBody*>(physicsObject.rp3dBody);
rp3dRigidBody->resetForce();
rp3dRigidBody->resetTorque();
rp3dRigidBody->setLinearVelocity(SHVec3::Zero);
rp3dRigidBody->setAngularVelocity(SHVec3::Zero);
}
// Sync active states
const bool COMPONENT_ACTIVE = rigidBodyComponent->isActive;
SyncActiveStates(physicsObject, COMPONENT_ACTIVE);
if (!COMPONENT_ACTIVE)
continue;
physicsObject.SyncRigidBody(rigidBodyComponent);
}
// Sync colliders
if (colliderComponent)
{
const bool COMPONENT_ACTIVE = colliderComponent->isActive;
SyncActiveStates(physicsObject, colliderComponent->isActive);
if (!COMPONENT_ACTIVE)
continue;
physicsObject.SyncColliders(colliderComponent);
}
}
} }
void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept
@ -316,7 +353,31 @@ namespace SHADE
{ {
system->SyncTransforms(); system->SyncTransforms();
// TODO(Diren): Handle trigger messages for scripting // TODO(Kah Wei): Take Collision & Trigger messages here
system->ClearInvalidCollisions();
}
}
void SHPhysicsSystem::onContact(const CallbackData& callbackData)
{
for (uint32_t i = 0; i < callbackData.getNbContactPairs(); ++i)
{
const auto CONTACT_PAIR = callbackData.getContactPair(i);
const SHCollisionEvent NEW_EVENT = GenerateCollisionEvent(CONTACT_PAIR);
UpdateEventContainers(NEW_EVENT, collisionInfo);
}
}
void SHPhysicsSystem::onTrigger(const rp3d::OverlapCallback::CallbackData& callbackData)
{
for (uint32_t i = 0; i < callbackData.getNbOverlappingPairs(); ++i)
{
const auto& OVERLAP_PAIR = callbackData.getOverlappingPair(i);
const SHCollisionEvent NEW_EVENT = GenerateCollisionEvent(OVERLAP_PAIR);
UpdateEventContainers(NEW_EVENT, triggerInfo);
} }
} }
@ -353,58 +414,11 @@ namespace SHADE
map.erase(entityID); map.erase(entityID);
} }
void SHPhysicsSystem::SyncActiveStates(SHPhysicsObject* physicsObject, bool componentActive) noexcept void SHPhysicsSystem::SyncActiveStates(SHPhysicsObject& physicsObject, bool componentActive) noexcept
{ {
const bool RP3D_ACTIVE = physicsObject->rp3dBody->isActive(); const bool RP3D_ACTIVE = physicsObject.rp3dBody->isActive();
if (RP3D_ACTIVE != componentActive) if (RP3D_ACTIVE != componentActive)
physicsObject->rp3dBody->setIsActive(componentActive); physicsObject.rp3dBody->setIsActive(componentActive);
}
void SHPhysicsSystem::SyncRigidBodyComponents(std::vector<SHRigidBodyComponent>& denseArray) noexcept
{
if (denseArray.empty())
return;
for (auto& comp : denseArray)
{
const EntityID ENTITY_ID = comp.GetEID();
// Get physicsObject
auto* physicsObject = GetPhysicsObject(ENTITY_ID);
// TODO(Diren): Check if active in hierarchy
const bool COMPONENT_ACTIVE = comp.isActive;
SyncActiveStates(physicsObject, COMPONENT_ACTIVE);
if (!COMPONENT_ACTIVE)
continue;
physicsObject->SyncRigidBody(&comp);
}
}
void SHPhysicsSystem::SyncColliderComponents(std::vector<SHColliderComponent>& denseArray) noexcept
{
if (denseArray.empty())
return;
for (auto& comp : denseArray)
{
const EntityID ENTITY_ID = comp.GetEID();
// Get physicsObject
auto* physicsObject = GetPhysicsObject(ENTITY_ID);
// TODO(Diren): Check if active in hierarchy
const bool COMPONENT_ACTIVE = comp.isActive;
SyncActiveStates(physicsObject, COMPONENT_ACTIVE);
if (!COMPONENT_ACTIVE)
continue;
physicsObject->SyncColliders(&comp);
}
} }
void SHPhysicsSystem::SyncTransforms() noexcept void SHPhysicsSystem::SyncTransforms() noexcept
@ -459,15 +473,54 @@ namespace SHADE
} }
// Convert RP3D Transform to SHADE // Convert RP3D Transform to SHADE
auto* transformComponent = SHComponentManager::GetComponent<SHTransformComponent>(entityID); auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
transformComponent->SetWorldPosition(rp3dPos);
transformComponent->SetWorldOrientation(rp3dRot); if (transformComponent != nullptr)
{
transformComponent->SetWorldPosition(rp3dPos);
transformComponent->SetWorldOrientation(rp3dRot);
}
// Cache transforms // Cache transforms
physicsObject.prevTransform = CURRENT_TF; physicsObject.prevTransform = CURRENT_TF;
} }
} }
void SHPhysicsSystem::UpdateEventContainers(const SHCollisionEvent& collisionEvent, CollisionEvents& container) noexcept
{
const auto IT = std::ranges::find_if(container.begin(), container.end(), [&](const SHCollisionEvent& e)
{
const bool ENTITY_MATCH = e.value[0] == collisionEvent.value[0];
const bool COLLIDERS_MATCH = e.value[1] == collisionEvent.value[1];
return ENTITY_MATCH && COLLIDERS_MATCH;
});
if (IT == container.end())
container.emplace_back(collisionEvent);
else
IT->collisionState = collisionEvent.collisionState;
}
void SHPhysicsSystem::ClearInvalidCollisions() noexcept
{
static const auto CLEAR = [](CollisionEvents& container)
{
for (auto eventIter = container.begin(); eventIter != container.end();)
{
const bool CLEAR_EVENT = eventIter->GetCollisionState() == SHCollisionEvent::State::EXIT
|| eventIter->GetCollisionState() == SHCollisionEvent::State::INVALID;
if (CLEAR_EVENT)
eventIter = container.erase(eventIter);
else
++eventIter;
}
};
CLEAR(collisionInfo);
CLEAR(triggerInfo);
}
SHEventHandle SHPhysicsSystem::AddPhysicsComponent(SHEventPtr addComponentEvent) SHEventHandle SHPhysicsSystem::AddPhysicsComponent(SHEventPtr addComponentEvent)
{ {
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentAddedEvent>*>(addComponentEvent.get()); const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentAddedEvent>*>(addComponentEvent.get());
@ -556,6 +609,9 @@ namespace SHADE
const EntityID ENTITY_ID = EVENT_DATA->data->eid; const EntityID ENTITY_ID = EVENT_DATA->data->eid;
auto* physicsObject = GetPhysicsObject(ENTITY_ID); auto* physicsObject = GetPhysicsObject(ENTITY_ID);
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ENTITY_ID);
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(ENTITY_ID);
SHASSERT(physicsObject != nullptr, "Physics object has been lost from the world!") SHASSERT(physicsObject != nullptr, "Physics object has been lost from the world!")
if (REMOVED_ID == RIGID_BODY_ID) if (REMOVED_ID == RIGID_BODY_ID)
@ -563,7 +619,6 @@ namespace SHADE
world->destroyRigidBody(reinterpret_cast<rp3d::RigidBody*>(physicsObject->rp3dBody)); world->destroyRigidBody(reinterpret_cast<rp3d::RigidBody*>(physicsObject->rp3dBody));
physicsObject->rp3dBody = nullptr; physicsObject->rp3dBody = nullptr;
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(ENTITY_ID);
if (colliderComponent != nullptr) if (colliderComponent != nullptr)
{ {
// Preserve colliders as a collision body // Preserve colliders as a collision body
@ -594,6 +649,10 @@ namespace SHADE
auto* collider = physicsObject->rp3dBody->getCollider(i); auto* collider = physicsObject->rp3dBody->getCollider(i);
physicsObject->rp3dBody->removeCollider(collider); physicsObject->rp3dBody->removeCollider(collider);
} }
// Check for a rigidbody component
if (rigidBodyComponent == nullptr)
physicsObject->rp3dBody = nullptr;
} }
if (physicsObject->rp3dBody == nullptr) if (physicsObject->rp3dBody == nullptr)

View File

@ -23,16 +23,23 @@
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Scene/SHSceneGraph.h" #include "Scene/SHSceneGraph.h"
#include "SHPhysicsObject.h" #include "SHPhysicsObject.h"
#include "SHPhysicsUtils.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/
/* Concepts */
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
class SH_API SHPhysicsSystem final : public SHSystem class SH_API SHPhysicsSystem final : public SHSystem
, public rp3d::EventListener
{ {
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -47,6 +54,8 @@ namespace SHADE
bool sleepingEnabled; bool sleepingEnabled;
}; };
using CollisionEvents = std::vector<SHCollisionEvent>;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */ /* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -57,13 +66,16 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] double GetFixedDT () const noexcept; [[nodiscard]] double GetFixedDT () const noexcept;
[[nodiscard]] bool IsSleepingEnabled () const noexcept; [[nodiscard]] bool IsSleepingEnabled () const noexcept;
[[nodiscard]] SHVec3 GetWorldGravity () const noexcept; [[nodiscard]] SHVec3 GetWorldGravity () const noexcept;
[[nodiscard]] uint16_t GetNumberVelocityIterations () const noexcept; [[nodiscard]] uint16_t GetNumberVelocityIterations () const noexcept;
[[nodiscard]] uint16_t GetNumberPositionIterations () const noexcept; [[nodiscard]] uint16_t GetNumberPositionIterations () const noexcept;
[[nodiscard]] const CollisionEvents& GetCollisionInfo () const noexcept;
[[nodiscard]] const CollisionEvents& GetTriggerInfo () const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -82,16 +94,14 @@ namespace SHADE
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void Init () override; void Init () override;
void Exit () override; void Exit () override;
//void AddRigidBody (EntityID entityID) noexcept; void AddCollisionShape (EntityID entityID, SHCollider* collider);
//void AddCollider (EntityID entityID) noexcept; void RemoveCollisionShape (EntityID entityID, int index);
//void RemoveRigidBody (EntityID entityID) noexcept;
//void RemoveCollider (EntityID entityID) noexcept;
void AddCollisionShape (EntityID entityID, SHCollider* collider); void onContact (const rp3d::CollisionCallback::CallbackData& callbackData) override;
void RemoveCollisionShape (EntityID entityID, int index); void onTrigger (const rp3d::OverlapCallback::CallbackData& callbackData) override;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* System Routines */ /* System Routines */
@ -156,49 +166,40 @@ namespace SHADE
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
bool worldUpdated; bool worldUpdated;
double interpolationFactor; double interpolationFactor;
double fixedDT; double fixedDT;
rp3d::PhysicsWorld* world;
rp3d::PhysicsCommon factory;
EntityObjectMap map;
rp3d::PhysicsWorld* world;
rp3d::PhysicsCommon factory;
EntityObjectMap map;
CollisionEvents collisionInfo;
CollisionEvents triggerInfo;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept;
SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
void DestroyPhysicsObject (EntityID entityID) noexcept;
void SyncActiveStates (SHPhysicsObject* physicsObject, bool componentActive) noexcept; SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept;
void SyncRigidBodyComponents (std::vector<SHRigidBodyComponent>& denseArray) noexcept; SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
void SyncColliderComponents (std::vector<SHColliderComponent>& denseArray) noexcept; void DestroyPhysicsObject (EntityID entityID) noexcept;
static void SyncActiveStates (SHPhysicsObject& physicsObject, bool componentActive) noexcept;
void SyncTransforms () noexcept; void SyncTransforms () noexcept;
static void UpdateEventContainers (const SHCollisionEvent& collisionEvent, CollisionEvents& container) noexcept;
void ClearInvalidCollisions () noexcept;
SHEventHandle AddPhysicsComponent (SHEventPtr addComponentEvent); SHEventHandle AddPhysicsComponent (SHEventPtr addComponentEvent);
SHEventHandle RemovePhysicsComponent (SHEventPtr removeComponentEvent); SHEventHandle RemovePhysicsComponent (SHEventPtr removeComponentEvent);
template <typename RP3DCollisionPair, typename = std::enable_if_t
<std::is_same_v<RP3DCollisionPair, rp3d::CollisionCallback::ContactPair>
|| std::is_same_v<RP3DCollisionPair, rp3d::OverlapCallback::OverlapPair>>>
SHCollisionEvent GenerateCollisionEvent (const RP3DCollisionPair& cp) noexcept;
}; };
} // namespace SHADE
/*-----------------------------------------------------------------------------------*/ #include "SHPhysicsSystem.hpp"
/* Event Data Definitions */
/*-----------------------------------------------------------------------------------*/
struct SHPhysicsColliderAddedEvent
{
EntityID entityID;
SHCollider::Type colliderType;
int colliderIndex;
};
struct SHPhysicsColliderRemovedEvent
{
EntityID entityID;
int colliderIndex;
};
} // namespace SHADE

View File

@ -0,0 +1,84 @@
/****************************************************************************************
* \file SHPhysicsSystem.hpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for templated functions the Physics System
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#pragma once
#include <type_traits>
// Primary Header
#include "SHPhysicsSystem.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
template <typename RP3DCollisionPair, typename Condition>
SHCollisionEvent SHPhysicsSystem::GenerateCollisionEvent(const RP3DCollisionPair& cp) noexcept
{
static const auto MATCH_COLLIDER = []
(
const SHPhysicsObject& physicsObject
, const rp3d::Entity colliderID
)->uint32_t
{
for (uint32_t i = 0; i < physicsObject.rp3dBody->getNbColliders(); ++i)
{
const auto* collider = physicsObject.rp3dBody->getCollider(i);
if (collider->getEntity() == colliderID)
return i;
}
return std::numeric_limits<uint32_t>::max();
};
SHCollisionEvent cInfo;
// Match body and collider for collision event
const rp3d::Entity body1 = cp.getBody1()->getEntity();
const rp3d::Entity body2 = cp.getBody2()->getEntity();
const rp3d::Entity collider1 = cp.getCollider1()->getEntity();
const rp3d::Entity collider2 = cp.getCollider2()->getEntity();
// Find and match both ids
bool matched[2] = { false, false };
for (auto& [entityID, physicsObject] : map)
{
// Match body 1
if (matched[SHCollisionEvent::ENTITY_A] == false && physicsObject.rp3dBody->getEntity() == body1)
{
cInfo.ids[SHCollisionEvent::ENTITY_A] = entityID;
cInfo.ids[SHCollisionEvent::COLLIDER_A] = MATCH_COLLIDER(physicsObject, collider1);
matched[SHCollisionEvent::ENTITY_A] = true;
}
// Match body 2
if (matched[SHCollisionEvent::ENTITY_B] == false && physicsObject.rp3dBody->getEntity() == body2)
{
cInfo.ids[SHCollisionEvent::ENTITY_B] = entityID;
cInfo.ids[SHCollisionEvent::COLLIDER_B] = MATCH_COLLIDER(physicsObject, collider2);
matched[SHCollisionEvent::ENTITY_B] = true;
}
if (matched[SHCollisionEvent::ENTITY_A] == true && matched[SHCollisionEvent::ENTITY_B] == true)
return cInfo;
}
// Update collision state
cInfo.collisionState = static_cast<SHCollisionEvent::State>(cp.getEventType());
return cInfo;
}
} // namespace SHADE

View File

@ -0,0 +1,93 @@
/****************************************************************************************
* \file SHPhysicsUtils.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for some Physics Utilities
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#include <SHpch.h>
// Primary Header
#include "SHPhysicsUtils.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHCollisionEvent::SHCollisionEvent() noexcept
: collisionState { State::INVALID }
{
ids[ENTITY_A] = MAX_EID;
ids[ENTITY_B] = MAX_EID;
ids[COLLIDER_A] = std::numeric_limits<uint32_t>::max();
ids[COLLIDER_B] = std::numeric_limits<uint32_t>::max();
}
SHCollisionEvent::SHCollisionEvent(EntityID entityA, EntityID entityB) noexcept
: collisionState { State::INVALID }
{
ids[ENTITY_A] = entityA;
ids[ENTITY_B] = entityB;
ids[COLLIDER_A] = std::numeric_limits<uint32_t>::max();
ids[COLLIDER_B] = std::numeric_limits<uint32_t>::max();
}
/*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/
bool SHCollisionEvent::operator==(const SHCollisionEvent& rhs) const noexcept
{
return value[0] == rhs.value[0] && value[1] == rhs.value[1];
}
bool SHCollisionEvent::operator!=(const SHCollisionEvent& rhs) const noexcept
{
return value[0] != rhs.value[0] || value[1] != rhs.value[1];
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
EntityID SHCollisionEvent::GetEntityA() const noexcept
{
return ids[ENTITY_A];
}
EntityID SHCollisionEvent::GetEntityB() const noexcept
{
return ids[ENTITY_B];
}
const SHRigidBodyComponent* SHCollisionEvent::GetRigidBodyA() const noexcept
{
return SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ids[ENTITY_A]);
}
const SHRigidBodyComponent* SHCollisionEvent::GetRigidBodyB() const noexcept
{
return SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ids[ENTITY_B]);
}
const SHCollider* SHCollisionEvent::GetColliderA() const noexcept
{
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_A])->GetCollider(ids[COLLIDER_A]);
}
const SHCollider* SHCollisionEvent::GetColliderB() const noexcept
{
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_B])->GetCollider(ids[COLLIDER_B]);
}
SHCollisionEvent::State SHCollisionEvent::GetCollisionState() const noexcept
{
return collisionState;
}
} // namespace SHADE

View File

@ -0,0 +1,116 @@
/****************************************************************************************
* \file SHPhysicsUtils.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for some Physics Utilities
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#pragma once
// Project Headers
#include "Components/SHColliderComponent.h"
#include "Components/SHRigidBodyComponent.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
struct SHPhysicsColliderAddedEvent
{
EntityID entityID;
SHCollider::Type colliderType;
int colliderIndex;
};
struct SHPhysicsColliderRemovedEvent
{
EntityID entityID;
int colliderIndex;
};
class SH_API SHCollisionEvent
{
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHPhysicsSystem;
public:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
enum class State
{
ENTER
, STAY
, EXIT
, TOTAL
, INVALID = -1
};
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHCollisionEvent () noexcept;
SHCollisionEvent (EntityID entityA, EntityID entityB) noexcept;
SHCollisionEvent (const SHCollisionEvent& rhs) = default;
SHCollisionEvent (SHCollisionEvent&& rhs) = default;
~SHCollisionEvent () = default;
/*---------------------------------------------------------------------------------*/
/* Operator Overloads */
/*---------------------------------------------------------------------------------*/
bool operator== (const SHCollisionEvent& rhs) const noexcept;
bool operator!= (const SHCollisionEvent& rhs) const noexcept;
SHCollisionEvent& operator= (const SHCollisionEvent& rhs) = default;
SHCollisionEvent& operator= (SHCollisionEvent&& rhs) = default;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] EntityID GetEntityA () const noexcept;
[[nodiscard]] EntityID GetEntityB () const noexcept;
[[nodiscard]] const SHRigidBodyComponent* GetRigidBodyA () const noexcept;
[[nodiscard]] const SHRigidBodyComponent* GetRigidBodyB () const noexcept;
[[nodiscard]] const SHCollider* GetColliderA () const noexcept;
[[nodiscard]] const SHCollider* GetColliderB () const noexcept;
[[nodiscard]] State GetCollisionState () const noexcept;
private:
static constexpr uint32_t ENTITY_A = 0;
static constexpr uint32_t ENTITY_B = 1;
static constexpr uint32_t COLLIDER_A = 2;
static constexpr uint32_t COLLIDER_B = 3;
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
union
{
uint64_t value[2]; // EntityValue, ColliderIndexValue
uint32_t ids [4]; // EntityA, EntityB, ColliderIndexA, ColliderIndexB
};
State collisionState;
};
} // namespace SHADE

View File

@ -21,6 +21,7 @@ of DigiPen Institute of Technology is prohibited.
#include "ECS.hxx" #include "ECS.hxx"
#include "Utility/Convert.hxx" #include "Utility/Convert.hxx"
#include "Scripts/ScriptStore.hxx" #include "Scripts/ScriptStore.hxx"
#include "Utility/Debug.hxx"
namespace SHADE namespace SHADE
{ {
@ -63,7 +64,13 @@ namespace SHADE
} }
bool GameObject::IsActiveInHierarchy::get() bool GameObject::IsActiveInHierarchy::get()
{ {
return true; // TODO: Update once we have an equivalent on the Entity object auto node = SHSceneManager::GetCurrentSceneGraph().GetNode(GetEntity());
if (!node)
{
Debug::LogWarning("Attempting to access a GameObject's ActiveInHierarchy state which does not exist. Assuming inactive.");
return false;
}
return node->IsActive();
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -667,14 +667,10 @@ namespace SHADE
bool ScriptStore::isEntityActive(Entity entity) bool ScriptStore::isEntityActive(Entity entity)
{ {
// Get native Entity // Invalid entity
SHEntity* nativeEntity = SHEntityManager::GetEntityByID(entity); if (!EntityUtils::IsValid(entity))
// Entity Validity Check
if (nativeEntity == nullptr)
return false; return false;
// Check active state return GameObject(entity).IsActiveInHierarchy;
return nativeEntity->GetActive();
} }
} }

View File

@ -0,0 +1,11 @@
using SHADE;
public class PrintWhenActive : Script
{
public PrintWhenActive(GameObject gameObj) : base(gameObj) { }
protected override void update()
{
Debug.Log("Active!");
}
}