SP3-2 Integrated Physics with a test scene #78

Merged
direnbharwani merged 16 commits from SP3-2-Physics into main 2022-10-01 22:17:23 +08:00
26 changed files with 2481 additions and 151 deletions

View File

@ -30,13 +30,14 @@ project "SHADE_Application"
externalincludedirs externalincludedirs
{ {
"%{IncludeDir.spdlog}/include", "%{IncludeDir.RTTR}\\include",
"%{IncludeDir.VULKAN}/include",
"%{IncludeDir.VMA}/include",
"%{IncludeDir.VULKAN}/Source/SPIRV-Reflect",
"%{IncludeDir.tinyddsloader}",
"%{IncludeDir.fmod}/include", "%{IncludeDir.fmod}/include",
"%{IncludeDir.RTTR}\\include" "%{IncludeDir.VULKAN}/Source/SPIRV-Reflect",
"%{IncludeDir.VMA}/include",
"%{IncludeDir.VULKAN}/include",
"%{IncludeDir.spdlog}/include",
"%{IncludeDir.tinyddsloader}",
"%{IncludeDir.reactphysics3d}\\include"
} }
externalwarnings "Off" externalwarnings "Off"
@ -57,7 +58,7 @@ project "SHADE_Application"
libdirs libdirs
{ {
"%{IncludeDir.spdlog}/lib", "%{IncludeDir.spdlog}/lib",
"%{IncludeDir.SDL}/lib", "%{IncludeDir.SDL}/lib"
} }
defines defines

View File

@ -16,19 +16,28 @@
#include <ctime> #include <ctime>
#include <SDL.h> #include <SDL.h>
#include "Scripting/SHScriptEngine.h"
#include "Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h" #include "Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h"
// Managers
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
// Systems
#include "Scripting/SHScriptEngine.h"
#include "Physics/SHPhysicsSystem.h"
#include "Math/Transform/SHTransformSystem.h" #include "Math/Transform/SHTransformSystem.h"
#include "Input/SHInputManager.h" #include "Input/SHInputManager.h"
#include "FRC/SHFramerateController.h" #include "FRC/SHFramerateController.h"
#include "AudioSystem/SHAudioSystem.h" #include "AudioSystem/SHAudioSystem.h"
#include "Scenes/SBTestScene.h" // Components
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Scenes/SBTestScene.h"
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
@ -54,7 +63,7 @@ namespace Sandbox
// Create Systems // Create Systems
SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>();
SHADE::SHSystemManager::CreateSystem<SHADE::SHScriptEngine>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHScriptEngine>();
// TODO(Diren): Create Physics System here SHADE::SHSystemManager::CreateSystem<SHADE::SHPhysicsSystem>();
SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>();
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>()); SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
SHADE::SHSystemManager::CreateSystem<SHADE::SHAudioSystem>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHAudioSystem>();
@ -65,18 +74,21 @@ namespace Sandbox
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::LateUpdateRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::LateUpdateRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameCleanUpRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameCleanUpRoutine>();
// TODO(Diren): Register Physics System & Routines here SHADE::SHSystemManager::RegisterRoutine<SHADE::SHPhysicsSystem, SHADE::SHPhysicsSystem::PhysicsPreUpdate>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHPhysicsSystem, SHADE::SHPhysicsSystem::PhysicsFixedUpdate>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHPhysicsSystem, SHADE::SHPhysicsSystem::PhysicsPostUpdate>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHTransformSystem, SHADE::SHTransformSystem::TransformUpdateRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHTransformSystem, SHADE::SHTransformSystem::TransformUpdateRoutine>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BatcherDispatcherRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BatcherDispatcherRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BeginRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BeginRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::RenderRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::RenderRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::EndRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::EndRoutine>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>(); SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRigidBodyComponent>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHColliderComponent>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>(); SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>();
//TODO: REMOVE AFTER PRESENTATION //TODO: REMOVE AFTER PRESENTATION
//SHADE::SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf"); //SHADE::SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf");

View File

@ -10,6 +10,8 @@
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Physics/Components/SHRigidBodyComponent.h"
#include "Physics/Components/SHColliderComponent.h"
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
@ -18,9 +20,9 @@ using namespace SHADE;
namespace Sandbox namespace Sandbox
{ {
void SBTestScene::WindowFocusFunc([[maybe_unused]]void* window, int focused) void SBTestScene::WindowFocusFunc([[maybe_unused]] void* window, int focused)
{ {
if(focused) if (focused)
{ {
} }
else else
@ -75,34 +77,35 @@ namespace Sandbox
customMat->SetProperty("data.alpha", 0.1f); customMat->SetProperty("data.alpha", 0.1f);
// Create Stress Test Objects // Create Stress Test Objects
static const SHVec3 TEST_OBJ_SCALE = { 0.05f, 0.05f, 0.05f }; static const SHVec3 TEST_OBJ_SCALE = SHVec3::One * 0.5f;
constexpr int NUM_ROWS = 100; constexpr int NUM_ROWS = 10;
constexpr int NUM_COLS = 100; constexpr int NUM_COLS = 10;
static const SHVec3 TEST_OBJ_SPACING = { 0.05f, 0.05f, 0.05f }; static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f };
static const SHVec3 TEST_OBJ_START_POS = { - (NUM_COLS / 2 * TEST_OBJ_SPACING.x ) + 1.0f, -2.0f, -1.0f }; static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f };
for (int y = 0; y < NUM_ROWS; ++y) for (int y = 0; y < NUM_ROWS; ++y)
for (int x = 0; x < NUM_COLS; ++x) for (int x = 0; x < NUM_COLS; ++x)
{ {
auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>(); auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent, SHRigidBodyComponent, SHColliderComponent>();
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity); auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity);
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity); auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity);
auto& collider = *SHComponentManager::GetComponent_s<SHColliderComponent>(entity);
renderable.Mesh = handles.front(); //renderable.Mesh = handles.front();
renderable.Mesh = CUBE_MESH;
renderable.SetMaterial(customMat); renderable.SetMaterial(customMat);
if (y == 50) if (y == 50)
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 0.0f, 0.0f, 1.0f)); renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 0.0f, 0.0f, 1.0f));
//Set initial positions //Set initial positions
transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f)});
x * TEST_OBJ_SPACING.x,
y * TEST_OBJ_SPACING.y,
0.0f
});
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f}); //transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
//transform.SetWorldRotation(3.14159265f * 1.5f, -3.14159265f / 2.0f, 0.0f); transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber());
transform.SetLocalScale(TEST_OBJ_SCALE); transform.SetWorldScale(TEST_OBJ_SCALE);
auto* box = collider.AddBoundingBox();
box->SetHalfExtents(transform.GetWorldScale() * 0.5f);
stressTestObjects.emplace_back(entity); stressTestObjects.emplace_back(entity);
} }
@ -115,27 +118,36 @@ namespace Sandbox
renderable.SetMaterial(customMat); renderable.SetMaterial(customMat);
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f)); renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f); renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
renderable.GetModifiableMaterial()->SetProperty("data.textureIndex", 0); renderable.GetModifiableMaterial()->SetProperty("data.textureIndex", 1);
transform.SetWorldPosition ({-3.0f, -1.0f, -1.0f}); transform.SetWorldPosition({ -3.0f, -1.0f, -1.0f });
transform.SetLocalScale({5.0f, 5.0f, 5.0f}); transform.SetLocalScale({ 5.0f, 5.0f, 5.0f });
//auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>(); auto floor = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent, SHRigidBodyComponent, SHColliderComponent>();
//auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity); auto& floorRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(floor);
//auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity); auto& floorTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(floor);
auto& floorRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(floor);
auto& floorCollider = *SHComponentManager::GetComponent_s<SHColliderComponent>(floor);
//renderable.Mesh = handles.back(); floorRenderable.Mesh = CUBE_MESH;
//renderable.SetMaterial(customMat); floorRenderable.SetMaterial(customMat);
floorRenderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
//transform.SetLocalScale(TEST_OBJ_SCALE); floorTransform.SetWorldScale({7.5f, 0.5f, 7.5});
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f}); floorTransform.SetWorldPosition({0.0f, -3.0f, -5.0f});
floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC);
auto* floorBox = floorCollider.AddBoundingBox();
floorBox->SetHalfExtents(floorTransform.GetWorldScale() * 0.5f);
// Create blank entity with a script // Create blank entity with a script
//testObj = SHADE::SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>(); //testObj = SHADE::SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
//auto& testObjRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(testObj); //auto& testObjRenderable = *SHComponentManager::GetComponent<SHRenderable>(testObj);
//testObjRenderable.Mesh = CUBE_MESH; //testObjRenderable.Mesh = CUBE_MESH;
//testObjRenderable.SetMaterial(matInst); //testObjRenderable.SetMaterial(matInst);
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>()); SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
scriptEngine->AddScript(raccoonSpin, "RaccoonSpin"); scriptEngine->AddScript(raccoonSpin, "RaccoonSpin");
@ -147,7 +159,7 @@ namespace Sandbox
renderableShowcase.SetMaterial(customMat); renderableShowcase.SetMaterial(customMat);
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f)); renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f); renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 0); renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 1);
transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f }); transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f });
transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f }); transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f });
@ -186,8 +198,4 @@ namespace Sandbox
{ {
//SHSerialization::SerializeScene("resources/scenes/Scene01.SHADE"); //SHSerialization::SerializeScene("resources/scenes/Scene01.SHADE");
} }
} }

