Restructured Physics Systems & Interfaces

This commit is contained in:
Diren D Bharwani 2022-12-04 17:31:22 +08:00
parent 6cd203179a
commit ca45a12186
28 changed files with 1333 additions and 655 deletions

View File

@ -1 +1,28 @@
[] - EID: 0
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: 1.77475965, z: 0}
Rotate: {x: -0, y: 0, z: -0}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
RigidBody Component:
Type: Static
Auto Mass: false
Mass: 1
Drag: 0
Angular Drag: 0
Use Gravity: true
Gravity Scale: 1
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true
Scripts: ~

View File

@ -109,7 +109,7 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostLogicUpdate>(); SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostLogicUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>(); SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();

View File

@ -11,7 +11,7 @@
#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/Interface/SHRigidBodyComponent.h" #include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
#include "Physics/Interface/SHColliderComponent.h" #include "Physics/Interface/SHColliderComponent.h"
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h" #include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h"
@ -44,13 +44,6 @@ namespace Sandbox
{ {
sceneName = SHSerialization::DeserializeSceneFromFile(sceneAssetID); sceneName = SHSerialization::DeserializeSceneFromFile(sceneAssetID);
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (!physicsSystem)
{
SHLOGV_CRITICAL("Failed to get the physics system for building the scene!")
return;
}
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* TESTING CODE */ /* TESTING CODE */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -10,7 +10,7 @@
#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/Interface/SHRigidBodyComponent.h" #include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
#include "Physics/Interface/SHColliderComponent.h" #include "Physics/Interface/SHColliderComponent.h"
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h"

View File

@ -251,7 +251,7 @@ namespace SHADE
if(rbType == SHRigidBodyComponent::Type::DYNAMIC) //Dynamic only fields if(rbType == SHRigidBodyComponent::Type::DYNAMIC) //Dynamic only fields
{ {
SHEditorWidgets::CheckBox("Use Gravity", [component]{return component->IsGravityEnabled();}, [component](bool const& value){component->SetGravityEnabled(value);}, "Gravity"); SHEditorWidgets::CheckBox("Use Gravity", [component]{return component->IsGravityEnabled();}, [component](bool const& value){component->SetIsGravityEnabled(value);}, "Gravity");
//SHEditorWidgets::DragFloat("Mass", [component] {return component->GetMass(); }, [component](float const& value) {component->SetMass(value); }, "Mass"); //SHEditorWidgets::DragFloat("Mass", [component] {return component->GetMass(); }, [component](float const& value) {component->SetMass(value); }, "Mass");
} }
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
@ -296,7 +296,7 @@ namespace SHADE
{ {
SHEditorWidgets::DragVec3("Force", { "X", "Y", "Z" }, [component] {return component->GetForce(); }, [](SHVec3 const& value) {}, false, "Force", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); SHEditorWidgets::DragVec3("Force", { "X", "Y", "Z" }, [component] {return component->GetForce(); }, [](SHVec3 const& value) {}, false, "Force", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::DragVec3("Torque", { "X", "Y", "Z" }, [component] {return component->GetTorque(); }, [](SHVec3 const& value) {}, false, "Torque", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); SHEditorWidgets::DragVec3("Torque", { "X", "Y", "Z" }, [component] {return component->GetTorque(); }, [](SHVec3 const& value) {}, false, "Torque", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::CheckBox("Is Asleep", [component] {return component->GetIsSleeping(); }, [](bool value) {}, "If the Rigid Body is asleep"); SHEditorWidgets::CheckBox("Is Asleep", [component] {return component->IsSleeping(); }, [](bool value) {}, "If the Rigid Body is asleep");
} }
} }

View File

@ -14,7 +14,7 @@
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Physics/Interface/SHRigidBodyComponent.h" #include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
#include "Physics/Interface/SHColliderComponent.h" #include "Physics/Interface/SHColliderComponent.h"
#include "Camera/SHCameraComponent.h" #include "Camera/SHCameraComponent.h"
#include "Camera/SHCameraArmComponent.h" #include "Camera/SHCameraArmComponent.h"

View File

@ -13,9 +13,11 @@ constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 }; constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 };
constexpr SHEventIdentifier SH_SCENEGRAPH_ADD_CHILD_EVENT { 6 }; constexpr SHEventIdentifier SH_SCENEGRAPH_ADD_CHILD_EVENT { 6 };
constexpr SHEventIdentifier SH_SCENEGRAPH_REMOVE_CHILD_EVENT { 7 }; constexpr SHEventIdentifier SH_SCENEGRAPH_REMOVE_CHILD_EVENT { 7 };
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 8 }; constexpr SHEventIdentifier SH_SCENE_ON_INIT_EVENT { 8 };
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 9 }; constexpr SHEventIdentifier SH_SCENE_ON_EXIT_EVENT { 9 };
constexpr SHEventIdentifier SH_EDITOR_ON_PLAY_EVENT { 10 }; constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 10 };
constexpr SHEventIdentifier SH_EDITOR_ON_PAUSE_EVENT { 11 }; constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 11 };
constexpr SHEventIdentifier SH_EDITOR_ON_STOP_EVENT { 12 }; constexpr SHEventIdentifier SH_EDITOR_ON_PLAY_EVENT { 12 };
constexpr SHEventIdentifier SH_EDITOR_ON_PAUSE_EVENT { 13 };
constexpr SHEventIdentifier SH_EDITOR_ON_STOP_EVENT { 14 };

View File

@ -12,7 +12,7 @@
// Project Headers // Project Headers
#include "Physics/Interface/SHColliderComponent.h" #include "Physics/Interface/SHColliderComponent.h"
#include "Physics/Interface/SHRigidBodyComponent.h" #include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
namespace SHADE namespace SHADE

View File