View File

@ -57,7 +57,7 @@ project "SHADE_Engine"
"%{IncludeDir.RTTR}/lib", "%{IncludeDir.RTTR}/lib",
"%{IncludeDir.SDL}/lib", "%{IncludeDir.SDL}/lib",
"%{IncludeDir.spdlog}/lib", "%{IncludeDir.spdlog}/lib",
"%{IncludeDir.fmod}/lib", "%{IncludeDir.fmod}/lib"
} }
links links

View File

@ -8,23 +8,19 @@ namespace SHADE
{ {
class SHFixedSystemRoutine: public SHSystemRoutine class SHFixedSystemRoutine: public SHSystemRoutine
{ {
private: protected:
double accumulatedTime; double accumulatedTime;
double fixedTimeStep; double fixedTimeStep;
protected:
SHFixedSystemRoutine(double timeStep = DEFAULT_FIXED_STEP, std::string routineName = "Default Fixed Routine Name", bool editorPause = false) SHFixedSystemRoutine(double timeStep = DEFAULT_FIXED_STEP, std::string routineName = "Default Fixed Routine Name", bool editorPause = false)
:SHSystemRoutine(routineName, editorPause), accumulatedTime(0.0), fixedTimeStep(timeStep){} :SHSystemRoutine(routineName, editorPause), accumulatedTime(0.0), fixedTimeStep(timeStep){}
public: public:
~SHFixedSystemRoutine() = default; ~SHFixedSystemRoutine() = default;
virtual void Execute(double dt) noexcept; virtual void Execute(double dt) noexcept override;
virtual void FixedExecute(double dt) noexcept {};
virtual void FixedExecute(double dt) noexcept {}
}; };

View File

@ -21,7 +21,7 @@ namespace SHADE
/* Constructors & Destructor Definitions */ /* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHBoundingBox::SHBoundingBox(const SHVec3& c, SHVec3& hE) noexcept SHBoundingBox::SHBoundingBox(const SHVec3& c, const SHVec3& hE) noexcept
: SHShape {} : SHShape {}
, center { c } , center { c }
, halfExtents { hE } , halfExtents { hE }

View File

@ -10,6 +10,8 @@
#pragma once #pragma once
#include <DirectXCollision.h>
// Project Headers // Project Headers
#include "SHShape.h" #include "SHShape.h"
#include "SH_API.h" #include "SH_API.h"
@ -20,6 +22,7 @@ namespace SHADE
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
// TODO(Diren): Use DirectX BoundingBox instead of custom
class SH_API SHBoundingBox : public SHShape class SH_API SHBoundingBox : public SHShape
{ {
public: public:
@ -27,7 +30,7 @@ namespace SHADE
/* Constructors & Destructor */ /* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHBoundingBox (const SHVec3& center, SHVec3& halfExtents) noexcept; SHBoundingBox (const SHVec3& center, const SHVec3& halfExtents) noexcept;
SHBoundingBox (const SHVec3* vertices, size_t numVertices) noexcept; SHBoundingBox (const SHVec3* vertices, size_t numVertices) noexcept;
SHBoundingBox (const SHBoundingBox* boxes, size_t numBoxes) noexcept; SHBoundingBox (const SHBoundingBox* boxes, size_t numBoxes) noexcept;

View File

@ -23,4 +23,14 @@ namespace SHADE
: type { Type::NONE } : type { Type::NONE }
{} {}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
SHShape::Type SHShape::GetType() const
{
return type;
}
} // namespace SHADE } // namespace SHADE

View File

@ -30,7 +30,9 @@ namespace SHADE
enum class Type enum class Type
{ {
BOUNDING_BOX BOUNDING_BOX
, RAY , SPHERE
, CAPSULE
, CONVEX_HULL
, TRIANGLE , TRIANGLE
, COUNT , COUNT

View File

@ -103,6 +103,9 @@ namespace SHADE
template <IsArithmetic T> template <IsArithmetic T>
T SHMath::GenerateRandomNumber(T lowerBound, T upperBound) T SHMath::GenerateRandomNumber(T lowerBound, T upperBound)
{ {
if (lowerBound > upperBound)
std::swap(lowerBound, upperBound);
if constexpr (IsIntegral<T>) if constexpr (IsIntegral<T>)
{ {
std::uniform_int_distribution<T> distribution(lowerBound, upperBound); std::uniform_int_distribution<T> distribution(lowerBound, upperBound);
@ -120,7 +123,7 @@ namespace SHADE
bool SHMath::CompareFloat(T lhs, T rhs, T absTolerance, T relTolerance) bool SHMath::CompareFloat(T lhs, T rhs, T absTolerance, T relTolerance)
{ {
const T RTOL = relTolerance * Max(std::fabs(lhs), std::fabs(rhs)); const T RTOL = relTolerance * Max(std::fabs(lhs), std::fabs(rhs));
return std::fabs(lhs - rhs) <= MAX(absTolerance, RTOL); return std::fabs(lhs - rhs) <= Max(absTolerance, RTOL);
} }
} // namespace SHADE } // namespace SHADE

View File

@ -15,6 +15,7 @@
// Project Headers // Project Headers
#include "Vector/SHVec3.h" #include "Vector/SHVec3.h"
#include "SHMatrix.h" #include "SHMatrix.h"
#include "SHMathHelpers.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
using namespace DirectX; using namespace DirectX;
@ -249,9 +250,30 @@ namespace SHADE
SHVec3 SHQuaternion::ToEuler() const noexcept SHVec3 SHQuaternion::ToEuler() const noexcept
{ {
// TODO (Diren) const float xx = x * x;
const float yy = y * y;
const float zz = z * z;
return SHVec3::Zero; const float m31 = 2.f * x * z + 2.f * y * w;
const float m32 = 2.f * y * z - 2.f * x * w;
const float m33 = 1.f - 2.f * xx - 2.f * yy;
const float cy = sqrtf(m33 * m33 + m31 * m31);
const float cx = atan2f(-m32, cy);
if (cy > 16.0f * SHMath::EPSILON)
{
const float m12 = 2.f * x * y + 2.f * z * w;
const float m22 = 1.f - 2.f * xx - 2.f * zz;
return SHVec3(cx, atan2f(m31, m33), atan2f(m12, m22));
}
else
{
const float m11 = 1.f - 2.f * yy - 2.f * zz;
const float m21 = 2.f * x * y - 2.f * z * w;
return SHVec3(cx, 0.f, atan2f(-m21, m11));
}
} }
std::string SHQuaternion::ToString() const noexcept std::string SHQuaternion::ToString() const noexcept

View File

@ -24,43 +24,6 @@ namespace SHADE
, dirty { true } , dirty { true }
{} {}
SHTransformComponent::SHTransformComponent(const SHTransformComponent& rhs) noexcept
: SHComponent {}
, dirty { true }
, local { rhs.local }
, world { rhs.world }
{}
SHTransformComponent::SHTransformComponent(SHTransformComponent&& rhs) noexcept
: SHComponent {}
, dirty { true }
, local { std::move(rhs.local) }
, world { std::move(rhs.world) }
{}
/*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/
SHTransformComponent& SHTransformComponent::operator=(const SHTransformComponent& rhs) noexcept
{
dirty = true;
local = rhs.local;
world = rhs.world;
return *this;
}
SHTransformComponent& SHTransformComponent::operator=(SHTransformComponent&& rhs) noexcept
{
dirty = true;
local = std::move(rhs.local);
world = std::move(rhs.world);
return *this;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */ /* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -189,7 +152,7 @@ RTTR_REGISTRATION
using namespace rttr; using namespace rttr;
registration::class_<SHTransformComponent>("Transform Component") registration::class_<SHTransformComponent>("Transform Component")
.property("Translate", &SHTransformComponent::GetLocalPosition, &SHTransformComponent::SetLocalPosition) .property("Translate" , &SHTransformComponent::GetLocalPosition , &SHTransformComponent::SetLocalPosition )
.property("Rotate", &SHTransformComponent::GetLocalRotation, select_overload<void(SHVec3 const&)>(&SHTransformComponent::SetLocalRotation)) .property("Rotate" , &SHTransformComponent::GetLocalRotation , select_overload<void(SHVec3 const&)>(&SHTransformComponent::SetLocalRotation) )
.property("Scale", &SHTransformComponent::GetLocalScale, &SHTransformComponent::SetLocalScale); .property("Scale" , &SHTransformComponent::GetLocalScale , &SHTransformComponent::SetLocalScale );
} }

View File

@ -13,6 +13,7 @@
#include <queue> #include <queue>
#include <rttr/registration> #include <rttr/registration>
// Project Headers // Project Headers
#include "SH_API.h" #include "SH_API.h"
#include "ECS_Base/Components/SHComponent.h" #include "ECS_Base/Components/SHComponent.h"
@ -41,15 +42,15 @@ namespace SHADE
~SHTransformComponent () override = default; ~SHTransformComponent () override = default;
SHTransformComponent () noexcept; SHTransformComponent () noexcept;
SHTransformComponent (const SHTransformComponent& rhs) noexcept; SHTransformComponent (const SHTransformComponent& rhs) noexcept = default;
SHTransformComponent (SHTransformComponent&& rhs) noexcept; SHTransformComponent (SHTransformComponent&& rhs) noexcept = default;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Operator Overloads */ /* Operator Overloads */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHTransformComponent& operator=(const SHTransformComponent& rhs) noexcept; SHTransformComponent& operator=(const SHTransformComponent& rhs) noexcept = default;
SHTransformComponent& operator=(SHTransformComponent&& rhs) noexcept; SHTransformComponent& operator=(SHTransformComponent&& rhs) noexcept = default;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */

View File

@ -0,0 +1,149 @@
/****************************************************************************************
* \file SHColliderComponent.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a Collider Component.
*
* \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 "SHColliderComponent.h"
// Project Headers
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Physics/SHPhysicsSystem.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHColliderComponent::SHColliderComponent() noexcept
: system { nullptr }
{}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
const SHVec3& SHColliderComponent::GetPosition() const noexcept
{
return position;
}
const SHQuaternion& SHColliderComponent::GetOrientation() const noexcept
{
return orientation;
}
SHVec3 SHColliderComponent::GetRotation() const noexcept
{
return orientation.ToEuler();
}
const SHColliderComponent::Colliders& SHColliderComponent::GetColliders() const noexcept
{
return colliders;
}
SHCollider& SHColliderComponent::GetCollider(int index)
{
if (index < 0 || static_cast<size_t>(index) >= colliders.size())
throw std::invalid_argument("Out-of-range access!");
return colliders[index].first;
}
/*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
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() noexcept
{
const auto TYPE = SHCollider::Type::BOX;
const auto BOX_PAIR = std::make_pair(SHCollider{TYPE}, true);
auto& collider = colliders.emplace_back(BOX_PAIR).first;
if (!system)
{
SHLOG_ERROR("Physics system does not exist, unable to add Box Collider!")
return nullptr;
}
// Notify Physics System
system->AddCollisionShape(GetEID(), collider.GetShape());
return reinterpret_cast<SHBoundingBox*>(collider.GetShape());
}
//void SHColliderComponent::AddSphere() noexcept
//{
// const auto TYPE = SHCollider::Type::SPHERE;
// if (!system)
// {
// SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!")
// return;
// }
// // Notify Physics System
//}
void SHColliderComponent::RemoveCollider(int index)
{
if (index < 0 || static_cast<size_t>(index) >= colliders.size())
throw std::invalid_argument("Out-of-range access!");
int idx = 0;
auto it = colliders.begin();
for (; it != colliders.end(); ++it)
{
if (idx == index)
break;
++idx;
}
it = colliders.erase(it);
// Notify Physics System
if (!system)
{
SHLOG_ERROR("Physics system does not exist, unable to remove Collider!")
return;
}
system->RemoveCollisionShape(GetEID(), index);
}
} // namespace SHADE

View File

@ -0,0 +1,96 @@
/****************************************************************************************
* \file SHColliderComponent.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a Collider Component.
*
* \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 <rttr/registration>
// Project Headers
#include "ECS_Base/Components/SHComponent.h"
#include "Physics/SHCollider.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHColliderComponent : public SHComponent
{
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHPhysicsSystem;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
using ColliderDirtyPair = std::pair<SHCollider, bool>;
using Colliders = std::vector<ColliderDirtyPair>;
public:
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHColliderComponent () noexcept;
SHColliderComponent (const SHColliderComponent& rhs) noexcept = default;
SHColliderComponent (SHColliderComponent&& rhs) noexcept = default;
~SHColliderComponent () override = default;
/*---------------------------------------------------------------------------------*/
/* Operator Overloads */
/*---------------------------------------------------------------------------------*/
SHColliderComponent& operator=(const SHColliderComponent& rhs) noexcept = default;
SHColliderComponent& operator=(SHColliderComponent&& rhs) noexcept = default;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] bool HasChanged () const noexcept;
[[nodiscard]] const SHVec3& GetPosition () const noexcept;
[[nodiscard]] const SHQuaternion& GetOrientation () const noexcept;
[[nodiscard]] SHVec3 GetRotation () const noexcept;
[[nodiscard]] const Colliders& GetColliders () const noexcept;
[[nodiscard]] SHCollider& GetCollider (int index);
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
void OnCreate () override;
void OnDestroy () override;
SHBoundingBox* AddBoundingBox () noexcept;
void RemoveCollider (int index);
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
SHPhysicsSystem* system;
SHVec3 position;
SHQuaternion orientation;
Colliders colliders;
};
} // namespace SHADE

View File

@ -0,0 +1,406 @@
/****************************************************************************************
* \file SHRigidBodyComponent.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a Rigidbody Component.
*
* \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 "SHRigidBodyComponent.h"
// Project Headers
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Physics/SHPhysicsSystem.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHRigidBodyComponent::SHRigidBodyComponent() noexcept
: type { Type::DYNAMIC }
, flags { 0 }
, dirtyFlags { 0 }
, interpolate { true }
, system { nullptr }
, mass { 1.0f }
, drag { 0.01f }
, angularDrag { 0.01f }
{
// Set default flags: Gravity & Sleeping enabled
flags |= 1U << 0;
flags |= 1U << 1;
// Set all dirty flags to true
dirtyFlags = 1023;
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
bool SHRigidBodyComponent::IsGravityEnabled() const noexcept
{
return flags & (1U << 0);
}
bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept
{
return flags & (1U << 1);
}
bool SHRigidBodyComponent::IsInterpolating() const noexcept
{
return interpolate;
}
SHRigidBodyComponent::Type SHRigidBodyComponent::GetType() const noexcept
{
return type;
}
float SHRigidBodyComponent::GetMass() const noexcept
{
return mass;
}
float SHRigidBodyComponent::GetDrag() const noexcept
{
return drag;
}
float SHRigidBodyComponent::GetAngularDrag() const noexcept
{
return angularDrag;
}
bool SHRigidBodyComponent::GetFreezePositionX() const noexcept
{
return flags & (1U << 2);
}
bool SHRigidBodyComponent::GetFreezePositionY() const noexcept
{
return flags & (1U << 3);
}
bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept
{
return flags & (1U << 4);
}
bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept
{
return flags & (1U << 5);
}
bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept
{
return flags & (1U << 6);
}
bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept
{
return flags & (1U << 7);
}
const SHVec3& SHRigidBodyComponent::GetForce() const noexcept
{
return force;
}
const SHVec3& SHRigidBodyComponent::GetTorque() const noexcept
{
return torque;
}
const SHVec3& SHRigidBodyComponent::GetLinearVelocity() const noexcept
{
return linearVelocity;
}
const SHVec3& SHRigidBodyComponent::GetAngularVelocity() const noexcept
{
return angularVelocity;
}
const SHVec3& SHRigidBodyComponent::GetPosition() const noexcept
{
return position;
}
const SHQuaternion& SHRigidBodyComponent::GetOrientation() const noexcept
{
return orientation;
}
SHVec3 SHRigidBodyComponent::GetRotation() const noexcept
{
return orientation.ToEuler();
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHRigidBodyComponent::SetType(Type newType) noexcept
{
if (type == newType)
return;
dirtyFlags |= 1U << 4;
type = newType;
}
void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept
{
constexpr int FLAG_POS = 0;
dirtyFlags |= 1U << FLAG_POS;
enableGravity ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
}
void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept
{
constexpr int FLAG_POS = 1;
dirtyFlags |= 1U << 1;
isAllowedToSleep ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
}
void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept
{
constexpr int FLAG_POS = 2;
dirtyFlags |= 1U << 2;
freezePositionX ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
}
void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept
{
constexpr int FLAG_POS = 3;
dirtyFlags |= 1U << 2;
freezePositionY ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
}
void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept
{
constexpr int FLAG_POS = 4;
dirtyFlags |= 1U << 2;
freezePositionZ ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
}
void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept
{
constexpr int FLAG_POS = 5;
dirtyFlags |= 1U << 3;
freezeRotationX ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
}
void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept
{
constexpr int FLAG_POS = 6;
dirtyFlags |= 1U << 3;
freezeRotationY ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
}
void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept
{
constexpr int FLAG_POS = 7;
dirtyFlags |= 1U << 3;
freezeRotationZ ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
}
void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept
{
interpolate = allowInterpolation;
}
void SHRigidBodyComponent::SetMass(float newMass) noexcept
{
dirtyFlags |= 1U << 5;
mass = newMass;
}
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
{
dirtyFlags |= 1U << 6;
drag = newDrag;
}
void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept
{
dirtyFlags |= 1U << 7;
angularDrag = newAngularDrag;
}
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
{
dirtyFlags |= 1U << 8;
linearVelocity = newLinearVelocity;
}
void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
{
dirtyFlags |= 1U << 9;
angularVelocity = newAngularVelocity;
}
/*-----------------------------------------------------------------------------------*/
/* 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)
{
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
return;
}
// Notify Physics Systems
system->AddForce(GetEID(), force);
}
void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept
{
if (!system)
{
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
return;
}
// Notify Physics Systems
system->AddForceAtLocalPos(GetEID(), force, localPos);
}
void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept
{
if (!system)
{
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
return;
}
// Notify Physics Systems
system->AddForceAtWorldPos(GetEID(), force, worldPos);
}
void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept
{
if (!system)
{
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
return;
}
// Notify Physics Systems
system->AddRelativeForce(GetEID(), force);
}
void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept
{
if (!system)
{
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
return;
}
// Notify Physics Systems
system->AddRelativeForceAtLocalPos(GetEID(), force, localPos);
}
void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept
{
if (!system)
{
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
return;
}
// Notify Physics Systems
system->AddRelativeForceAtWorldPos(GetEID(), force, worldPos);
}
void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept
{
if (!system)
{
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
return;
}
// Notify Physics Systems
system->AddTorque(GetEID(), torque);
}
void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept
{
if (!system)
{
SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!")
return;
}
// Notify Physics Systems
system->AddRelativeTorque(GetEID(), relativeTorque);
}
} // namespace SHADE
RTTR_REGISTRATION
{
using namespace SHADE;
using namespace rttr;
registration::class_<SHRigidBodyComponent>("RigidBody Component")
.property("Type" , &SHRigidBodyComponent::GetType , &SHRigidBodyComponent::SetType )
.property("Mass" , &SHRigidBodyComponent::GetMass , &SHRigidBodyComponent::SetMass )
.property("Drag" , &SHRigidBodyComponent::GetDrag , &SHRigidBodyComponent::SetDrag )
.property("Angular Drag" , &SHRigidBodyComponent::GetAngularDrag , &SHRigidBodyComponent::SetAngularDrag )
.property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetGravityEnabled )
.property("Interpolate" , &SHRigidBodyComponent::IsInterpolating , &SHRigidBodyComponent::SetInterpolate )
.property("Freeze Position X" , &SHRigidBodyComponent::GetFreezePositionX , &SHRigidBodyComponent::SetFreezePositionX )
.property("Freeze Position Y" , &SHRigidBodyComponent::GetFreezePositionY , &SHRigidBodyComponent::SetFreezePositionY )
.property("Freeze Position Z" , &SHRigidBodyComponent::GetFreezePositionZ , &SHRigidBodyComponent::SetFreezePositionZ )
.property("Freeze Rotation X" , &SHRigidBodyComponent::GetFreezeRotationX , &SHRigidBodyComponent::SetFreezeRotationX )
.property("Freeze Rotation Y" , &SHRigidBodyComponent::GetFreezeRotationY , &SHRigidBodyComponent::SetFreezeRotationY )
.property("Freeze Rotation Z" , &SHRigidBodyComponent::GetFreezeRotationZ , &SHRigidBodyComponent::SetFreezeRotationZ );
}

View File

@ -0,0 +1,171 @@
/****************************************************************************************
* \file SHRigidBodyComponent.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a Rigidbody Component.
*
* \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 <rttr/registration>
// Project Headers
#include "ECS_Base/Components/SHComponent.h"
#include "Physics/SHPhysicsObject.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHRigidBodyComponent : public SHComponent
{
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHPhysicsSystem;
public:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
enum class Type
{
STATIC
, KINEMATIC
, DYNAMIC
, COUNT
};
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHRigidBodyComponent () noexcept;
SHRigidBodyComponent (const SHRigidBodyComponent& rhs) noexcept = default;
SHRigidBodyComponent (SHRigidBodyComponent&& rhs) noexcept = default;
~SHRigidBodyComponent () override = default;
/*---------------------------------------------------------------------------------*/
/* Operator Overloads */
/*---------------------------------------------------------------------------------*/
SHRigidBodyComponent& operator=(const SHRigidBodyComponent& rhs) noexcept = default;
SHRigidBodyComponent& operator=(SHRigidBodyComponent&& rhs) noexcept = default;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] bool IsGravityEnabled () const noexcept;
[[nodiscard]] bool IsAllowedToSleep () const noexcept;
[[nodiscard]] bool IsInterpolating () const noexcept;
[[nodiscard]] Type GetType () const noexcept;
[[nodiscard]] float GetMass () const noexcept;
[[nodiscard]] float GetDrag () const noexcept;
[[nodiscard]] float GetAngularDrag () const noexcept;
[[nodiscard]] bool GetFreezePositionX () const noexcept;
[[nodiscard]] bool GetFreezePositionY () const noexcept;
[[nodiscard]] bool GetFreezePositionZ () const noexcept;
[[nodiscard]] bool GetFreezeRotationX () const noexcept;
[[nodiscard]] bool GetFreezeRotationY () const noexcept;
[[nodiscard]] bool GetFreezeRotationZ () const noexcept;
[[nodiscard]] const SHVec3& GetForce () const noexcept;
[[nodiscard]] const SHVec3& GetTorque () const noexcept;
[[nodiscard]] const SHVec3& GetLinearVelocity () const noexcept;
[[nodiscard]] const SHVec3& GetAngularVelocity () const noexcept;
[[nodiscard]] const SHVec3& GetPosition () const noexcept;
[[nodiscard]] const SHQuaternion& GetOrientation () const noexcept;
[[nodiscard]] SHVec3 GetRotation () const noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetType (Type newType) noexcept;
void SetGravityEnabled (bool enableGravity) noexcept;
void SetIsAllowedToSleep(bool isAllowedToSleep) noexcept;
void SetFreezePositionX (bool freezePositionX) noexcept;
void SetFreezePositionY (bool freezePositionY) noexcept;
void SetFreezePositionZ (bool freezePositionZ) noexcept;
void SetFreezeRotationX (bool freezeRotationX) noexcept;
void SetFreezeRotationY (bool freezeRotationY) noexcept;
void SetFreezeRotationZ (bool freezeRotationZ) noexcept;
void SetInterpolate (bool allowInterpolation) noexcept;
void SetMass (float newMass) noexcept;
void SetDrag (float newDrag) noexcept;
void SetAngularDrag (float newAngularDrag) noexcept;
void SetLinearVelocity (const SHVec3& newLinearVelocity) noexcept;
void SetAngularVelocity (const SHVec3& newAngularVelocity) noexcept;
/*---------------------------------------------------------------------------------*/
/* 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;
void AddRelativeForce (const SHVec3& relativeForce) const noexcept;
void AddRelativeForceAtLocalPos (const SHVec3& relativeForce, const SHVec3& localPos) const noexcept;
void AddRelativeForceAtWorldPos (const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept;
void AddTorque (const SHVec3& torque) const noexcept;
void AddRelativeTorque (const SHVec3& relativeTorque) const noexcept;
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
Type type;
// rX rY rZ pX pY pZ slp g
uint8_t flags;
// 0 0 0 0 0 0 aV lV aD d m t ag lc slp g
uint16_t dirtyFlags;
bool interpolate;
SHPhysicsSystem* system;
float mass;
float drag;
float angularDrag;
SHVec3 force;
SHVec3 linearVelocity;
SHVec3 torque;
SHVec3 angularVelocity;
// TODO(Diren): Once quaternions have replaced euler angles in transforms, store it for the rigidbody.
SHVec3 position;
SHQuaternion orientation;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
RTTR_ENABLE()
};
} // namespace SHADE

View File

@ -0,0 +1,215 @@
/****************************************************************************************
* \file SHCollider.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a Collider.
*
* \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 "SHCollider.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHCollider::SHCollider(Type colliderType)
: type { colliderType }
, isTrigger { false }
, dirty { true }
, shape { nullptr }
{
CreateShape();
}
SHCollider::SHCollider(const SHCollider& rhs) noexcept
: type { rhs.type}
, isTrigger { rhs.isTrigger }
, dirty { true }
, shape { nullptr }
{
CreateShape();
// TODO(Diren): Copy transform data over
}
SHCollider::SHCollider(SHCollider&& rhs) noexcept
: type { rhs.type}
, isTrigger { rhs.isTrigger }
, dirty { true }
, shape { nullptr }
{
CreateShape();
// TODO(Diren): Copy transform data over
}
SHCollider::~SHCollider() noexcept
{
delete shape;
}
/*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/
SHCollider& SHCollider::operator=(const SHCollider& rhs) noexcept
{
type = rhs.type;
isTrigger = rhs.isTrigger;
dirty = true;
CreateShape();
// TODO(Diren): Copy transform data over
return *this;
}
SHCollider& SHCollider::operator=(SHCollider&& rhs) noexcept
{
type = rhs.type;
isTrigger = rhs.isTrigger;
dirty = true;
CreateShape();
// TODO(Diren): Copy transform data over
return *this;
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
bool SHCollider::HasChanged() const noexcept
{
return dirty;
}
bool SHCollider::IsTrigger() const noexcept
{
return isTrigger;
}
SHCollider::Type SHCollider::GetType() const noexcept
{
return type;
}
SHShape* SHCollider::GetShape() const noexcept
{
return shape;
}
float SHCollider::GetFriction() const noexcept
{
// TODO(Diren): Fix after implementing materials
return 0.0f;
}
float SHCollider::GetBounciness() const noexcept
{
// TODO(Diren): Fix after implementing materials
return 0.0f;
}
float SHCollider::GetDensity() const noexcept
{
// TODO(Diren): Fix after implementing materials
return 0.0f;
}
SHVec3 SHCollider::GetPosition() const noexcept
{
// TODO(Diren): Fix after linking transform data
return SHVec3::Zero;
}
const SHVec3& SHCollider::GetPositionOffset() const noexcept
{
return positionOffset;
}
SHQuaternion SHCollider::GetOrientation() const noexcept
{
// TODO(Diren): Fix after linking transform data
return SHQuaternion::Identity;
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHCollider::SetType(Type newType) noexcept
{
if (type == newType)
return;
dirty = true;
type = newType;
CreateShape();
}
void SHCollider::SetIsTrigger(bool trigger) noexcept
{
dirty = true;
isTrigger = trigger;
}
void SHCollider::SetFriction(float friction) noexcept
{
dirty = true;
}
void SHCollider::SetBounciness(float bounciness) noexcept
{
dirty = true;
}
void SHCollider::SetDensity(float density) noexcept
{
dirty = true;
}
void SHCollider::SetPositionOffset(const SHVec3& posOffset) noexcept
{
dirty = true;
positionOffset = posOffset;
}
/*-----------------------------------------------------------------------------------*/
/* Private Member Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHCollider::CreateShape()
{
// Remove current shape
delete shape;
switch (type)
{
case Type::BOX: CreateBoundingBox(); break;
case Type::SPHERE: CreateSphere(); break;
default: break;
}
}
void SHCollider::CreateBoundingBox()
{
shape = new SHBoundingBox{ SHVec3::Zero, SHVec3::One };
}
void SHCollider::CreateSphere()
{
}
} // namespace SHADE

View File

@ -0,0 +1,108 @@
/****************************************************************************************
* \file SHCollider.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a Collider.
*
* \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 "Math/Geometry/SHBoundingBox.h"
#include "Math/SHQuaternion.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHCollider
{
public:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
enum class Type
{
BOX
, SPHERE
, CAPSULE
, CONVEX_HULL
, CONVEX_MESH
};
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHCollider (Type colliderType);
SHCollider (const SHCollider& rhs) noexcept;
SHCollider (SHCollider&& rhs) noexcept;
~SHCollider () noexcept;
/*---------------------------------------------------------------------------------*/
/* Operator Overloads */
/*---------------------------------------------------------------------------------*/
SHCollider& operator=(const SHCollider& rhs) noexcept;
SHCollider& operator=(SHCollider&& rhs) noexcept;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] bool HasChanged () const noexcept;
[[nodiscard]] bool IsTrigger () const noexcept;
[[nodiscard]] Type GetType () const noexcept;
[[nodiscard]] SHShape* GetShape () const noexcept;
[[nodiscard]] float GetFriction () const noexcept;
[[nodiscard]] float GetBounciness () const noexcept;
[[nodiscard]] float GetDensity () const noexcept;
[[nodiscard]] SHVec3 GetPosition () const noexcept;
[[nodiscard]] const SHVec3& GetPositionOffset () const noexcept;
[[nodiscard]] SHQuaternion GetOrientation () const noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetType (Type newType) noexcept;
void SetIsTrigger (bool isTrigger) noexcept;
void SetFriction (float friction) noexcept;
void SetBounciness (float bounciness) noexcept;
void SetDensity (float density) noexcept;
void SetPositionOffset (const SHVec3& positionOffset) noexcept;
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
Type type;
bool isTrigger;
bool dirty;
SHShape* shape;
SHVec3 positionOffset;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
void CreateShape ();
void CreateBoundingBox ();
void CreateSphere ();
};
} // namespace SHADE