@ -13,6 +13,9 @@
// Primary Header // Primary Header
#include "SHRigidBody.h" #include "SHRigidBody.h"
// Project Headers
#include "Tools/Logger/SHLogger.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -93,4 +96,357 @@ namespace SHADE
return *this; return *this;
} }
/*-----------------------------------------------------------------------------------*/
/* Getter Functions Definitions */
/*-----------------------------------------------------------------------------------*/
SHRigidBody::Type SHRigidBody::GetType() const noexcept
{
return bodyType;
}
float SHRigidBody::GetMass() const noexcept
{
return 1.0f/ invMass;
}
float SHRigidBody::GetLinearDrag() const noexcept
{
return linearDrag;
}
float SHRigidBody::GetGravityScale() const noexcept
{
return gravityScale;
}
const SHVec3& SHRigidBody::GetAccumulatedForce() const noexcept
{
return accumulatedForce;
}
const SHVec3& SHRigidBody::GetLinearVelocity() const noexcept
{
return linearVelocity;
}
const SHVec3& SHRigidBody::GetAngularVelocity() const noexcept
{
return angularVelocity;
}
// Flags
bool SHRigidBody::IsActive() const noexcept
{
static constexpr unsigned int FLAG_POS = 0;
return flags & (1U << FLAG_POS);
}
bool SHRigidBody::IsSleeping() const noexcept
{
static constexpr unsigned int FLAG_POS = 1;
return flags & (1U << FLAG_POS);
}
bool SHRigidBody::IsSleepingEnabled() const noexcept
{
static constexpr unsigned int FLAG_POS = 2;
return flags & (1U << FLAG_POS);
}
bool SHRigidBody::IsGravityEnabled() const noexcept
{
static constexpr unsigned int FLAG_POS = 3;
return flags & (1U << FLAG_POS);
}
bool SHRigidBody::IsAutoMassEnabled() const noexcept
{
static constexpr unsigned int FLAG_POS = 4;
return flags & (1U << FLAG_POS);
}
bool SHRigidBody::GetFreezePositionX() const noexcept
{
static constexpr unsigned int FLAG_POS = 10;
return flags & (1U << FLAG_POS);
}
bool SHRigidBody::GetFreezePositionY() const noexcept
{
static constexpr unsigned int FLAG_POS = 11;
return flags & (1U << FLAG_POS);
}
bool SHRigidBody::GetFreezePositionZ() const noexcept
{
static constexpr unsigned int FLAG_POS = 12;
return flags & (1U << FLAG_POS);
}
bool SHRigidBody::GetFreezeRotationX() const noexcept
{
static constexpr unsigned int FLAG_POS = 13;
return flags & (1U << FLAG_POS);
}
bool SHRigidBody::GetFreezeRotationY() const noexcept
{
static constexpr unsigned int FLAG_POS = 14;
return flags & (1U << FLAG_POS);
}
bool SHRigidBody::GetFreezeRotationZ() const noexcept
{
static constexpr unsigned int FLAG_POS = 15;
return flags & (1U << FLAG_POS);
}
/*-----------------------------------------------------------------------------------*/
/* Setter Functions Definitions */
/*-----------------------------------------------------------------------------------*/
void SHRigidBody::SetType(Type newType) noexcept
{
if (newType == bodyType)
return;
bodyType = newType;
invMass = newType == Type::DYNAMIC ? 1.0f : 0.0f;
}
void SHRigidBody::SetMass(float newMass) noexcept
{
if (bodyType != Type::DYNAMIC)
{
SHLOG_WARNING("Cannot set mass of a non-Dynamic Body {}", entityID)
return;
}
if (newMass < 0.0f)
{
SHLOG_WARNING("Cannot set mass below 0. Object {}'s mass will remain unchanged.", entityID)
return;
}
invMass = 1.0f / newMass;
// TODO: Recompute inertia tensor
}
void SHRigidBody::SetLinearDrag(float newLinearDrag) noexcept
{
if (bodyType == Type::STATIC)
{
SHLOG_WARNING("Cannot set linear drag of a Static Body {}", entityID)
return;
}
if (newLinearDrag < 0.0f)
{
SHLOG_WARNING("Cannot set drag below 0. Object {}'s linear drag will remain unchanged.", entityID)
return;
}
linearDrag = newLinearDrag;
}
void SHRigidBody::SetGravityScale(float newGravityScale) noexcept
{
gravityScale = newGravityScale;
}
void SHRigidBody::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
{
linearVelocity = newLinearVelocity;
}
void SHRigidBody::SetIsActive(bool isActive) noexcept
{
static constexpr unsigned int FLAG_POS = 0;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
isActive ? flags |= VALUE : flags &= ~VALUE;
}
void SHRigidBody::SetIsSleeping(bool isSleeping) noexcept
{
static constexpr unsigned int FLAG_POS = 1;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
isSleeping ? flags |= VALUE : flags &= ~VALUE;
}
void SHRigidBody::SetSleepingEnabled(bool enableSleeping) noexcept
{
static constexpr unsigned int FLAG_POS = 2;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (enableSleeping)
{
flags |= VALUE;
}
else
{
flags &= ~VALUE;
// Wake the body
SetIsSleeping(false);
}
}
void SHRigidBody::SetGravityEnabled(bool enableGravity) noexcept
{
static constexpr unsigned int FLAG_POS = 3;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
enableGravity ? flags |= VALUE : flags &= ~VALUE;
}
void SHRigidBody::SetAutoMassEnabled(bool enableAutoMass) noexcept
{
static constexpr unsigned int FLAG_POS = 4;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (enableAutoMass)
{
flags |= VALUE;
// TODO: Compute mass based on collider geometry
}
else
{
flags &= ~VALUE;
// Use default mass of 1
invMass = 1.0f;
}
}
void SHRigidBody::SetFreezePositionX(bool freezePositionX) noexcept
{
static constexpr unsigned int FLAG_POS = 10;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (freezePositionX)
{
flags |= VALUE;
// Reset linear velocity along X-axis
linearVelocity.x = 0.0f;
}
else
{
flags &= ~VALUE;
}
}
void SHRigidBody::SetFreezePositionY(bool freezePositionY) noexcept
{
static constexpr unsigned int FLAG_POS = 11;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (freezePositionY)
{
flags |= VALUE;
// Reset linear velocity along Y-axis
linearVelocity.y = 0.0f;
}
else
{
flags &= ~VALUE;
}
}
void SHRigidBody::SetFreezePositionZ(bool freezePositionZ) noexcept
{
static constexpr unsigned int FLAG_POS = 12;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (freezePositionZ)
{
flags |= VALUE;
// Reset linear velocity along Z-axis
linearVelocity.z = 0.0f;
}
else
{
flags &= ~VALUE;
}
}
void SHRigidBody::SetFreezeRotationX(bool freezeRotationX) noexcept
{
static constexpr unsigned int FLAG_POS = 13;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (freezeRotationX)
{
flags |= VALUE;
// Reset angular velocity along X-axis
angularVelocity.x = 0.0f;
}
else
{
flags &= ~VALUE;
}
}
void SHRigidBody::SetFreezeRotationY(bool freezeRotationY) noexcept
{
static constexpr unsigned int FLAG_POS = 14;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (freezeRotationY)
{
flags |= VALUE;
// Reset angular velocity along Y-axis
angularVelocity.y = 0.0f;
}
else
{
flags &= ~VALUE;
}
}
void SHRigidBody::SetFreezeRotationZ(bool freezeRotationZ) noexcept
{
static constexpr unsigned int FLAG_POS = 15;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (freezeRotationZ)
{
flags |= VALUE;
// Reset angular velocity along Z-axis
angularVelocity.z = 0.0f;
}
else
{
flags &= ~VALUE;
}
}
/*-----------------------------------------------------------------------------------*/
/* Member Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHRigidBody::AddForce(const SHVec3& force, const SHVec3& pos) noexcept
{
if (bodyType != Type::DYNAMIC)
return;
accumulatedForce += force;
// Compute torque when force is offset
}
void SHRigidBody::AddImpulse(const SHVec3& impulse, const SHVec3& pos) noexcept
{
if (bodyType != Type::DYNAMIC)
return;
linearVelocity += impulse * invMass;
}
void SHRigidBody::ClearForces() noexcept
{
accumulatedForce = SHVec3::Zero;
}
} // namespace SHADE } // namespace SHADE

View File

@ -13,22 +13,20 @@
// Project Headers // Project Headers
#include "ECS_Base/SHECSMacros.h" #include "ECS_Base/SHECSMacros.h"
#include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec3.h"
#include "SH_API.h"
namespace SHADE namespace SHADE
{ {
/*-------------------------------------------------------------------------------------*/
/* Type Definitions */
/*-------------------------------------------------------------------------------------*/
/** /**
* @brief * @brief
* Encapsulates a Rigid Body used in Physics Simulations * Encapsulates a Rigid Body used in Physics Simulations
*/ */
class SHRigidBody class SH_API SHRigidBody
{ {
private:
/*-----------------------------------------------------------------------------------*/
/* Friends */
/*-----------------------------------------------------------------------------------*/
friend class SHRigidBodyComponent;
public: public:
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -185,5 +183,3 @@ namespace SHADE
}; };
} // namespace SHADE } // namespace SHADE
#include "SHRigidBody.inl"

View File