View File

@ -0,0 +1,121 @@
/****************************************************************************************
* \file SHPhysicsObject.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a Physics Object.
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#include <SHpch.h>
// Primary Header
#include "SHPhysicsObject.h"
// Project Headers
#include "ECS_Base/Managers/SHSystemManager.h"
#include "SHPhysicsSystem.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObject::SHPhysicsObject() noexcept
: entityID { MAX_EID }
, isRigidBody { false }
, hasColliders{ false }
, rp3dBody { nullptr }
{}
SHPhysicsObject::~SHPhysicsObject() noexcept
{
rp3dBody = nullptr;
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
SHVec3 SHPhysicsObject::GetPosition() const noexcept
{
SHVec3 result;
if (rp3dBody)
{
const auto& RP3D_RESULT = rp3dBody->getTransform().getPosition();
result = SHVec3{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z };
}
return result;
}
SHQuaternion SHPhysicsObject::GetOrientation() const noexcept
{
SHQuaternion result;
if (rp3dBody)
{
const auto& RP3D_RESULT = rp3dBody->getTransform().getOrientation();
result = SHQuaternion{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z, RP3D_RESULT.w };
}
return result;
}
SHVec3 SHPhysicsObject::GetRotation() const noexcept
{
SHVec3 result;
if (rp3dBody)
{
const auto& RP3D_RESULT = rp3dBody->getTransform().getOrientation();
result = SHQuaternion{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z, RP3D_RESULT.w }.ToEuler();
}
return result;
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsObject::SetPosition(const SHVec3& position) noexcept
{
const rp3d::Vector3 RP3D_POS { position.x, position.y, position.z };
rp3d::Transform rp3dTF;
rp3dTF.setPosition(RP3D_POS);
rp3dTF.setOrientation(rp3dBody->getTransform().getOrientation());
rp3dBody->setTransform(rp3dTF);
prevTransform = rp3dTF;
}
void SHPhysicsObject::SetOrientation(const SHQuaternion& orientation) noexcept
{
const rp3d::Quaternion RP3D_ORIENTATION { orientation.x, orientation.y, orientation.z, orientation.w };
rp3d::Transform rp3dTF;
rp3dTF.setPosition(rp3dBody->getTransform().getPosition());
rp3dTF.setOrientation(RP3D_ORIENTATION);
rp3dBody->setTransform(rp3dTF);
prevTransform = rp3dTF;
}
void SHPhysicsObject::SetRotation(const SHVec3& rotation) noexcept
{
const rp3d::Quaternion RP3D_ORIENTATION = rp3d::Quaternion::fromEulerAngles( rotation.x, rotation.y, rotation.z );
rp3d::Transform rp3dTF;
rp3dTF.setPosition(rp3dBody->getTransform().getPosition());
rp3dTF.setOrientation(RP3D_ORIENTATION);
rp3dBody->setTransform(rp3dTF);
prevTransform = rp3dTF;
}
} // namespace SHADE

View File

@ -0,0 +1,89 @@
/****************************************************************************************
* \file SHPhysicsObject.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a Physics Object.
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#pragma once
#include <reactphysics3d/reactphysics3d.h>
// Project Headers
#include "Math/Vector/SHVec3.h"
#include "Math/SHQuaternion.h"
#include "ECS_Base/Entity/SHEntity.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHPhysicsObject
{
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHPhysicsSystem;
friend class SHRigidBodyComponent;
friend class SHColliderComponent;
public:
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHPhysicsObject () noexcept;
SHPhysicsObject (const SHPhysicsObject& rhs) noexcept = default;
SHPhysicsObject (SHPhysicsObject&& rhs) noexcept = default;
virtual ~SHPhysicsObject () noexcept;
/*---------------------------------------------------------------------------------*/
/* Operator Overloads */
/*---------------------------------------------------------------------------------*/
SHPhysicsObject& operator=(const SHPhysicsObject& rhs) noexcept = default;
SHPhysicsObject& operator=(SHPhysicsObject&& rhs) noexcept = default;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] SHVec3 GetPosition () const noexcept;
[[nodiscard]] SHQuaternion GetOrientation () const noexcept;
[[nodiscard]] SHVec3 GetRotation () const noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetPosition (const SHVec3& position) noexcept;
void SetOrientation (const SHQuaternion& orientation) noexcept;
void SetRotation (const SHVec3& rotation) noexcept;
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
EntityID entityID;
bool isRigidBody;
bool hasColliders;
rp3d::CollisionBody* rp3dBody; // Can be either a collision body or a rigid body
rp3d::Transform prevTransform; // Cached transform for interpolation
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
};
} // namespace SHADE