@ -1,375 +0,0 @@
/****************************************************************************************
* \file SHRigidBody.inl
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for inlined functions of a Rigid Body.
*
* \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
// Primary Header
#include "SHRigidBody.h"
// Project Headers
#include "Math/SHMathHelpers.h"
#include "Tools/Logger/SHLogger.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Getter Functions Definitions */
/*-----------------------------------------------------------------------------------*/
inline SHRigidBody::Type SHRigidBody::GetType() const noexcept
{
return bodyType;
}
inline float SHRigidBody::GetMass() const noexcept
{
return 1.0f/ invMass;
}
inline float SHRigidBody::GetLinearDrag() const noexcept
{
return linearDrag;
}
inline float SHRigidBody::GetGravityScale() const noexcept
{
return gravityScale;
}
inline const SHVec3& SHRigidBody::GetAccumulatedForce() const noexcept
{
return accumulatedForce;
}
inline const SHVec3& SHRigidBody::GetLinearVelocity() const noexcept
{
return linearVelocity;
}
inline const SHVec3& SHRigidBody::GetAngularVelocity() const noexcept
{
return angularVelocity;
}
// Flags
inline bool SHRigidBody::IsActive() const noexcept
{
static constexpr unsigned int FLAG_POS = 0;
return flags & (1U << FLAG_POS);
}
inline bool SHRigidBody::IsSleeping() const noexcept
{
static constexpr unsigned int FLAG_POS = 1;
return flags & (1U << FLAG_POS);
}
inline bool SHRigidBody::IsSleepingEnabled() const noexcept
{
static constexpr unsigned int FLAG_POS = 2;
return flags & (1U << FLAG_POS);
}
inline bool SHRigidBody::IsGravityEnabled() const noexcept
{
static constexpr unsigned int FLAG_POS = 3;
return flags & (1U << FLAG_POS);
}
inline bool SHRigidBody::IsAutoMassEnabled() const noexcept
{
static constexpr unsigned int FLAG_POS = 4;
return flags & (1U << FLAG_POS);
}
inline bool SHRigidBody::GetFreezePositionX() const noexcept
{
static constexpr unsigned int FLAG_POS = 10;
return flags & (1U << FLAG_POS);
}
inline bool SHRigidBody::GetFreezePositionY() const noexcept
{
static constexpr unsigned int FLAG_POS = 11;
return flags & (1U << FLAG_POS);
}
inline bool SHRigidBody::GetFreezePositionZ() const noexcept
{
static constexpr unsigned int FLAG_POS = 12;
return flags & (1U << FLAG_POS);
}
inline bool SHRigidBody::GetFreezeRotationX() const noexcept
{
static constexpr unsigned int FLAG_POS = 13;
return flags & (1U << FLAG_POS);
}
inline bool SHRigidBody::GetFreezeRotationY() const noexcept
{
static constexpr unsigned int FLAG_POS = 14;
return flags & (1U << FLAG_POS);
}
inline bool SHRigidBody::GetFreezeRotationZ() const noexcept
{
static constexpr unsigned int FLAG_POS = 15;
return flags & (1U << FLAG_POS);
}
/*-----------------------------------------------------------------------------------*/
/* Setter Functions Definitions */
/*-----------------------------------------------------------------------------------*/
inline void SHRigidBody::SetType(Type newType) noexcept
{
if (newType == bodyType)
return;
bodyType = newType;
invMass = newType == Type::DYNAMIC ? 1.0f : 0.0f;
}
inline void SHRigidBody::SetMass(float newMass) noexcept
{
if (bodyType != Type::DYNAMIC)
{
SHLOG_WARNING("Cannot set mass of a non-Dynamic Body {}", entityID)
return;
}
if (newMass < 0.0f)
{
SHLOG_WARNING("Cannot set mass below 0. Object {}'s mass will remain unchanged.", entityID)
return;
}
invMass = 1.0f / newMass;
// TODO: Recompute inertia tensor
}
inline void SHRigidBody::SetLinearDrag(float newLinearDrag) noexcept
{
if (bodyType == Type::STATIC)
{
SHLOG_WARNING("Cannot set linear drag of a Static Body {}", entityID)
return;
}
if (newLinearDrag < 0.0f)
{
SHLOG_WARNING("Cannot set drag below 0. Object {}'s linear drag will remain unchanged.", entityID)
return;
}
linearDrag = newLinearDrag;
}
inline void SHRigidBody::SetGravityScale(float newGravityScale) noexcept
{
gravityScale = newGravityScale;
}
inline void SHRigidBody::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
{
linearVelocity = newLinearVelocity;
}
inline void SHRigidBody::SetIsActive(bool isActive) noexcept
{
static constexpr unsigned int FLAG_POS = 0;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
isActive ? flags |= VALUE : flags &= ~VALUE;
}
inline void SHRigidBody::SetIsSleeping(bool isSleeping) noexcept
{
static constexpr unsigned int FLAG_POS = 1;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
isSleeping ? flags |= VALUE : flags &= ~VALUE;
}
inline void SHRigidBody::SetSleepingEnabled(bool enableSleeping) noexcept
{
static constexpr unsigned int FLAG_POS = 2;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (enableSleeping)
{
flags |= VALUE;
}
else
{
flags &= ~VALUE;
// Wake the body
SetIsSleeping(false);
}
}
inline void SHRigidBody::SetGravityEnabled(bool enableGravity) noexcept
{
static constexpr unsigned int FLAG_POS = 3;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
enableGravity ? flags |= VALUE : flags &= ~VALUE;
}
inline void SHRigidBody::SetAutoMassEnabled(bool enableAutoMass) noexcept
{
static constexpr unsigned int FLAG_POS = 4;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (enableAutoMass)
{
flags |= VALUE;
// TODO: Compute mass based on collider geometry
}
else
{
flags &= ~VALUE;
// Use default mass of 1
invMass = 1.0f;
}
}
inline void SHRigidBody::SetFreezePositionX(bool freezePositionX) noexcept
{
static constexpr unsigned int FLAG_POS = 10;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (freezePositionX)
{
flags |= VALUE;
// Reset linear velocity along X-axis
linearVelocity.x = 0.0f;
}
else
{
flags &= ~VALUE;
}
}
inline void SHRigidBody::SetFreezePositionY(bool freezePositionY) noexcept
{
static constexpr unsigned int FLAG_POS = 11;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (freezePositionY)
{
flags |= VALUE;
// Reset linear velocity along Y-axis
linearVelocity.y = 0.0f;
}
else
{
flags &= ~VALUE;
}
}
inline void SHRigidBody::SetFreezePositionZ(bool freezePositionZ) noexcept
{
static constexpr unsigned int FLAG_POS = 12;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (freezePositionZ)
{
flags |= VALUE;
// Reset linear velocity along Z-axis
linearVelocity.z = 0.0f;
}
else
{
flags &= ~VALUE;
}
}
inline void SHRigidBody::SetFreezeRotationX(bool freezeRotationX) noexcept
{
static constexpr unsigned int FLAG_POS = 13;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (freezeRotationX)
{
flags |= VALUE;
// Reset angular velocity along X-axis
angularVelocity.x = 0.0f;
}
else
{
flags &= ~VALUE;
}
}
inline void SHRigidBody::SetFreezeRotationY(bool freezeRotationY) noexcept
{
static constexpr unsigned int FLAG_POS = 14;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (freezeRotationY)
{
flags |= VALUE;
// Reset angular velocity along Y-axis
angularVelocity.y = 0.0f;
}
else
{
flags &= ~VALUE;
}
}
inline void SHRigidBody::SetFreezeRotationZ(bool freezeRotationZ) noexcept
{
static constexpr unsigned int FLAG_POS = 15;
static constexpr uint16_t VALUE = 1U << FLAG_POS;
if (freezeRotationZ)
{
flags |= VALUE;
// Reset angular velocity along Z-axis
angularVelocity.z = 0.0f;
}
else
{
flags &= ~VALUE;
}
}
/*-----------------------------------------------------------------------------------*/
/* Member Function Definitions */
/*-----------------------------------------------------------------------------------*/
inline void SHRigidBody::AddForce(const SHVec3& force, const SHVec3& pos) noexcept
{
if (bodyType != Type::DYNAMIC)
return;
accumulatedForce += force;
// Compute torque when force is offset
}
inline void SHRigidBody::AddImpulse(const SHVec3& impulse, const SHVec3& pos) noexcept
{
if (bodyType != Type::DYNAMIC)
return;
linearVelocity += impulse * invMass;
}
inline void SHRigidBody::ClearForces() noexcept
{
accumulatedForce = SHVec3::Zero;
}
} // namespace SHADE

View File

@ -0,0 +1,74 @@
/****************************************************************************************
* \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"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructor & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObject::SHPhysicsObject(EntityID eid) noexcept
: entityID { eid }
{}
SHPhysicsObject::SHPhysicsObject(const SHPhysicsObject& rhs) noexcept
: entityID { rhs.entityID }
{
// Perform a deep copy of the components
*rigidBody = *rhs.rigidBody;
}
SHPhysicsObject::SHPhysicsObject(SHPhysicsObject&& rhs) noexcept
: entityID { rhs.entityID }
{
// Perform a deep copy of the components
*rigidBody = *rhs.rigidBody;
}
SHPhysicsObject::~SHPhysicsObject() noexcept
{
entityID = MAX_EID;
delete rigidBody;
}
/*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObject& SHPhysicsObject::operator=(const SHPhysicsObject& rhs) noexcept
{
if (this == &rhs)
return *this;
entityID = rhs.entityID;
// Perform a deep copy of the components
*rigidBody = *rhs.rigidBody;
return *this;
}
SHPhysicsObject& SHPhysicsObject::operator=(SHPhysicsObject&& rhs) noexcept
{
entityID = rhs.entityID;
// Perform a deep copy of the components
*rigidBody = *rhs.rigidBody;
return *this;
}
} // namespace SHADE

View File

@ -0,0 +1,52 @@
/****************************************************************************************
* \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
// Project Headers
#include "Physics/Dynamics/SHRigidBody.h"
namespace SHADE
{
/*-------------------------------------------------------------------------------------*/
/* Type Definitions */
/*-------------------------------------------------------------------------------------*/
/**
* @brief
* Encapsulates a rigid body and a collider tied to an Entity.
*/
struct SH_API SHPhysicsObject
{
public:
/*-----------------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------------*/
EntityID entityID = MAX_EID;
SHRigidBody* rigidBody = nullptr;
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObject (EntityID eid) noexcept;
SHPhysicsObject (const SHPhysicsObject& rhs) noexcept;
SHPhysicsObject (SHPhysicsObject&& rhs) noexcept;
~SHPhysicsObject () noexcept;
/*-----------------------------------------------------------------------------------*/
/* Operator Overloads */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObject& operator=(const SHPhysicsObject& rhs) noexcept;
SHPhysicsObject& operator=(SHPhysicsObject&& rhs) noexcept;
};
} // namespace SHADE