View File

@ -0,0 +1,747 @@
/****************************************************************************************
* \file SHPhysicsSystem.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for the Physics System
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#include <SHpch.h>
// Primary Header
#include "SHPhysicsSystem.h"
// Project Headers
#include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Scene/SHSceneManager.h"
#include "Math/Transform/SHTransformComponent.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsSystem::SHPhysicsSystem()
: worldUpdated { false }
, interpolationFactor { 0.0 }
, fixedDT { 60.0 }
, world { nullptr }
{}
SHPhysicsSystem::PhysicsPreUpdate::PhysicsPreUpdate()
: SHSystemRoutine { "Physics PreUpdate", true }
{}
SHPhysicsSystem::PhysicsFixedUpdate::PhysicsFixedUpdate()
: SHFixedSystemRoutine { DEFAULT_FIXED_STEP, "Physics FixedUpdate", false }
{}
SHPhysicsSystem::PhysicsPostUpdate::PhysicsPostUpdate()
: SHSystemRoutine { "Physics PostUpdate", false }
{}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
double SHPhysicsSystem::GetFixedDT() const noexcept
{
return fixedDT;
}
bool SHPhysicsSystem::IsSleepingEnabled() const noexcept
{
if (world)
return world->isSleepingEnabled();
SHLOGV_WARNING("No physics world has been initialised!")
return false;
}
SHVec3 SHPhysicsSystem::GetWorldGravity() const noexcept
{
SHVec3 result;
if (world)
{
const auto RP3D_GRAVITY = world->getGravity();
result.x = RP3D_GRAVITY.x;
result.y = RP3D_GRAVITY.y;
result.z = RP3D_GRAVITY.z;
}
else
{
SHLOGV_WARNING("No physics world has been initialised!")
}
return result;
}
uint16_t SHPhysicsSystem::GetNumberVelocityIterations() const noexcept
{
if (world)
return world->getNbIterationsVelocitySolver();
SHLOGV_WARNING("No physics world has been initialised!")
return 0;
}
uint16_t SHPhysicsSystem::GetNumberPositionIterations() const noexcept
{
if (world)
return world->getNbIterationsPositionSolver();
SHLOGV_WARNING("No physics world has been initialised!")
return 0;
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsSystem::SetFixedDT(double fixedUpdateRate) noexcept
{
fixedDT = fixedUpdateRate;
}
void SHPhysicsSystem::SetWorldGravity(const SHVec3& gravity) const noexcept
{
if (world)
{
const rp3d::Vector3 G { gravity.x, gravity.y, gravity.z };
world->setGravity(G);
}
else
{
SHLOGV_WARNING("No physics world has been initialised!")
}
}
void SHPhysicsSystem::SetNumberVelocityIterations(uint16_t numVelIterations) const noexcept
{
if (world)
{
world->setNbIterationsVelocitySolver(numVelIterations);
}
else
{
SHLOGV_WARNING("No physics world has been initialised!")
}
}
void SHPhysicsSystem::SetNumberPositionIterations(uint16_t numPosIterations) const noexcept
{
if (world)
{
world->setNbIterationsPositionSolver(numPosIterations);
}
else
{
SHLOGV_WARNING("No physics world has been initialised!")
}
}
void SHPhysicsSystem::SetSleepingEnabled(bool enableSleeping) const noexcept
{
if (world)
{
world->enableSleeping(enableSleeping);
}
else
{
SHLOGV_WARNING("No physics world has been initialised!")
}
}
void SHPhysicsSystem::SetWorldSettings(const WorldSettings& settings) const noexcept
{
if (world)
{
const rp3d::Vector3 G { settings.gravity.x, settings.gravity.y, settings.gravity.z };
world->setGravity(G);
world->setNbIterationsVelocitySolver(settings.numVelocitySolverIterations);
world->setNbIterationsPositionSolver(settings.numPositionSolverIterations);
world->enableSleeping(settings.sleepingEnabled);
}
else
{
SHLOGV_WARNING("No physics world has been initialised!")
}
}
/*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
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 };
settings.isSleepingEnabled = true;
settings.defaultVelocitySolverNbIterations = 8;
settings.defaultPositionSolverNbIterations = 3;
settings.defaultFrictionCoefficient = 0.4f;
settings.defaultBounciness = 0.0f;
world = factory.createPhysicsWorld(settings);
// Set up solvers
world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES);
}
void SHPhysicsSystem::Exit()
{
factory.destroyPhysicsWorld(world);
}
void SHPhysicsSystem::AddRigidBody(EntityID entityID) noexcept
{
#ifdef _DEBUG
SHLOG_INFO("Adding a Rigidbody to the Physics World.")
#endif
// Check if entity is already a physics object
auto* physicsObject = GetPhysicsObject(entityID);
if (!physicsObject)
{
physicsObject = &(map.emplace(entityID, SHPhysicsObject{}).first->second);
physicsObject->entityID = entityID;
}
// Get entity transform
auto const* SHADE_TF = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
// Possibly redundant
if (!SHADE_TF)
{
SHComponentManager::AddComponent<SHTransformComponent>(entityID);
SHADE_TF = SHComponentManager::GetComponent<SHTransformComponent>(entityID);
}
const SHVec3& SHADE_POS = SHADE_TF->GetWorldPosition();
const SHVec3& SHADE_ROT = SHADE_TF->GetWorldRotation();
const rp3d::Vector3 RP3D_POS { SHADE_POS.x, SHADE_POS.y, SHADE_POS.z };
const rp3d::Quaternion RP3D_ROT = rp3d::Quaternion::fromEulerAngles( SHADE_ROT.x, SHADE_ROT.y, SHADE_ROT.z );
const rp3d::Transform RP3D_TF { RP3D_POS, RP3D_ROT };
// If collider already exists
if (physicsObject->hasColliders)
world->destroyCollisionBody(physicsObject->rp3dBody);
physicsObject->rp3dBody = world->createRigidBody(RP3D_TF);
physicsObject->isRigidBody = true;
// Recreate colliders
if (physicsObject->hasColliders)
{
const auto& COLLIDERS = SHComponentManager::GetComponent<SHColliderComponent>(entityID)->GetColliders();
for (const auto& collider : COLLIDERS | std::views::keys)
{
switch (collider.GetType())
{
case SHCollider::Type::BOX:
{
SHBoundingBox* box = reinterpret_cast<SHBoundingBox*>(collider.GetShape());
const SHVec3& SHADE_EXTENTS = box->GetHalfExtents();
rp3d::Vector3 RP3D_EXTENTS { SHADE_EXTENTS.x, SHADE_EXTENTS.y, SHADE_EXTENTS.z };
rp3d::BoxShape* newBox = factory.createBoxShape(RP3D_EXTENTS);
// TODO(Diren): Handle offsets
physicsObject->rp3dBody->addCollider(newBox, RP3D_TF);
break;
}
case SHCollider::Type::SPHERE:
{
break;
}
// TODO(Diren): Add more collider shapes
default: break;
}
}
}
}
void SHPhysicsSystem::AddCollider(EntityID entityID) noexcept
{
#ifdef _DEBUG
SHLOG_INFO("Adding a Collider to the Physics World.")
#endif
// Check if entity is already a physics object
auto* physicsObject = GetPhysicsObject(entityID);
if (!physicsObject)
{
physicsObject = &(map.emplace(entityID, SHPhysicsObject{}).first->second);
physicsObject->entityID = entityID;
}
// Get entity transform
auto const* SHADE_TF = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
// Possibly redundant
if (!SHADE_TF)
{
SHComponentManager::AddComponent<SHTransformComponent>(entityID);
SHADE_TF = SHComponentManager::GetComponent<SHTransformComponent>(entityID);
}
const SHVec3& SHADE_POS = SHADE_TF->GetWorldPosition();
const SHVec3& SHADE_ROT = SHADE_TF->GetWorldRotation();
const rp3d::Vector3 RP3D_POS { SHADE_POS.x, SHADE_POS.y, SHADE_POS.z };
const rp3d::Quaternion RP3D_ROT = rp3d::Quaternion::fromEulerAngles( SHADE_ROT.x, SHADE_ROT.y, SHADE_ROT.z );
const rp3d::Transform RP3D_TF { RP3D_POS, RP3D_ROT };
// No rb
if (!physicsObject->isRigidBody)
physicsObject->rp3dBody = world->createCollisionBody(RP3D_TF);
const auto& COLLIDERS = SHComponentManager::GetComponent<SHColliderComponent>(entityID)->GetColliders();
for (const auto& collider : COLLIDERS | std::views::keys)
{
switch (collider.GetType())
{
case SHCollider::Type::BOX:
{
SHBoundingBox* box = reinterpret_cast<SHBoundingBox*>(collider.GetShape());
const SHVec3& SHADE_EXTENTS = box->GetHalfExtents();
rp3d::Vector3 RP3D_EXTENTS { SHADE_EXTENTS.x, SHADE_EXTENTS.y, SHADE_EXTENTS.z };
rp3d::BoxShape* newBox = factory.createBoxShape(RP3D_EXTENTS);
// TODO(Diren): Handle offsets
physicsObject->rp3dBody->addCollider(newBox, RP3D_TF);
break;
}
case SHCollider::Type::SPHERE:
{
break;
}
// TODO(Diren): Add more collider shapes
default: break;
}
}
physicsObject->hasColliders = true;
}
void SHPhysicsSystem::RemoveRigidBody(EntityID entityID) noexcept
{
#ifdef _DEBUG
SHLOG_INFO("Removing a Rigidbody from the Physics World.")
#endif
}
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, SHShape* shape)
{
auto* physicsObject = GetPhysicsObject(entityID);
switch (shape->GetType())
{
case SHShape::Type::BOUNDING_BOX:
{
auto* box = reinterpret_cast<SHBoundingBox*>(shape);
const SHVec3& SHADE_EXTENTS = box->GetHalfExtents();
rp3d::Vector3 RP3D_EXTENTS { SHADE_EXTENTS.x, SHADE_EXTENTS.y, SHADE_EXTENTS.z };
rp3d::BoxShape* newBox = factory.createBoxShape(RP3D_EXTENTS);
// TODO(Diren): Handle offsets
rp3d::Transform tf = rp3d::Transform::identity();
physicsObject->rp3dBody->addCollider(newBox, tf);
break;
}
case SHShape::Type::SPHERE:
{
break;
}
// TODO(Diren): Add more collider shapes
default: break;
}
}
void SHPhysicsSystem::RemoveCollisionShape(EntityID entityID, int index)
{
}
void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept
{
auto* system = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
// 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.SetRotation(TF->GetWorldRotation());
}
}
}
void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept
{
auto* system = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
fixedTimeStep = 1.0 / system->fixedDT;
accumulatedTime += dt;
int count = 0;
while (accumulatedTime > fixedTimeStep)
{
system->world->update(static_cast<rp3d::decimal>(fixedTimeStep));
accumulatedTime -= fixedTimeStep;
++count;
}
stats.numSteps = count;
system->worldUpdated = count > 0;
system->interpolationFactor = accumulatedTime / fixedTimeStep;
}
void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept
{
auto* system = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
// Interpolate transforms for rendering
if (system->worldUpdated)
{
system->SyncTransforms();
// TODO(Diren): Handle trigger messages for scripting
}
}
/*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObject* SHPhysicsSystem::GetPhysicsObject(EntityID entityID) noexcept
{
const auto it = map.find(entityID);
if (it == map.end())
{
SHLOG_ERROR("Entity {} is not in the physics system!", entityID)
return nullptr;
}
return &(it->second);
}
void SHPhysicsSystem::SyncRigidBodyComponents(std::vector<SHRigidBodyComponent>& denseArray) noexcept
{
if (denseArray.empty())
return;
for (auto& comp : denseArray)
{
const EntityID ENTITY_ID = comp.GetEID();
// Get physicsObject
auto const* physicsObject = GetPhysicsObject(ENTITY_ID);
const bool RP3D_ACTIVE = physicsObject->rp3dBody->isActive();
// TODO(Diren): Check if active in hierarchy
const bool COMPONENT_ACTIVE = comp.isActive;
if (RP3D_ACTIVE != COMPONENT_ACTIVE)
physicsObject->rp3dBody->setIsActive(COMPONENT_ACTIVE);
if (!COMPONENT_ACTIVE)
continue;
if (comp.dirtyFlags > 0)
{
SyncRigidBody(physicsObject, &comp);
comp.dirtyFlags = 0;
}
}
}
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 const* physicsObject = GetPhysicsObject(ENTITY_ID);
const bool RP3D_ACTIVE = physicsObject->rp3dBody->isActive();
// TODO(Diren): Check if active in hierarchy
const bool COMPONENT_ACTIVE = comp.isActive;
if (RP3D_ACTIVE != COMPONENT_ACTIVE)
physicsObject->rp3dBody->setIsActive(COMPONENT_ACTIVE);
if (!COMPONENT_ACTIVE)
continue;
SyncCollider(physicsObject, &comp);
}
}
void SHPhysicsSystem::SyncTransforms() noexcept
{
for (auto& pair : map)
{
const EntityID ENTITY_ID = pair.first;
SHPhysicsObject& physicsObject = pair.second;
rp3d::Vector3 rp3dPos;
rp3d::Quaternion rp3dRot;
const rp3d::Transform CURRENT_TF = physicsObject.rp3dBody->getTransform();
// Check if transform should be interpolated
if (physicsObject.isRigidBody)
{
auto const* rbComponent = SHComponentManager::GetComponent<SHRigidBodyComponent>(ENTITY_ID);
if (rbComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
continue;
if (rbComponent->IsInterpolating())
{
const rp3d::Transform PREV_TF = physicsObject.prevTransform;
const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast<rp3d::decimal>(interpolationFactor));
rp3dPos = INTERPOLATED_TF.getPosition();
rp3dRot = INTERPOLATED_TF.getOrientation();
}
else
{
rp3dPos = CURRENT_TF.getPosition();
rp3dRot = CURRENT_TF.getOrientation();
}
}
else
{
rp3dPos = CURRENT_TF.getPosition();
rp3dRot = CURRENT_TF.getOrientation();
}
// Convert RP3D Transform to SHADE
const SHVec3 SHADE_POS = SHVec3{ rp3dPos.x, rp3dPos.y, rp3dPos.z };
const SHVec3 SHADE_ROT = SHQuaternion{ rp3dRot.x, rp3dRot.y, rp3dRot.z, rp3dRot.w }.ToEuler();
auto* tfComponent = SHComponentManager::GetComponent<SHTransformComponent>(ENTITY_ID);
tfComponent->SetWorldPosition(SHADE_POS);
tfComponent->SetWorldRotation(SHADE_ROT);
// Cache transforms
physicsObject.prevTransform = CURRENT_TF;
}
}
void SHPhysicsSystem::SyncRigidBody(SHPhysicsObject const* physicsObject, const SHRigidBodyComponent* comp) noexcept
{
auto* rigidBody = reinterpret_cast<rp3d::RigidBody*>(physicsObject->rp3dBody);
const uint16_t RB_FLAGS = comp->dirtyFlags;
const size_t NUM_FLAGS = sizeof(RB_FLAGS) * 8U;
for (size_t i = 0; i < NUM_FLAGS; ++i)
{
// Check if current dirty flag has been set to true
if (RB_FLAGS & 1U << i)
{
switch (i)
{
case 0: // Gravity
{
rigidBody->enableGravity(comp->IsGravityEnabled());
break;
}
case 1: // Sleeping
{
rigidBody->setIsAllowedToSleep(comp->IsAllowedToSleep());
break;
}
case 2: // Linear Constraints
{
SetRP3DLinearConstraints(rigidBody, comp->flags);
break;
}
case 3: // Angular Constraints
{
SetRP3DAngularConstraints(rigidBody, comp->flags);
break;
}
case 4: // Type
{
rigidBody->setType(static_cast<rp3d::BodyType>(comp->GetType()));
break;
}
case 5: // Mass
{
rigidBody->setMass(comp->GetMass());
break;
}
case 6: // Drag
{
rigidBody->setLinearDamping(comp->GetDrag());
break;
}
case 7: // Angular Drag
{
rigidBody->setAngularDamping(comp->GetAngularDrag());
break;
}
case 8: // Linear Velocity
{
const SHVec3& SHADE_VEL = comp->GetLinearVelocity();
rp3d::Vector3 RP3D_VEL { SHADE_VEL.x, SHADE_VEL.y, SHADE_VEL.z };
rigidBody->setLinearVelocity(RP3D_VEL);
break;
}
case 9: // Angular Velocity
{
const SHVec3& SHADE_VEL = comp->GetAngularVelocity();
rp3d::Vector3 RP3D_VEL { SHADE_VEL.x, SHADE_VEL.y, SHADE_VEL.z };
rigidBody->setAngularVelocity(RP3D_VEL);
break;
}
default: break;
}
}
}
}
void SHPhysicsSystem::SetRP3DLinearConstraints(rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept
{
const rp3d::Vector3 CONSTRAINTS
{
rbFlags & 1U << 2 ? 0.0f : 1.0f,
rbFlags & 1U << 3 ? 0.0f : 1.0f,
rbFlags & 1U << 4 ? 0.0f : 1.0f
};
rp3dRigidBody->setLinearLockAxisFactor(CONSTRAINTS);
}
void SHPhysicsSystem::SetRP3DAngularConstraints(rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept
{
const rp3d::Vector3 CONSTRAINTS
{
rbFlags & 1U << 5 ? 0.0f : 1.0f,
rbFlags & 1U << 6 ? 0.0f : 1.0f,
rbFlags & 1U << 7 ? 0.0f : 1.0f
};
rp3dRigidBody->setAngularLockAxisFactor(CONSTRAINTS);
}
void SHPhysicsSystem::SyncCollider(SHPhysicsObject const* physicsObject, SHColliderComponent* comp) noexcept
{
int index = 0;
for (auto& [collider, dirty] : comp->colliders)
{
if (!dirty)
continue;
switch (collider.GetType())
{
case SHCollider::Type::BOX:
{
SHBoundingBox* box = reinterpret_cast<SHBoundingBox*>(collider.GetShape());
const SHVec3& SHADE_EXTENTS = box->GetHalfExtents();
rp3d::Vector3 RP3D_EXTENTS { SHADE_EXTENTS.x, SHADE_EXTENTS.y, SHADE_EXTENTS.z };
auto* rp3dBoxShape = reinterpret_cast<rp3d::BoxShape*>(physicsObject->rp3dBody->getCollider(index)->getCollisionShape());
rp3dBoxShape->setHalfExtents(RP3D_EXTENTS);
if (rp3dBoxShape)
{
SHLOG_INFO("Updating box things")
}
break;
}
case SHCollider::Type::SPHERE:
{
break;
}
default: break;
}
dirty = false;
++index;
}
}
} // namespace SHADE

View File

@ -0,0 +1,203 @@
/****************************************************************************************
* \file SHPhysicsSystem.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for the Physics System
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#pragma once
#include <queue>
#include <unordered_map>
#include <reactphysics3d/reactphysics3d.h>
// Project Headers
#include "SHPhysicsObject.h"
#include "Components/SHRigidBodyComponent.h"
#include "Components/SHColliderComponent.h"
#include "Scene/SHSceneGraph.h"
#include "ECS_Base/System/SHSystemRoutine.h"
#include "ECS_Base/System/SHFixedSystemRoutine.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHPhysicsSystem : public SHSystem
{
public:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
struct WorldSettings
{
SHVec3 gravity;
uint16_t numVelocitySolverIterations;
uint16_t numPositionSolverIterations;
bool sleepingEnabled;
};
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHPhysicsSystem();
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] double GetFixedDT () const noexcept;
[[nodiscard]] bool IsSleepingEnabled () const noexcept;
[[nodiscard]] SHVec3 GetWorldGravity () const noexcept;
[[nodiscard]] uint16_t GetNumberVelocityIterations () const noexcept;
[[nodiscard]] uint16_t GetNumberPositionIterations () const noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetFixedDT (double fixedUpdateRate) noexcept;
void SetWorldGravity (const SHVec3& gravity) const noexcept;
void SetNumberVelocityIterations (uint16_t numVelIterations) const noexcept;
void SetNumberPositionIterations (uint16_t numPosIterations) const noexcept;
void SetSleepingEnabled (bool enableSleeping) const noexcept;
void SetWorldSettings (const WorldSettings& settings) const noexcept;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
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 AddCollisionShape (EntityID entityID, SHShape* shape);
void RemoveCollisionShape (EntityID entityID, int index);
/*---------------------------------------------------------------------------------*/
/* System Routines */
/*---------------------------------------------------------------------------------*/
/**
* @brief Synchronises RP3D with SHADE
*/
class SH_API PhysicsPreUpdate : public SHSystemRoutine
{
public:
/*-------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-------------------------------------------------------------------------------*/
PhysicsPreUpdate();
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
void Execute(double dt) noexcept override;
};
class SH_API PhysicsFixedUpdate : public SHFixedSystemRoutine
{
public:
/*-------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-------------------------------------------------------------------------------*/
PhysicsFixedUpdate();
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
void Execute (double dt) noexcept override;
};
class SH_API PhysicsPostUpdate : public SHSystemRoutine
{
public:
/*-------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-------------------------------------------------------------------------------*/
PhysicsPostUpdate();
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
void Execute(double dt) noexcept override;
};
private:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
using EntityObjectMap = std::unordered_map<EntityID, SHPhysicsObject>;
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
// TODO(Diren): Store interpFactor
bool worldUpdated;
double interpolationFactor;
double fixedDT;
rp3d::PhysicsWorld* world;
rp3d::PhysicsCommon factory;
EntityObjectMap map;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
void SyncRigidBodyComponents (std::vector<SHRigidBodyComponent>& denseArray) noexcept;
void SyncColliderComponents (std::vector<SHColliderComponent>& denseArray) noexcept;
void SyncTransforms () noexcept;
// TODO(Diren): Trigger handling
static void SyncRigidBody (SHPhysicsObject const* physicsObject, const SHRigidBodyComponent* comp) noexcept;
static void SetRP3DLinearConstraints (rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept;
static void SetRP3DAngularConstraints (rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept;
static void SyncCollider (SHPhysicsObject const* physicsObject, SHColliderComponent* comp) noexcept;
};
} // namespace SHADE

View File

@ -38,3 +38,4 @@
#include "Common/SHCommonTypes.h" #include "Common/SHCommonTypes.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
#include "Tools/SHException.h"

View File

@ -75,10 +75,13 @@ namespace SHADE
}; };
} }
#define SHASSERT(cond, msg) \ #ifdef _DEBUG
#define SHASSERT(cond, msg) \
if (!(cond)) \ if (!(cond)) \
{ \ { \
SHLOGV_CRITICAL(msg) \ SHLOGV_CRITICAL(msg) \
std::abort(); \ std::abort(); \
} }
#else
#define SHASSERT(cond, msg) { }
#endif