View File

@ -0,0 +1,138 @@
/****************************************************************************************
* \file SHPhysicsObjectManager.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a Physics Object Manager.
*
* \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 "SHPhysicsObjectManager.h"
// Project Headers
#include "Physics/Interface/SHColliderComponent.h"
#include "Physics/Interface/SHCollisionShape.h"
#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
#include "Tools/Utilities/SHUtilities.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObjectManager::EntityObjectMap& SHPhysicsObjectManager::GetPhysicsObjects() noexcept
{
return physicsObjects;
}
const SHPhysicsObject* SHPhysicsObjectManager::GetPhysicsObject(EntityID entityID) noexcept
{
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
if (PHYSICS_OBJECT_ITERATOR == physicsObjects.end())
{
SHLOG_ERROR("Cannot find physics object for entity {}!", entityID)
return nullptr;
}
return &PHYSICS_OBJECT_ITERATOR->second;
}
/*-----------------------------------------------------------------------------------*/
/* Public Member Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsObjectManager::AddRigidBody(EntityID entityID) noexcept
{
SHPhysicsObject* physicsObject = nullptr;
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
if (PHYSICS_OBJECT_ITERATOR == physicsObjects.end())
physicsObject = createPhysicsObject(entityID);
else
physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
// Get the component
auto* rigidBodyComponent = SHComponentManager::GetComponent<SHRigidBodyComponent>(entityID);
// Create a new rigidbody in the physics object
// We assume none has already been made
physicsObject->rigidBody = new SHRigidBody
{
entityID
, static_cast<SHRigidBody::Type>(rigidBodyComponent->GetType())
};
// Link with the component
rigidBodyComponent->SetRigidBody(physicsObject->rigidBody);
// TODO: Broadcast event
}
void SHPhysicsObjectManager::RemoveRigidBody(EntityID entityID) noexcept
{
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
if (PHYSICS_OBJECT_ITERATOR != physicsObjects.end())
{
SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
delete physicsObject->rigidBody;
physicsObject->rigidBody = nullptr;
// Destroy empty physics objects
if (physicsObject->rigidBody == nullptr)
destroyPhysicsObject(entityID);
}
// TODO: Broadcast event
}
void SHPhysicsObjectManager::AddCollider(EntityID entityID) noexcept
{
// Link with the component
// TODO: Broadcast event
}
void SHPhysicsObjectManager::RemoveCollider(EntityID entityID) noexcept
{
// Unlink with the component
// TODO: Broadcast event
}
void SHPhysicsObjectManager::AddCollisionShape(EntityID entityID, uint8_t shapeID) noexcept
{
// Link with the component
// TODO: Broadcast event
}
void SHPhysicsObjectManager::RemoveCollisionShape(EntityID entityID, uint8_t shapeID) noexcept
{
// Unlink with the component
// TODO: Broadcast event
}
/*-----------------------------------------------------------------------------------*/
/* Private Member Function Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObject* SHPhysicsObjectManager::createPhysicsObject(EntityID entityID)
{
const auto& NEW_OBJECT = physicsObjects.emplace(entityID, SHPhysicsObject{entityID}).first;
return &NEW_OBJECT->second;
}
void SHPhysicsObjectManager::destroyPhysicsObject(EntityID entityID)
{
physicsObjects.erase(entityID);
}
} // namespace SHADE

View File

@ -0,0 +1,125 @@
/****************************************************************************************
* \file SHPhysicsObjectManager.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a Physics Object Manager.
*
* \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 <unordered_map>
// Project Headers
#include "SHPhysicsObject.h"
namespace SHADE
{
/*-------------------------------------------------------------------------------------*/
/* Type Definitions */
/*-------------------------------------------------------------------------------------*/
/**
* @brief
* Encapsulates a manager for physics objects that links raw physics components with the
* engine's components.
*/
class SHPhysicsObjectManager
{
private:
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
using EntityObjectMap = std::unordered_map<EntityID, SHPhysicsObject>;
public:
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObjectManager() noexcept = default;
/*-----------------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------------*/
[[nodiscard]] EntityObjectMap& GetPhysicsObjects () noexcept;
[[nodiscard]] const SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
/*-----------------------------------------------------------------------------------*/
/* Member Functions */
/*-----------------------------------------------------------------------------------*/
/**
* @brief
* Creates a rigid body and links it with the rigid body component.
* @param entityID
* The entity to link the new rigid body to.
*/
void AddRigidBody (EntityID entityID) noexcept;
/**
* @brief
* Destroys a rigid body and removes the link with the rigid body component.
* @param entityID
* The entity to destroy the rigid body of.
*/
void RemoveRigidBody (EntityID entityID) noexcept;
/**
* @brief
* Creates a collider and links it with the collider component.
* @param entityID
* The entity to link the new collider to.
*/
void AddCollider (EntityID entityID) noexcept;
/**
* @brief
* Destroys a collider and removes the link with the collider component.
* @param entityID
* The entity to destroy the collider of.
*/
void RemoveCollider (EntityID entityID) noexcept;
/**
* @brief
* Creates a collision shape for composite colliders and links it with the
* collider component.
* @param eientityIDd
* The entity to create a collision shape for.
* @param shapeID
* The id of the shape being created.
*/
void AddCollisionShape (EntityID entityID, uint8_t shapeID) noexcept;
/**
* @brief
* Destroys a collision shape for composite colliders and removes the link with the
* collider component.
* @param entityID
* The entity to destroy the collision shape of.
* @param shapeID
* The id of the shape being destroyed.
*/
void RemoveCollisionShape (EntityID entityID, uint8_t shapeID) noexcept;
private:
/*-----------------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------------*/
EntityObjectMap physicsObjects;
/*-----------------------------------------------------------------------------------*/
/* Member Functions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObject* createPhysicsObject (EntityID entityID);
void destroyPhysicsObject (EntityID entityID);
};
} // namespace SHADE

View File

@ -18,7 +18,7 @@
// Project Headers // Project Headers
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Math/SHMathHelpers.h" #include "Physics/Dynamics/SHRigidBody.h"
#include "Physics/System/SHPhysicsSystem.h" #include "Physics/System/SHPhysicsSystem.h"
namespace SHADE namespace SHADE
@ -28,77 +28,127 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHRigidBodyComponent::SHRigidBodyComponent() noexcept SHRigidBodyComponent::SHRigidBodyComponent() noexcept
: type { Type::STATIC }
, interpolate { true }
, rigidBody { nullptr }
{}
/*-----------------------------------------------------------------------------------*/
/* Getter Functions Definitions */
/*-----------------------------------------------------------------------------------*/
SHRigidBodyComponent::Type SHRigidBodyComponent::GetType() const noexcept
{ {
return type;
} }
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
bool SHRigidBodyComponent::IsGravityEnabled() const noexcept bool SHRigidBodyComponent::IsGravityEnabled() const noexcept
{ {
if (rigidBody)
return rigidBody->IsGravityEnabled();
return false; return false;
} }
bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept
{ {
if (rigidBody)
return rigidBody->IsSleepingEnabled();
return false; return false;
} }
bool SHRigidBodyComponent::IsInterpolating() const noexcept bool SHRigidBodyComponent::IsInterpolating() const noexcept
{ {
return interpolate;
}
bool SHRigidBodyComponent::IsSleeping() const noexcept
{
if (rigidBody)
return rigidBody->IsSleeping();
return false; return false;
} }
bool SHRigidBodyComponent::GetIsSleeping() const noexcept bool SHRigidBodyComponent::GetAutoMass() const noexcept
{ {
return false; if (rigidBody)
} return rigidBody->IsAutoMassEnabled();
SHRigidBodyComponent::Type SHRigidBodyComponent::GetType() const noexcept return false;
{
return Type::STATIC;
} }
bool SHRigidBodyComponent::GetFreezePositionX() const noexcept bool SHRigidBodyComponent::GetFreezePositionX() const noexcept
{ {
if (rigidBody)
return rigidBody->GetFreezePositionX();
return false; return false;
} }
bool SHRigidBodyComponent::GetFreezePositionY() const noexcept bool SHRigidBodyComponent::GetFreezePositionY() const noexcept
{ {
if (rigidBody)
return rigidBody->GetFreezePositionY();
return false; return false;
} }
bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept
{ {
if (rigidBody)
return rigidBody->GetFreezePositionZ();
return false; return false;
} }
bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept
{ {
if (rigidBody)
return rigidBody->GetFreezeRotationX();
return false; return false;
} }
bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept
{ {
if (rigidBody)
return rigidBody->GetFreezeRotationY();
return false; return false;
} }
bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept
{ {
if (rigidBody)
return rigidBody->GetFreezeRotationZ();
return false; return false;
} }
float SHRigidBodyComponent::GetMass() const noexcept float SHRigidBodyComponent::GetGravityScale() const noexcept
{ {
if (rigidBody)
return rigidBody->GetGravityScale();
return 0.0f; return 0.0f;
} }
float SHRigidBodyComponent::GetMass() const noexcept
{
if (rigidBody)
return rigidBody->GetMass();
return -1.0f;
}
float SHRigidBodyComponent::GetDrag() const noexcept float SHRigidBodyComponent::GetDrag() const noexcept
{ {
return 0.0f; if (rigidBody)
return rigidBody->GetLinearDrag();
return -1.0f;
} }
float SHRigidBodyComponent::GetAngularDrag() const noexcept float SHRigidBodyComponent::GetAngularDrag() const noexcept
@ -108,6 +158,9 @@ namespace SHADE
SHVec3 SHRigidBodyComponent::GetForce() const noexcept SHVec3 SHRigidBodyComponent::GetForce() const noexcept
{ {
if (rigidBody)
return rigidBody->GetAccumulatedForce();
return SHVec3::Zero; return SHVec3::Zero;
} }
@ -118,6 +171,9 @@ namespace SHADE
SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept
{ {
if (rigidBody)
return rigidBody->GetLinearVelocity();
return SHVec3::Zero; return SHVec3::Zero;
} }
@ -127,91 +183,126 @@ namespace SHADE
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */ /* Setter Functions Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHRigidBodyComponent::SetType(Type newType) noexcept void SHRigidBodyComponent::SetType(Type newType) noexcept
{ {
if (newType == type)
return;
type = newType;
if (rigidBody)
rigidBody->SetType(static_cast<SHRigidBody::Type>(newType));
} }
void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept void SHRigidBodyComponent::SetRigidBody(SHRigidBody* rb) noexcept
{ {
rigidBody = rb;
}
void SHRigidBodyComponent::SetIsGravityEnabled(bool enableGravity) noexcept
{
if (rigidBody)
rigidBody->SetGravityEnabled(enableGravity);
} }
void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept
{ {
if (rigidBody)
rigidBody->SetSleepingEnabled(isAllowedToSleep);
}
void SHRigidBodyComponent::SetAutoMass(bool autoMass) noexcept
{
if (rigidBody)
rigidBody->SetAutoMassEnabled(autoMass);
} }
void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept
{ {
if (rigidBody)
rigidBody->SetFreezePositionX(freezePositionX);
} }
void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept
{ {
if (rigidBody)
rigidBody->SetFreezePositionY(freezePositionY);
} }
void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept
{ {
if (rigidBody)
rigidBody->SetFreezePositionZ(freezePositionZ);
} }
void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept
{ {
if (rigidBody)
rigidBody->SetFreezeRotationX(freezeRotationX);
} }
void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept
{ {
if (rigidBody)
rigidBody->SetFreezeRotationY(freezeRotationY);
} }
void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept
{ {
if (rigidBody)
rigidBody->SetFreezeRotationZ(freezeRotationZ);
} }
void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept
{ {
interpolate = allowInterpolation;
}
void SHRigidBodyComponent::SetGravityScale(float gravityScale) noexcept
{
if (rigidBody)
rigidBody->SetGravityScale(gravityScale);
}
void SHRigidBodyComponent::SetMass(float newMass) noexcept
{
if (rigidBody)
rigidBody->SetMass(newMass);
} }
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
{ {
if (rigidBody)
rigidBody->SetLinearDrag(newDrag);
} }
void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept
{ {
} }
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
{ {
if (rigidBody)
rigidBody->SetLinearVelocity(newLinearVelocity);
} }
void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
{ {
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */ /* Member Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHRigidBodyComponent::OnCreate()
{
}
void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept
{ {
if (rigidBody)
rigidBody->AddForce(force);
} }
void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept
@ -221,12 +312,13 @@ namespace SHADE
void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept
{ {
if (rigidBody)
rigidBody->AddForce(force, worldPos);
} }
void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept
{ {
} }
void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept
@ -251,7 +343,8 @@ namespace SHADE
void SHRigidBodyComponent::ClearForces() const noexcept void SHRigidBodyComponent::ClearForces() const noexcept
{ {
if (rigidBody)
rigidBody->ClearForces();
} }
void SHRigidBodyComponent::ClearTorque() const noexcept void SHRigidBodyComponent::ClearTorque() const noexcept
@ -259,6 +352,15 @@ namespace SHADE
} }
/*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
void SHRigidBodyComponent::OnCreate()
{
}
} // namespace SHADE } // namespace SHADE
RTTR_REGISTRATION RTTR_REGISTRATION
@ -274,17 +376,19 @@ RTTR_REGISTRATION
); );
registration::class_<SHRigidBodyComponent>("RigidBody Component") registration::class_<SHRigidBodyComponent>("RigidBody Component")
.property("Type" , &SHRigidBodyComponent::GetType , &SHRigidBodyComponent::SetType ) .property("Type" , &SHRigidBodyComponent::GetType , &SHRigidBodyComponent::SetType )
//.property("Mass" , &SHRigidBodyComponent::GetMass , &SHRigidBodyComponent::SetMass ) .property("Auto Mass" , &SHRigidBodyComponent::GetAutoMass , &SHRigidBodyComponent::SetAutoMass )
.property("Drag" , &SHRigidBodyComponent::GetDrag , &SHRigidBodyComponent::SetDrag ) .property("Mass" , &SHRigidBodyComponent::GetMass , &SHRigidBodyComponent::SetMass )
.property("Angular Drag" , &SHRigidBodyComponent::GetAngularDrag , &SHRigidBodyComponent::SetAngularDrag ) .property("Drag" , &SHRigidBodyComponent::GetDrag , &SHRigidBodyComponent::SetDrag )
.property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetGravityEnabled ) .property("Angular Drag" , &SHRigidBodyComponent::GetAngularDrag , &SHRigidBodyComponent::SetAngularDrag )
.property("Interpolate" , &SHRigidBodyComponent::IsInterpolating , &SHRigidBodyComponent::SetInterpolate ) .property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetIsGravityEnabled )
.property("Sleeping Enabled" , &SHRigidBodyComponent::IsAllowedToSleep , &SHRigidBodyComponent::SetIsAllowedToSleep) .property("Gravity Scale" , &SHRigidBodyComponent::GetGravityScale , &SHRigidBodyComponent::SetGravityScale )
.property("Freeze Position X" , &SHRigidBodyComponent::GetFreezePositionX , &SHRigidBodyComponent::SetFreezePositionX ) .property("Interpolate" , &SHRigidBodyComponent::IsInterpolating , &SHRigidBodyComponent::SetInterpolate )
.property("Freeze Position Y" , &SHRigidBodyComponent::GetFreezePositionY , &SHRigidBodyComponent::SetFreezePositionY ) .property("Sleeping Enabled" , &SHRigidBodyComponent::IsAllowedToSleep , &SHRigidBodyComponent::SetIsAllowedToSleep )
.property("Freeze Position Z" , &SHRigidBodyComponent::GetFreezePositionZ , &SHRigidBodyComponent::SetFreezePositionZ ) .property("Freeze Position X" , &SHRigidBodyComponent::GetFreezePositionX , &SHRigidBodyComponent::SetFreezePositionX )
.property("Freeze Rotation X" , &SHRigidBodyComponent::GetFreezeRotationX , &SHRigidBodyComponent::SetFreezeRotationX ) .property("Freeze Position Y" , &SHRigidBodyComponent::GetFreezePositionY , &SHRigidBodyComponent::SetFreezePositionY )
.property("Freeze Rotation Y" , &SHRigidBodyComponent::GetFreezeRotationY , &SHRigidBodyComponent::SetFreezeRotationY ) .property("Freeze Position Z" , &SHRigidBodyComponent::GetFreezePositionZ , &SHRigidBodyComponent::SetFreezePositionZ )
.property("Freeze Rotation Z" , &SHRigidBodyComponent::GetFreezeRotationZ , &SHRigidBodyComponent::SetFreezeRotationZ ); .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

@ -15,10 +15,15 @@
// Project Headers // Project Headers
#include "ECS_Base/Components/SHComponent.h" #include "ECS_Base/Components/SHComponent.h"
#include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec3.h"
#include "Math/SHQuaternion.h"
namespace SHADE namespace SHADE
{ {
/*-------------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-------------------------------------------------------------------------------------*/
class SHRigidBody;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -67,13 +72,13 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] Type GetType () const noexcept;
[[nodiscard]] bool IsGravityEnabled () const noexcept; [[nodiscard]] bool IsGravityEnabled () const noexcept;
[[nodiscard]] bool IsAllowedToSleep () const noexcept; [[nodiscard]] bool IsAllowedToSleep () const noexcept;
[[nodiscard]] bool IsInterpolating () const noexcept; [[nodiscard]] bool IsInterpolating () const noexcept;
[[nodiscard]] bool IsSleeping () const noexcept;
[[nodiscard]] bool GetIsSleeping () const noexcept; [[nodiscard]] bool GetAutoMass () const noexcept;
[[nodiscard]] Type GetType () const noexcept;
[[nodiscard]] bool GetFreezePositionX () const noexcept; [[nodiscard]] bool GetFreezePositionX () const noexcept;
[[nodiscard]] bool GetFreezePositionY () const noexcept; [[nodiscard]] bool GetFreezePositionY () const noexcept;
@ -82,6 +87,7 @@ namespace SHADE
[[nodiscard]] bool GetFreezeRotationY () const noexcept; [[nodiscard]] bool GetFreezeRotationY () const noexcept;
[[nodiscard]] bool GetFreezeRotationZ () const noexcept; [[nodiscard]] bool GetFreezeRotationZ () const noexcept;
[[nodiscard]] float GetGravityScale () const noexcept;
[[nodiscard]] float GetMass () const noexcept; [[nodiscard]] float GetMass () const noexcept;
[[nodiscard]] float GetDrag () const noexcept; [[nodiscard]] float GetDrag () const noexcept;
[[nodiscard]] float GetAngularDrag () const noexcept; [[nodiscard]] float GetAngularDrag () const noexcept;
@ -91,18 +97,18 @@ namespace SHADE
[[nodiscard]] SHVec3 GetLinearVelocity () const noexcept; [[nodiscard]] SHVec3 GetLinearVelocity () const noexcept;
[[nodiscard]] SHVec3 GetAngularVelocity () const noexcept; [[nodiscard]] SHVec3 GetAngularVelocity () const noexcept;
//[[nodiscard]] const SHVec3& GetPosition () const noexcept;
//[[nodiscard]] const SHQuaternion& GetOrientation () const noexcept;
//[[nodiscard]] SHVec3 GetRotation () const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SetType (Type newType) noexcept; void SetType (Type newType) noexcept;
void SetGravityEnabled (bool enableGravity) noexcept; void SetRigidBody (SHRigidBody* rb) noexcept;
void SetIsGravityEnabled (bool enableGravity) noexcept;
void SetIsAllowedToSleep (bool isAllowedToSleep) noexcept; void SetIsAllowedToSleep (bool isAllowedToSleep) noexcept;
void SetAutoMass (bool autoMass) noexcept;
void SetFreezePositionX (bool freezePositionX) noexcept; void SetFreezePositionX (bool freezePositionX) noexcept;
void SetFreezePositionY (bool freezePositionY) noexcept; void SetFreezePositionY (bool freezePositionY) noexcept;
void SetFreezePositionZ (bool freezePositionZ) noexcept; void SetFreezePositionZ (bool freezePositionZ) noexcept;
@ -110,9 +116,9 @@ namespace SHADE
void SetFreezeRotationY (bool freezeRotationY) noexcept; void SetFreezeRotationY (bool freezeRotationY) noexcept;
void SetFreezeRotationZ (bool freezeRotationZ) noexcept; void SetFreezeRotationZ (bool freezeRotationZ) noexcept;
void SetInterpolate (bool allowInterpolation) noexcept; void SetInterpolate (bool allowInterpolation) noexcept;
//void SetAutoMass (bool autoMass) noexcept;
//void SetMass (float newMass) noexcept; void SetGravityScale (float gravityScale) noexcept;
void SetMass (float newMass) noexcept;
void SetDrag (float newDrag) noexcept; void SetDrag (float newDrag) noexcept;
void SetAngularDrag (float newAngularDrag) noexcept; void SetAngularDrag (float newAngularDrag) noexcept;
@ -142,6 +148,11 @@ namespace SHADE
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
Type type;
bool interpolate;
SHRigidBody* rigidBody;
RTTR_ENABLE() RTTR_ENABLE()
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -19,53 +19,9 @@ namespace SHADE
/* Constructors & Destructor Definitions */ /* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHPhysicsWorldState::SHPhysicsWorldState() noexcept
: world { nullptr }
{}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Public Function Members Definitions */ /* Public Function Members Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHPhysicsWorldState::CreateWorld(rp3d::PhysicsCommon& factory)
{
rp3d::PhysicsWorld::WorldSettings rp3dWorldSettings;
rp3dWorldSettings.gravity = settings.gravity;
rp3dWorldSettings.defaultVelocitySolverNbIterations = settings.numVelocitySolverIterations;
rp3dWorldSettings.defaultPositionSolverNbIterations = settings.numPositionSolverIterations;
rp3dWorldSettings.isSleepingEnabled = settings.sleepingEnabled;
// These are my preferred default values. QoL for modifying these.
rp3dWorldSettings.defaultBounciness = 0.0f;
rp3dWorldSettings.defaultFrictionCoefficient = 0.4f;
world = factory.createPhysicsWorld(rp3dWorldSettings);
world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES);
}
void SHPhysicsWorldState::DestroyWorld(rp3d::PhysicsCommon& factory)
{
if (!world)
return;
factory.destroyPhysicsWorld(world);
world = nullptr;
}
void SHPhysicsWorldState::UpdateSettings() const noexcept
{
if (!world)
{
SHLOGV_ERROR("Unable to update Physics World settings without creating a world!")
return;
}
world->setGravity(settings.gravity);
world->setNbIterationsVelocitySolver(settings.numVelocitySolverIterations);
world->setNbIterationsPositionSolver(settings.numPositionSolverIterations);
world->enableSleeping(settings.sleepingEnabled);
}
} // namespace SHADE } // namespace SHADE

View File

@ -10,8 +10,6 @@
#pragma once #pragma once
#include <reactphysics3d/reactphysics3d.h>
// Project Headers // Project Headers
#include "Math/SHMath.h" #include "Math/SHMath.h"
#include "SH_API.h" #include "SH_API.h"
@ -47,7 +45,6 @@ namespace SHADE
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
rp3d::PhysicsWorld* world;
WorldSettings settings; WorldSettings settings;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -60,14 +57,6 @@ namespace SHADE
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void CreateWorld (rp3d::PhysicsCommon& factory);
void DestroyWorld (rp3d::PhysicsCommon& factory);
/**
* @brief Applies the current settings to the physics world. The world must be created
* before this is called.
*/
void UpdateSettings () const noexcept;
}; };

View File

@ -1,7 +1,7 @@
/**************************************************************************************** /****************************************************************************************
* \file SHPhysicsSystemRoutines.h * \file SHPhysicsPostUpdateRoutine.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520 * \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for the Physics System Routines * \brief Implementation for the Physics Post-Update Routine
* *
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent * disclosure of this file or its contents without the prior written consent
@ -11,24 +11,12 @@
#include <SHpch.h> #include <SHpch.h>
// Primary Header // Primary Header
#include "SHPhysicsSystem.h" #include "Physics/System/SHPhysicsSystem.h"
// Project Headers // Project Headers
#include "ECS_Base/Managers/SHEntityManager.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/SHEditor.h"
#include "Scene/SHSceneManager.h"
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
#include "Input/SHInputManager.h"
#include "Physics/Collision/SHCollisionTagMatrix.h"
/*-------------------------------------------------------------------------------------*/
/* Local Functions */
/*-------------------------------------------------------------------------------------*/
void testFunction();
/////////////////////////////////////////////////////////////////////////////////////////
namespace SHADE namespace SHADE
{ {
@ -36,59 +24,14 @@ namespace SHADE
/* Constructors & Destructor Definitions */ /* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHPhysicsSystem::PhysicsPreUpdate::PhysicsPreUpdate()
: SHSystemRoutine { "Physics PreUpdate", true }
{}
SHPhysicsSystem::PhysicsFixedUpdate::PhysicsFixedUpdate()
: SHFixedSystemRoutine { DEFAULT_FIXED_STEP, "Physics FixedUpdate", false }
{}
SHPhysicsSystem::PhysicsPostUpdate::PhysicsPostUpdate() SHPhysicsSystem::PhysicsPostUpdate::PhysicsPostUpdate()
: SHSystemRoutine { "Physics PostUpdate", false } : SHSystemRoutine { "Physics Post-Update", false }
{} {}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */ /* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept
{
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
}
void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept
{
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
if (scriptingSystem == nullptr)
{
SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
}
const double FIXED_DT = physicsSystem->fixedDT;
accumulatedTime += dt;
int count = 0;
while (accumulatedTime > FIXED_DT)
{
if (scriptingSystem != nullptr)
scriptingSystem->ExecuteFixedUpdates();
// TODO: Update World
accumulatedTime -= FIXED_DT;
++count;
}
stats.numSteps = count;
physicsSystem->worldUpdated = count > 0;
physicsSystem->interpolationFactor = accumulatedTime / fixedTimeStep;
}
void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept
{ {
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem()); auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
@ -110,6 +53,10 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */ /* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
} // namespace SHADE
void SHPhysicsSystem::PhysicsPostUpdate::syncTransforms(SHRigidBodyComponent* rbComponent) const noexcept
{
}
}

View File

@ -0,0 +1,62 @@
/****************************************************************************************
* \file SHPhysicsPreUpdateRoutine.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for the Physics Pre-Update Routine
*
* \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 "Physics/System/SHPhysicsSystem.h"
// Project Headers
#include "ECS_Base/Managers/SHComponentManager.h"
#include "Math/Transform/SHTransformComponent.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsSystem::PhysicsPreUpdate::PhysicsPreUpdate()
: SHSystemRoutine { "Physics Pre-Update", true }
{}
/*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept
{
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
// Get all physics objects & sync transforms
for (auto& physicsObject : physicsSystem->physicsObjectManager.GetPhysicsObjects() | std::views::values)
syncTransforms(&physicsObject);
}
/*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsSystem::PhysicsPreUpdate::syncTransforms(SHPhysicsObject* physicsObject) const noexcept
{
const EntityID EID = physicsObject->entityID;
// Get relevant components: Transform, Rigidbody & Collider
const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent_s<SHTransformComponent>(EID);
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(EID);
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(EID);
if (TRANSFORM_COMPONENT && TRANSFORM_COMPONENT->HasChanged())
{
// Sync the objects transforms
}
}
}

View File

@ -0,0 +1,62 @@
/****************************************************************************************
* \file SHPhysicsUpdateRoutine.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for the Physics Update Routine
*
* \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 "Physics/System/SHPhysicsSystem.h"
// Project Headers
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Scripting/SHScriptEngine.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsSystem::PhysicsUpdate::PhysicsUpdate()
: SHFixedSystemRoutine { DEFAULT_FIXED_STEP, "Physics Update", false }
{}
/*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsSystem::PhysicsUpdate::Execute(double dt) noexcept
{
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
auto* scriptEngine = SHSystemManager::GetSystem<SHScriptEngine>();
if (!scriptEngine)
{
SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing ScriptEngine!")
}
const double FIXED_DT = physicsSystem->fixedDT;
accumulatedTime += dt;
int count = 0;
while (accumulatedTime > FIXED_DT)
{
accumulatedTime -= FIXED_DT;
++count;
}
stats.numSteps = count;
physicsSystem->worldUpdated = count > 0;
physicsSystem->interpolationFactor = physicsSystem->worldUpdated ? accumulatedTime / FIXED_DT : 0.0;
}
} // namespace SHADE

View File

@ -20,9 +20,7 @@
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/SHEditor.h" #include "Editor/SHEditor.h"
#include "Physics/Collision/SHCollisionTagMatrix.h" #include "Physics/Collision/SHCollisionTagMatrix.h"
#include "Physics/SHPhysicsEvents.h" #include "Physics/Interface/SHColliderComponent.h"
#include "Scene/SHSceneManager.h"
#include "Scripting/SHScriptEngine.h"
namespace SHADE namespace SHADE
{ {
@ -34,7 +32,18 @@ namespace SHADE
: worldUpdated { false } : worldUpdated { false }
, interpolationFactor { 0.0 } , interpolationFactor { 0.0 }
, fixedDT { DEFAULT_FIXED_STEP } , fixedDT { DEFAULT_FIXED_STEP }
{} {
// Add more events here to register them
eventFunctions[0] = { &SHPhysicsSystem::onComponentAdded , SH_COMPONENT_ADDED_EVENT };
eventFunctions[1] = { &SHPhysicsSystem::onComponentRemoved, SH_COMPONENT_REMOVED_EVENT };
eventFunctions[2] = { &SHPhysicsSystem::onSceneInit , SH_SCENE_ON_INIT_EVENT };
eventFunctions[3] = { &SHPhysicsSystem::onSceneExit , SH_SCENE_ON_EXIT_EVENT };
#ifdef SHEDITOR
eventFunctions[4] = { &SHPhysicsSystem::onEditorPlay , SH_EDITOR_ON_PLAY_EVENT };
#endif
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */ /* Getter Function Definitions */
@ -45,13 +54,48 @@ namespace SHADE
return 1.0 / fixedDT; return 1.0 / fixedDT;
} }
double SHPhysicsSystem::GetFixedDT() const noexcept
{
return fixedDT;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */ /* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHPhysicsSystem::SetFixedUpdateRate(double fixedUpdateRate) noexcept void SHPhysicsSystem::SetFixedUpdateRate(double fixedUpdateRate) noexcept
{ {
// Handle invalid input
if (fixedUpdateRate <= 0.0)
{
SHLOGV_WARNING("Invalid value for setting fixed update rate! Fixed update rate unchanged.")
return;
}
fixedDT = 1.0 / fixedUpdateRate; fixedDT = 1.0 / fixedUpdateRate;
// Handle potential incorrect / unintended input
if (fixedDT > 1.0)
{
SHLOGV_WARNING("Fixed Update Rate Time is set below 1. This may result in undesirable behaviour.")
}
}
void SHPhysicsSystem::SetFixedDT(double fixedDt) noexcept
{
if (fixedDt <= 0.0)
{
SHLOGV_WARNING("Invalid value for setting fixed delta time! Fixed delta time unchanged.")
return;
}
fixedDT = fixedDt;
// Handle potential incorrect / unintended input
if (fixedDT > 1.0)
{
SHLOGV_WARNING("Fixed Delta Time is set above 1. This may result in undesirable behaviour.")
}
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -64,11 +108,21 @@ namespace SHADE
std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT }; std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT };
defaultCollisionTagNameFilePath.append("CollisionTags.SHConfig"); defaultCollisionTagNameFilePath.append("CollisionTags.SHConfig");
SHCollisionTagMatrix::Init(defaultCollisionTagNameFilePath); SHCollisionTagMatrix::Init(defaultCollisionTagNameFilePath);
// Link Managers to system
// Register Events
for (int i = 0; i < NUM_EVENT_FUNCTIONS; ++i)
{
const std::shared_ptr EVENT_RECEIVER = std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, eventFunctions[i].first);
const ReceiverPtr EVENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(EVENT_RECEIVER);
SHEventManager::SubscribeTo(eventFunctions[i].second, EVENT_RECEIVER_PTR);
}
} }
void SHPhysicsSystem::Exit() void SHPhysicsSystem::Exit()
{ {
// Write collision tag names to file // Write collision tag names to file
std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT }; std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT };
defaultCollisionTagNameFilePath.append("CollisionTags.SHConfig"); defaultCollisionTagNameFilePath.append("CollisionTags.SHConfig");
@ -84,4 +138,98 @@ namespace SHADE
/* Private Function Member Definitions */ /* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHEventHandle SHPhysicsSystem::onSceneInit(SHEventPtr onSceneInitEvent)
{
/*
* TODO:
* If a world already exists, destroy it
* Recreate the world
*
* If there is an editor and editor mode is already playing, link all entities with the world immediately.
*/
return onSceneInitEvent.get()->handle;
}
SHEventHandle SHPhysicsSystem::onSceneExit(SHEventPtr onSceneExitEvent)
{
/*
* TODO:
* Destroy the physics world.
* Destroy all physics objects.
*/
return onSceneExitEvent.get()->handle;
}
SHEventHandle SHPhysicsSystem::onComponentAdded(SHEventPtr onComponentAddedEvent)
{
static const auto RIGID_BODY_COMPONENT_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
static const auto COLLIDER_COMPONENT_ID = ComponentFamily::GetID<SHColliderComponent>();
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentAddedEvent>*>(onComponentAddedEvent.get())->data;
const auto ADDED_ID = EVENT_DATA->addedComponentType;
const bool IS_RIGID_BODY = ADDED_ID == RIGID_BODY_COMPONENT_ID;
const bool IS_COLLIDER = ADDED_ID == COLLIDER_COMPONENT_ID;
// Check if its a physics component
if (IS_RIGID_BODY || IS_COLLIDER)
{
const EntityID EID = EVENT_DATA->eid;
// Link engine components with physics object component
if (IS_RIGID_BODY)
physicsObjectManager.AddRigidBody(EID);
if (IS_COLLIDER)
physicsObjectManager.AddCollider(EID);
}
return onComponentAddedEvent.get()->handle;
}
SHEventHandle SHPhysicsSystem::onComponentRemoved(SHEventPtr onComponentRemovedEvent)
{
static const auto RIGID_BODY_COMPONENT_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
static const auto COLLIDER_COMPONENT_ID = ComponentFamily::GetID<SHColliderComponent>();
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentRemovedEvent>*>(onComponentRemovedEvent.get())->data;
const auto REMOVED_DATA = EVENT_DATA->removedComponentType;
const bool IS_RIGID_BODY = REMOVED_DATA == RIGID_BODY_COMPONENT_ID;
const bool IS_COLLIDER = REMOVED_DATA == COLLIDER_COMPONENT_ID;
// Check if its a physics component
if (IS_RIGID_BODY || IS_COLLIDER)
{
const EntityID EID = EVENT_DATA->eid;
// Link engine components with physics object component
if (IS_RIGID_BODY)
physicsObjectManager.RemoveRigidBody(EID);
if (IS_COLLIDER)
physicsObjectManager.RemoveCollider(EID);
}
return onComponentRemovedEvent.get()->handle;
}
#ifdef SHEDITOR
SHEventHandle SHPhysicsSystem::onEditorPlay(SHEventPtr onEditorPlayEvent)
{
/*
* TODO:
* Link all entities with the world.
*/
return onEditorPlayEvent.get()->handle;
}
#endif
} // namespace SHADE } // namespace SHADE

View File

@ -11,14 +11,15 @@
#pragma once #pragma once
// Project Headers // Project Headers
#include "ECS_Base/System/SHSystem.h"
#include "ECS_Base/System/SHSystemRoutine.h" #include "ECS_Base/System/SHSystemRoutine.h"
#include "ECS_Base/System/SHFixedSystemRoutine.h" #include "ECS_Base/System/SHFixedSystemRoutine.h"
#include "Events/SHEvent.h"
#include "Math/Transform/SHTransformComponent.h" #include "Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h"
#include "Physics/Interface/SHRigidBodyComponent.h" #include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
#include "Physics/Interface/SHColliderComponent.h" #include "Physics/Interface/SHColliderComponent.h"
#include "Physics/SHPhysicsWorld.h"
#include "Scene/SHSceneGraph.h"
namespace SHADE namespace SHADE
{ {
@ -28,13 +29,6 @@ namespace SHADE
class SH_API SHPhysicsSystem final : public SHSystem class SH_API SHPhysicsSystem final : public SHSystem
{ {
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHPhysicsDebugDrawSystem;
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */ /* Constructors & Destructor */
@ -46,104 +40,121 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] double GetFixedUpdateRate () const noexcept; [[nodiscard]] double GetFixedUpdateRate() const noexcept;
[[nodiscard]] const SHPhysicsWorldState::WorldSettings& GetWorldSettings () const noexcept; [[nodiscard]] double GetFixedDT() const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SetFixedUpdateRate (double fixedUpdateRate) noexcept; void SetFixedUpdateRate(double fixedUpdateRate) noexcept;
void SetWorldSettings (const SHPhysicsWorldState::WorldSettings& settings) noexcept; void SetFixedDT(double fixedDt) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void Init () override; void Init() override;
void Exit () override; void Exit() override;
void ForceUpdate (); void ForceUpdate();
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* System Routines */ /* System Routines */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/**
* @brief
* The physics update routine that runs before the simulation is updated.
* This is always running, regardless of the editor state.
* <br/>
* This update game logic is applied before the simulation runs.
*/
class SH_API PhysicsPreUpdate final : public SHSystemRoutine class SH_API PhysicsPreUpdate final : public SHSystemRoutine
{ {
public: public:
/*-------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-------------------------------------------------------------------------------*/
PhysicsPreUpdate(); PhysicsPreUpdate();
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
void Execute(double dt) noexcept override; void Execute(double dt) noexcept override;
private: private:
/*-------------------------------------------------------------------------------*/ void syncTransforms(SHPhysicsObject* physicsObject) const noexcept;
/* Function Members */
/*-------------------------------------------------------------------------------*/
}; };
class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine /**
* @brief
* The physics update routine that runs at a fixed rate. This is where the main
* simulation runs. If delta time is large enough, this may run more than once per
* frame. If delta time is small enough, this may not run at all.
*/
class SH_API PhysicsUpdate final : public SHFixedSystemRoutine
{ {
public: public:
/*-------------------------------------------------------------------------------*/ PhysicsUpdate();
/* Constructors & Destructor */ void Execute(double dt) noexcept override;
/*-------------------------------------------------------------------------------*/
PhysicsFixedUpdate();
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
void Execute (double dt) noexcept override;
}; };
/**
* @brief
* The physics update that runs after the simulation. This sets the rendering
* transforms and sends messages to scripting system for collision & trigger events.
*/
class SH_API PhysicsPostUpdate final : public SHSystemRoutine class SH_API PhysicsPostUpdate final : public SHSystemRoutine
{ {
public: public:
/*-------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-------------------------------------------------------------------------------*/
PhysicsPostUpdate(); PhysicsPostUpdate();
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
void Execute(double dt) noexcept override; void Execute(double dt) noexcept override;
private: private:
void syncTransforms(SHRigidBodyComponent* rbComponent) const noexcept;
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
}; };
private: private:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
using EventFunctionPair = std::pair<SHEventHandle(SHPhysicsSystem::*)(SHEventPtr), SHEventIdentifier>;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
#ifdef SHEDITOR
static constexpr int NUM_EVENT_FUNCTIONS = 5;
#else
static constexpr int NUM_EVENT_FUNCTIONS = 4;
#endif
// Event function container for cleanly registering to events
EventFunctionPair eventFunctions[NUM_EVENT_FUNCTIONS];
// System data // System data
bool worldUpdated; bool worldUpdated;
double interpolationFactor; double interpolationFactor;
double fixedDT; double fixedDT;
// Sub-systems / managers
SHPhysicsObjectManager physicsObjectManager;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHEventHandle onSceneInit (SHEventPtr onSceneInitEvent);
SHEventHandle onSceneExit (SHEventPtr onSceneExitEvent);
SHEventHandle onComponentAdded (SHEventPtr onComponentAddedEvent);
SHEventHandle onComponentRemoved (SHEventPtr onComponentRemovedEvent);
#ifdef SHEDITOR
SHEventHandle onEditorPlay (SHEventPtr onEditorPlayEvent);
// We don't need an onEditorStop because on stop exits the scene, which is already handled above.
#endif
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -15,7 +15,7 @@
#include "Camera/SHCameraArmComponent.h" #include "Camera/SHCameraArmComponent.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Physics/Interface/SHRigidBodyComponent.h" #include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
#include "UI/SHCanvasComponent.h" #include "UI/SHCanvasComponent.h"
#include "UI/SHButtonComponent.h" #include "UI/SHButtonComponent.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"

View File

@ -34,7 +34,7 @@ namespace SHADE
} }
void RigidBody::IsGravityEnabled::set(bool value) void RigidBody::IsGravityEnabled::set(bool value)
{ {
return GetNativeComponent()->SetGravityEnabled(value); return GetNativeComponent()->SetIsGravityEnabled(value);
} }
bool RigidBody::IsAllowedToSleep::get() bool RigidBody::IsAllowedToSleep::get()
{ {

View File

@ -15,7 +15,7 @@ of DigiPen Institute of Technology is prohibited.
#pragma once #pragma once
// External Dependencies // External Dependencies
#include "Physics/Interface/SHRigidBodyComponent.h" #include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
// Project Includes // Project Includes
#include "Components/Component.hxx" #include "Components/Component.hxx"

View File

@ -23,7 +23,7 @@ of DigiPen Institute of Technology is prohibited.
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Physics/Interface/SHColliderComponent.h" #include "Physics/Interface/SHColliderComponent.h"
#include "Physics/Interface/SHRigidBodyComponent.h" #include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
#include "Scene/SHSceneGraph.h" #include "Scene/SHSceneGraph.h"
#include "Tools/Logger/SHLog.h" #include "Tools/Logger/SHLog.h"