diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp index e3989d6e..16863dbd 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp @@ -18,12 +18,6 @@ #include "Math/SHMathHelpers.h" #include "Math/SHQuaternion.h" -/*-------------------------------------------------------------------------------------*/ -/* Local Function Definitions */ -/*-------------------------------------------------------------------------------------*/ - - - namespace SHADE { /*-----------------------------------------------------------------------------------*/ @@ -31,8 +25,7 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHRigidBodyComponent::SHRigidBodyComponent() noexcept - : rigidBody { nullptr } - , type { Type::DYNAMIC } + : type { Type::DYNAMIC } , mass { 1.0f } , drag { 0.01f } , angularDrag { 0.01f } @@ -41,13 +34,11 @@ namespace SHADE // Set default flags: Gravity & Sleeping enabled flags |= 1U << 0; flags |= 1U << 1; - - // TODO(Diren): Send an update command to the physics system } SHRigidBodyComponent::~SHRigidBodyComponent() { - rigidBody = nullptr; + } /*-----------------------------------------------------------------------------------*/ @@ -57,9 +48,10 @@ namespace SHADE bool SHRigidBodyComponent::IsGravityEnabled() const noexcept { const bool GRAVITY = flags & (1U << 0); - if (rigidBody) + if (rp3dBody) { - SHASSERT(rigidBody->isGravityEnabled() == GRAVITY, "ReactPhysics and SHADE body enable gravity do not match!") + + SHASSERT(reinterpret_cast(rp3dBody)->isGravityEnabled() == GRAVITY, "ReactPhysics and SHADE body enable gravity do not match!") } return GRAVITY; @@ -68,21 +60,26 @@ namespace SHADE bool SHRigidBodyComponent::IsSleepingEnabled() const noexcept { const bool SLEEP = flags & (1U << 1); - if (rigidBody) + if (rp3dBody) { - SHASSERT(rigidBody->isAllowedToSleep() == SLEEP, "ReactPhysics and SHADE body enable sleep do not match!") + SHASSERT(reinterpret_cast(rp3dBody)->isAllowedToSleep() == SLEEP, "ReactPhysics and SHADE body enable sleep do not match!") } return SLEEP; } + bool SHRigidBodyComponent::IsInterpolating() const noexcept + { + return interpolate; + } + SHRigidBodyComponent::Type SHRigidBodyComponent::GetType() const noexcept { - if (rigidBody) + if (rp3dBody) { SHASSERT ( - SHUtilities::ConvertEnum(rigidBody->getType()) == SHUtilities::ConvertEnum(type), + SHUtilities::ConvertEnum(reinterpret_cast(rp3dBody)->getType()) == SHUtilities::ConvertEnum(type), "ReactPhysics and SHADE body types do not match!" ) } @@ -92,9 +89,9 @@ namespace SHADE float SHRigidBodyComponent::GetMass() const noexcept { - if (rigidBody) + if (rp3dBody) { - SHASSERT(rigidBody->getMass() == mass, "ReactPhysics and SHADE body masses do not match!") + SHASSERT(reinterpret_cast(rp3dBody)->getMass() == mass, "ReactPhysics and SHADE body masses do not match!") } return mass; @@ -102,11 +99,11 @@ namespace SHADE float SHRigidBodyComponent::GetDrag() const noexcept { - if (rigidBody) + if (rp3dBody) { SHASSERT ( - SHMath::CompareFloat(rigidBody->getLinearDamping(), drag), + SHMath::CompareFloat(reinterpret_cast(rp3dBody)->getLinearDamping(), drag), "ReactPhysics and SADE body drag coefficients do not match!" ) } @@ -116,11 +113,11 @@ namespace SHADE float SHRigidBodyComponent::GetAngularDrag() const noexcept { - if (rigidBody) + if (rp3dBody) { SHASSERT ( - SHMath::CompareFloat(rigidBody->getAngularDamping(), angularDrag), + SHMath::CompareFloat(reinterpret_cast(rp3dBody)->getAngularDamping(), angularDrag), "ReactPhysics and SADE body drag coefficients do not match!" ) } @@ -131,9 +128,9 @@ namespace SHADE bool SHRigidBodyComponent::GetFreezePositionX() const noexcept { const bool FREEZE_X_POS = flags & (1U << 2); - if (rigidBody) + if (rp3dBody) { - const bool RP3D_FREEZE_X_POS = fabs(rigidBody->getLinearLockAxisFactor().x) > 0.0f; + const bool RP3D_FREEZE_X_POS = fabs(reinterpret_cast(rp3dBody)->getLinearLockAxisFactor().x) > 0.0f; SHASSERT(RP3D_FREEZE_X_POS == FREEZE_X_POS, "ReactPhysics and SHADE body x-axis position lock do not match!") } @@ -143,9 +140,9 @@ namespace SHADE bool SHRigidBodyComponent::GetFreezePositionY() const noexcept { const bool FREEZE_Y_POS = flags & (1U << 3); - if (rigidBody) + if (rp3dBody) { - const bool RP3D_FREEZE_Y_POS = fabs(rigidBody->getLinearLockAxisFactor().y) > 0.0f; + const bool RP3D_FREEZE_Y_POS = fabs(reinterpret_cast(rp3dBody)->getLinearLockAxisFactor().y) > 0.0f; SHASSERT(RP3D_FREEZE_Y_POS == FREEZE_Y_POS, "ReactPhysics and SHADE body y-axis position lock do not match!") } @@ -155,9 +152,9 @@ namespace SHADE bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept { const bool FREEZE_Z_POS = flags & (1U << 4); - if (rigidBody) + if (rp3dBody) { - const bool RP3D_FREEZE_Z_POS = fabs(rigidBody->getLinearLockAxisFactor().z) > 0.0f; + const bool RP3D_FREEZE_Z_POS = fabs(reinterpret_cast(rp3dBody)->getLinearLockAxisFactor().z) > 0.0f; SHASSERT(RP3D_FREEZE_Z_POS == FREEZE_Z_POS, "ReactPhysics and SHADE body z-axis position lock do not match!") } @@ -167,9 +164,9 @@ namespace SHADE bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept { const bool FREEZE_X_ROT = flags & (1U << 5); - if (rigidBody) + if (rp3dBody) { - const bool RP3D_FREEZE_Y_ROT = fabs(rigidBody->getAngularLockAxisFactor().x) > 0.0f; + const bool RP3D_FREEZE_Y_ROT = fabs(reinterpret_cast(rp3dBody)->getAngularLockAxisFactor().x) > 0.0f; SHASSERT(RP3D_FREEZE_Y_ROT == FREEZE_X_ROT, "ReactPhysics and SHADE body x-axis rotation lock do not match!") } @@ -179,9 +176,9 @@ namespace SHADE bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept { const bool FREEZE_Y_ROT = flags & (1U << 6); - if (rigidBody) + if (rp3dBody) { - const bool RP3D_FREEZE_Y_ROT = fabs(rigidBody->getAngularLockAxisFactor().y) > 0.0f; + const bool RP3D_FREEZE_Y_ROT = fabs(reinterpret_cast(rp3dBody)->getAngularLockAxisFactor().y) > 0.0f; SHASSERT(RP3D_FREEZE_Y_ROT == FREEZE_Y_ROT, "ReactPhysics and SHADE body y-axis rotation lock do not match!") } @@ -191,9 +188,9 @@ namespace SHADE bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept { const bool FREEZE_Z_ROT = flags & (1U << 7); - if (rigidBody) + if (rp3dBody) { - const bool RP3D_FREEZE_Z_ROT = fabs(rigidBody->getAngularLockAxisFactor().z) > 0.0f; + const bool RP3D_FREEZE_Z_ROT = fabs(reinterpret_cast(rp3dBody)->getAngularLockAxisFactor().z) > 0.0f; SHASSERT(RP3D_FREEZE_Z_ROT == FREEZE_Z_ROT, "ReactPhysics and SHADE body z-axis rotation lock do not match!") } @@ -204,9 +201,9 @@ namespace SHADE { SHVec3 result; - if (rigidBody) + if (rp3dBody) { - const auto RP3D_RESULT = rigidBody->getForce(); + const auto& RP3D_RESULT = reinterpret_cast(rp3dBody)->getForce(); result = SHVec3{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z }; } @@ -217,9 +214,9 @@ namespace SHADE { SHVec3 result; - if (rigidBody) + if (rp3dBody) { - const auto RP3D_RESULT = rigidBody->getTorque(); + const auto& RP3D_RESULT = reinterpret_cast(rp3dBody)->getTorque(); result = SHVec3{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z }; } @@ -230,9 +227,9 @@ namespace SHADE { SHVec3 result; - if (rigidBody) + if (rp3dBody) { - const auto RP3D_RESULT = rigidBody->getLinearVelocity(); + const auto& RP3D_RESULT = reinterpret_cast(rp3dBody)->getLinearVelocity(); result = SHVec3{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z }; } @@ -243,41 +240,15 @@ namespace SHADE { SHVec3 result; - if (rigidBody) + if (rp3dBody) { - const auto RP3D_RESULT = rigidBody->getAngularVelocity(); + const auto& RP3D_RESULT = reinterpret_cast(rp3dBody)->getAngularVelocity(); result = SHVec3{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z }; } return result; } - SHVec3 SHRigidBodyComponent::GetPosition() const noexcept - { - SHVec3 result; - - if (rigidBody) - { - const auto RP3D_RESULT = rigidBody->getTransform().getPosition(); - result = SHVec3{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z }; - } - - return result; - } - - SHQuaternion SHRigidBodyComponent::GetOrientation() const noexcept - { - SHQuaternion result; - - if (rigidBody) - { - const auto RP3D_RESULT = rigidBody->getTransform().getOrientation(); - result = SHQuaternion{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z, RP3D_RESULT.w }; - } - - return result; - } - /*-----------------------------------------------------------------------------------*/ /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -288,43 +259,43 @@ namespace SHADE return; type = newType; - if (rigidBody) - rigidBody->setType(static_cast(newType)); + if (rp3dBody) + reinterpret_cast(rp3dBody)->setType(static_cast(newType)); } void SHRigidBodyComponent::SetMass(float newMass) noexcept { mass = newMass; - if (rigidBody) - rigidBody->setMass(newMass); + if (rp3dBody) + reinterpret_cast(rp3dBody)->setMass(newMass); } void SHRigidBodyComponent::SetDrag(float newDrag) noexcept { drag = newDrag; - if (rigidBody) - rigidBody->setLinearDamping(newDrag); + if (rp3dBody) + reinterpret_cast(rp3dBody)->setLinearDamping(newDrag); } void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept { angularDrag = newAngularDrag; - if (rigidBody) - rigidBody->setAngularDamping(newAngularDrag); + if (rp3dBody) + reinterpret_cast(rp3dBody)->setAngularDamping(newAngularDrag); } void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept { SetFlag(enableGravity, 0); - if (rigidBody) - rigidBody->enableGravity(enableGravity); + if (rp3dBody) + reinterpret_cast(rp3dBody)->enableGravity(enableGravity); } void SHRigidBodyComponent::SetSleepingEnabled(bool enableSleeping) noexcept { SetFlag(enableSleeping, 1); - if (rigidBody) - rigidBody->setIsAllowedToSleep(enableSleeping); + if (rp3dBody) + reinterpret_cast(rp3dBody)->setIsAllowedToSleep(enableSleeping); } void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept @@ -363,21 +334,26 @@ namespace SHADE SetRP3DAngularConstraints(); } + void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept + { + interpolate = allowInterpolation; + } + void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) const noexcept { - if (rigidBody) + if (rp3dBody) { const rp3d::Vector3 NEW_V { newLinearVelocity.x, newLinearVelocity.y, newLinearVelocity.z }; - rigidBody->setLinearVelocity(NEW_V); + reinterpret_cast(rp3dBody)->setLinearVelocity(NEW_V); } } void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) const noexcept { - if (rigidBody) + if (rp3dBody) { const rp3d::Vector3 NEW_V { newAngularVelocity.x, newAngularVelocity.y, newAngularVelocity.z }; - rigidBody->setAngularVelocity(NEW_V); + reinterpret_cast(rp3dBody)->setAngularVelocity(NEW_V); } } @@ -385,79 +361,97 @@ namespace SHADE /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ + void SHRigidBodyComponent::OnCreate() + { + componentFlags |= 1U << 0; // dirty + componentFlags |= 1U << 1; // rb dirty + componentFlags |= 1U << 2; // has rb + + Synchronise(); + } + + void SHRigidBodyComponent::OnDestroy() + { + componentFlags |= 1U << 0; // dirty + componentFlags |= 1U << 1; // rb dirty + componentFlags &= ~(1U << 2); // no rb + + Synchronise(); + } + void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept { - if (rigidBody) + if (rp3dBody) { const rp3d::Vector3 F { force.x, force.y, force.z }; - rigidBody->applyWorldForceAtCenterOfMass(F); + reinterpret_cast(rp3dBody)->applyWorldForceAtCenterOfMass(F); } } void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept { - if (rigidBody) + if (rp3dBody) { const rp3d::Vector3 F{ force.x, force.y, force.z }; const rp3d::Vector3 P{ localPos.x, localPos.y, localPos.z }; - rigidBody->applyWorldForceAtLocalPosition(F, P); + reinterpret_cast(rp3dBody)->applyWorldForceAtLocalPosition(F, P); } } void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept { - if (rigidBody) + if (rp3dBody) { const rp3d::Vector3 F{ force.x, force.y, force.z }; const rp3d::Vector3 P{ worldPos.x, worldPos.y, worldPos.z }; - rigidBody->applyWorldForceAtWorldPosition(F, P); + reinterpret_cast(rp3dBody)->applyWorldForceAtWorldPosition(F, P); } } void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept { - if (rigidBody) + if (rp3dBody) { const rp3d::Vector3 F{ relativeForce.x, relativeForce.y, relativeForce.z }; - rigidBody->applyLocalForceAtCenterOfMass(F); + reinterpret_cast(rp3dBody)->applyLocalForceAtCenterOfMass(F); } } void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept { - if (rigidBody) + if (rp3dBody) { const rp3d::Vector3 F{ relativeForce.x, relativeForce.y, relativeForce.z }; const rp3d::Vector3 P{ localPos.x, localPos.y, localPos.z }; - rigidBody->applyLocalForceAtLocalPosition(F, P); + reinterpret_cast(rp3dBody)->applyLocalForceAtLocalPosition(F, P); } } void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept { - if (rigidBody) + if (rp3dBody) { const rp3d::Vector3 F{ relativeForce.x, relativeForce.y, relativeForce.z }; const rp3d::Vector3 P{ worldPos.x, worldPos.y, worldPos.z }; - rigidBody->applyLocalForceAtWorldPosition(F, P); + reinterpret_cast(rp3dBody)->applyLocalForceAtWorldPosition(F, P); } } void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept { - if (rigidBody) + if (rp3dBody) { const rp3d::Vector3 T{ torque.x, torque.y, torque.z }; - rigidBody->applyWorldTorque(T); + reinterpret_cast(rp3dBody)->applyWorldTorque(T); } } void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept { - if (rigidBody) + if (rp3dBody) { const rp3d::Vector3 T{ relativeTorque.x, relativeTorque.y, relativeTorque.z }; - rigidBody->applyLocalTorque(T); + reinterpret_cast(rp3dBody)->applyLocalTorque(T); } } @@ -467,6 +461,8 @@ namespace SHADE void SHRigidBodyComponent::SyncRP3DAndSHADE() { + auto* rigidBody = reinterpret_cast(rp3dBody); + rigidBody->setType(static_cast(type)); rigidBody->setMass(mass); @@ -494,8 +490,8 @@ namespace SHADE flags & 1U << 4 ? 1.0f : 0.0f }; - if (rigidBody) - rigidBody->setLinearLockAxisFactor(CONSTRAINTS); + if (rp3dBody) + reinterpret_cast(rp3dBody)->setLinearLockAxisFactor(CONSTRAINTS); } void SHRigidBodyComponent::SetRP3DAngularConstraints() const @@ -507,8 +503,8 @@ namespace SHADE flags & 1U << 7 ? 1.0f : 0.0f }; - if (rigidBody) - rigidBody->setAngularLockAxisFactor(CONSTRAINTS); + if (rp3dBody) + reinterpret_cast(rp3dBody)->setAngularLockAxisFactor(CONSTRAINTS); } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h index 668ab6bd..439fa3db 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h +++ b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h @@ -10,16 +10,17 @@ #pragma once -#include - // Project Headers -#include "Math/Vector/SHVec3.h" -#include "Math/SHMatrix.h" #include "ECS_Base/Components/SHComponent.h" +#include "Physics/SHPhysicsObject.h" namespace SHADE { - class SH_API SHRigidBodyComponent : public SHComponent + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + class SH_API SHRigidBodyComponent : public SHComponent, public SHPhysicsObject { private: /*---------------------------------------------------------------------------------*/ @@ -66,6 +67,7 @@ namespace SHADE [[nodiscard]] bool IsGravityEnabled () const noexcept; [[nodiscard]] bool IsSleepingEnabled () const noexcept; + [[nodiscard]] bool IsInterpolating () const noexcept; [[nodiscard]] Type GetType () const noexcept; [[nodiscard]] float GetMass () const noexcept; @@ -84,8 +86,6 @@ namespace SHADE [[nodiscard]] SHVec3 GetTorque () const noexcept; [[nodiscard]] SHVec3 GetLinearVelocity () const noexcept; [[nodiscard]] SHVec3 GetAngularVelocity () const noexcept; - [[nodiscard]] SHVec3 GetPosition () const noexcept; - [[nodiscard]] SHQuaternion GetOrientation () const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ @@ -104,6 +104,7 @@ namespace SHADE void SetFreezeRotationX (bool freezeRotationX) noexcept; void SetFreezeRotationY (bool freezeRotationY) noexcept; void SetFreezeRotationZ (bool freezeRotationZ) noexcept; + void SetInterpolate (bool allowInterpolation) noexcept; void SetLinearVelocity (const SHVec3& newLinearVelocity) const noexcept; void SetAngularVelocity (const SHVec3& newAngularVelocity) const noexcept; @@ -112,6 +113,9 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ + void OnCreate () override; + void OnDestroy () override; + void AddForce (const SHVec3& force) const noexcept; void AddForceAtLocalPos (const SHVec3& force, const SHVec3& localPos) const noexcept; void AddForceAtWorldPos (const SHVec3& force, const SHVec3& worldPos) const noexcept; @@ -127,8 +131,6 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ - - rp3d::RigidBody* rigidBody; Type type; @@ -138,6 +140,7 @@ namespace SHADE // rX rY rZ pX pY pZ slp g uint8_t flags; + bool interpolate; /*---------------------------------------------------------------------------------*/ /* Function Members */ diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp new file mode 100644 index 00000000..4f0616f8 --- /dev/null +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp @@ -0,0 +1,112 @@ +/**************************************************************************************** + * \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 + +// 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 } + , componentFlags { 0 } + , 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; + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsObject::Synchronise() const + { + if (const bool IS_DIRTY = componentFlags & 1U << 0; IS_DIRTY) + { + auto* physicsSystem = SHSystemManager::GetSystem(); + + const bool IS_RIGIDBODY_DIRTY = componentFlags & 1U << 1; + const bool IS_COLLIDER_DIRTY = componentFlags & 1U << 3; + + if (IS_RIGIDBODY_DIRTY) + { + static constexpr auto COMP_ENUM = SHPhysicsSystem::UpdateComponent::RIGID_BODY; + + const bool HAS_RIGIDBODY = componentFlags & 1U << 2; + HAS_RIGIDBODY ? physicsSystem->AddComponent(COMP_ENUM, entityID) : physicsSystem->RemoveComponent(COMP_ENUM, entityID); + } + + if (IS_COLLIDER_DIRTY) + { + static constexpr auto COMP_ENUM = SHPhysicsSystem::UpdateComponent::COLLIDER; + + const bool HAS_COLLIDER = componentFlags & 1U << 2; + HAS_COLLIDER ? physicsSystem->AddComponent(COMP_ENUM, entityID) : physicsSystem->RemoveComponent(COMP_ENUM, entityID); + } + } + } + + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.h b/SHADE_Engine/src/Physics/SHPhysicsObject.h new file mode 100644 index 00000000..20449f2d --- /dev/null +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.h @@ -0,0 +1,82 @@ +/**************************************************************************************** + * \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 + +// 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 + { + protected: + /*---------------------------------------------------------------------------------*/ + /* Friends */ + /*---------------------------------------------------------------------------------*/ + + friend class SHPhysicsSystem; + + public: + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHPhysicsObject () noexcept; + SHPhysicsObject (const SHPhysicsObject& rhs) noexcept = default; + SHPhysicsObject (SHPhysicsObject&& rhs) noexcept = default; + ~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; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + /** + * @brief Checks for updates in the component states and tells the physics system to + * make any necessary additions / removals to rp3d side to sync with the SHADE + * component. + */ + void Synchronise() const; + + protected: + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + EntityID entityID; + uint8_t componentFlags; // 0 0 0 c cDirty rb rbDirty dirty + rp3d::CollisionBody* rp3dBody; // Can be either a collision body or a rigid body + rp3d::Transform prevTransform; // Cached transform for interpolation + + }; +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp index 537c2c70..d27469ad 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp @@ -14,11 +14,10 @@ #include "SHPhysicsSystem.h" // Project Headers -#include "Math/Transform/SHTransformComponent.h" -#include "Scene/SHSceneManager.h" #include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHEntityManager.h" -#include "Graphics/MiddleEnd/Interface/SHRenderable.h" +#include "Scene/SHSceneManager.h" +#include "Math/Transform/SHTransformComponent.h" namespace SHADE { @@ -26,6 +25,12 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ + SHPhysicsSystem::SHPhysicsSystem() + : accumulatedTime { 0.0 } + , fixedDT { 1.0 / 60.0 } + , world { nullptr } + {} + SHPhysicsSystem::PhysicsPreUpdate::PhysicsPreUpdate() : SHSystemRoutine { "Physics PreUpdate", true } {} @@ -51,11 +56,6 @@ namespace SHADE return false; } - //double SHPhysicsSystem::GetFixedUpdate() const noexcept - //{ - // return fixedUpdate; - //} - SHVec3 SHPhysicsSystem::GetWorldGravity() const noexcept { SHVec3 result; @@ -97,12 +97,6 @@ namespace SHADE /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - //void SHPhysicsSystem::SetFixedUpdate(double fixedUpdateRate) noexcept - //{ - // fixedUpdate = fixedUpdateRate; - // SHLOG_INFO("Setting Physics update rate to {}", 1.0 / fixedUpdate) - //} - void SHPhysicsSystem::SetWorldGravity(const SHVec3& gravity) const noexcept { if (world) @@ -178,7 +172,7 @@ namespace SHADE // Create a physics world with the default settings PhysicsWorld::WorldSettings settings; - settings.gravity = Vector3{ 0, -9.81, 0 }; + settings.gravity = Vector3{ 0.0f, -9.81f, 0.0f }; settings.isSleepingEnabled = true; settings.defaultVelocitySolverNbIterations = 8; settings.defaultPositionSolverNbIterations = 3; @@ -194,108 +188,14 @@ namespace SHADE factory.destroyPhysicsWorld(world); } - void SHPhysicsSystem::AddRigidBodyComponent(EntityID id) noexcept - { - const UpdateCommand NEW_CMD - { - .component = UpdateComponent::RIGID_BODY, - .type = UpdateType::ADD, - .entityID = id - }; - - updateQueue.push(NEW_CMD); - } - - void SHPhysicsSystem::AddColliderComponent(EntityID id) noexcept - { - const UpdateCommand NEW_CMD - { - .component = UpdateComponent::COLLIDER, - .type = UpdateType::ADD, - .entityID = id - }; - - updateQueue.push(NEW_CMD); - } - - void SHPhysicsSystem::RemoveRigidBodyComponent(EntityID id) noexcept - { - const UpdateCommand NEW_CMD - { - .component = UpdateComponent::RIGID_BODY, - .type = UpdateType::REMOVE, - .entityID = id - }; - - updateQueue.push(NEW_CMD); - } - - void SHPhysicsSystem::RemoveColliderComponent(EntityID id) noexcept - { - const UpdateCommand NEW_CMD - { - .component = UpdateComponent::COLLIDER, - .type = UpdateType::REMOVE, - .entityID = id - }; - - updateQueue.push(NEW_CMD); - } - void SHPhysicsSystem::PhysicsPreUpdate::Execute([[maybe_unused]]double dt) noexcept { auto* system = reinterpret_cast(GetSystem()); + system->ClearUpdateQueue(); - - // Sync active states: if node or component is not active, set rp3d to inactive - static const auto SYNC_ACTIVE = [](SHSceneNode* node) - { - const EntityID ENTITY_ID = node->GetEntityID(); - - // Check if has rigid body - auto const* rigidBodyComponent = SHComponentManager::GetComponent_s(ENTITY_ID); - if(rigidBodyComponent) - { - const bool RP3D_ACTIVE = rigidBodyComponent->rigidBody->isActive(); - const bool SHADE_ACTIVE = node->IsActive() && rigidBodyComponent->isActive; - - if (RP3D_ACTIVE != SHADE_ACTIVE) - rigidBodyComponent->rigidBody->setIsActive(SHADE_ACTIVE); - } - else // Check for a collider - { - - } - }; - - const auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); - sceneGraph.Traverse(SYNC_ACTIVE); + system->SyncActiveStates(SHSceneManager::GetCurrentSceneGraph()); } - //void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept - //{ - // // I had to override this anyway due to needing to calculate the - // // interpolation factor right after the fixed update was done - - // auto* system = reinterpret_cast(GetSystem()); - // fixedTimeStep = 1.0 / system->fixedUpdate; - - // accumulatedTime += dt; - // int counter = 0; - - // while (accumulatedTime > fixedTimeStep) - // { - // FixedExecute(fixedTimeStep); - - // accumulatedTime -= fixedTimeStep; - // ++counter; - // } - - // stats.numSteps = counter; - - // system->interpolationFactor = accumulatedTime / fixedTimeStep; - //} - void SHPhysicsSystem::PhysicsFixedUpdate::FixedExecute(double dt) noexcept { auto* system = reinterpret_cast(GetSystem()); @@ -309,38 +209,25 @@ namespace SHADE { // Interpolate transforms for rendering const auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); - sceneGraph.Traverse([](SHSceneNode* node) - { - const EntityID ENTITY_ID = node->GetEntityID(); - - // Check if has rigid body - if (auto* rb = SHComponentManager::GetComponent_s(ENTITY_ID); rb) - { - // TODO(Diren): Interpolate transforms for rendering - if (node->IsActive() && rb->isActive) - { - // Get SHADE transform - auto* transformComponent = SHComponentManager::GetComponent_s(ENTITY_ID); - SHASSERT(transformComponent != nullptr, "Transform Component missing from Entity " + std::to_string(ENTITY_ID)) - - const auto& RP3D_POS = rb->GetPosition(); - const SHVec3 SHADE_POS{ RP3D_POS.x, RP3D_POS.y, RP3D_POS.z }; - - const auto& SHADE_ROT = rb->GetOrientation().ToEuler(); - - transformComponent->SetWorldPosition(SHADE_POS); - transformComponent->SetWorldRotation(SHADE_ROT); - } - else // Check for a collider - { - - } - } - }); // TODO(Diren): Handle trigger messages for scripting } + /*-----------------------------------------------------------------------------------*/ + /* Protected Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsSystem::AddComponent(UpdateComponent comp, EntityID entityID) noexcept + { + updateQueue.push({ comp, UpdateType::ADD, entityID }); + } + + + void SHPhysicsSystem::RemoveComponent(UpdateComponent comp, EntityID entityID) noexcept + { + updateQueue.push({ comp, UpdateType::REMOVE, entityID }); + } + /*-----------------------------------------------------------------------------------*/ /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -377,6 +264,85 @@ namespace SHADE } } + void SHPhysicsSystem::SyncActiveStates(const SHSceneGraph& sceneGraph) const noexcept + { + // Sync active states: if node or component is not active, set rp3d to inactive + static constexpr auto SYNC_ACTIVE = [](SHSceneNode* node) + { + const EntityID ENTITY_ID = node->GetEntityID(); + + // Check if has rigid body + auto const* rigidBodyComponent = SHComponentManager::GetComponent_s(ENTITY_ID); + if(rigidBodyComponent) + { + const bool RP3D_ACTIVE = rigidBodyComponent->rp3dBody->isActive(); + const bool SHADE_ACTIVE = node->IsActive() && rigidBodyComponent->isActive; + + if (RP3D_ACTIVE != SHADE_ACTIVE) + rigidBodyComponent->rp3dBody->setIsActive(SHADE_ACTIVE); + } + else // Check for a collider + { + + } + }; + + sceneGraph.Traverse(SYNC_ACTIVE); + } + + void SHPhysicsSystem::SyncTransforms(const SHSceneGraph& sceneGraph) const noexcept + { + const rp3d::decimal INTERPOLATION_FACTOR = static_cast(accumulatedTime / fixedDT); + + static const auto SYNC_TRANSFORMS = [&](SHSceneNode* node) + { + const EntityID ENTITY_ID = node->GetEntityID(); + + // Check if has rigid body + if (auto* rb = SHComponentManager::GetComponent_s(ENTITY_ID); rb) + { + if (node->IsActive() && rb->isActive) + { + // Get SHADE transform + auto* transformComponent = SHComponentManager::GetComponent_s(ENTITY_ID); + SHASSERT(transformComponent != nullptr, "Transform Component missing from Entity " + std::to_string(ENTITY_ID)) + + SHVec3 shadePos, shadeRot; + + if (rb->interpolate) + { + const rp3d::Transform CURRENT_TRANSFORM = rb->rp3dBody->getTransform(); + const rp3d::Transform INTERPOLATED_TRANSFORM = rp3d::Transform::interpolateTransforms(rb->prevTransform, CURRENT_TRANSFORM, INTERPOLATION_FACTOR); + + const auto& RP3D_POS = INTERPOLATED_TRANSFORM.getPosition(); + shadePos = SHVec3{ RP3D_POS.x, RP3D_POS.y, RP3D_POS.z }; + + const auto& RP3D_ORT = INTERPOLATED_TRANSFORM.getOrientation(); + shadeRot = SHQuaternion{ RP3D_ORT.x, RP3D_ORT.y, RP3D_ORT.z, RP3D_ORT.w }.ToEuler(); + + rb->prevTransform = CURRENT_TRANSFORM; + } + else + { + + const auto& RP3D_POS = rb->GetPosition(); + shadePos = SHVec3{ RP3D_POS.x, RP3D_POS.y, RP3D_POS.z }; + shadeRot = rb->GetOrientation().ToEuler(); + } + + transformComponent->SetWorldPosition(shadePos); + transformComponent->SetWorldRotation(shadeRot); + } + else // Check for a collider + { + + } + } + }; + + sceneGraph.Traverse(SYNC_TRANSFORMS); + } + void SHPhysicsSystem::AddRigidBody(EntityID entityID) const noexcept { @@ -413,7 +379,8 @@ namespace SHADE rigidBodyComponent = SHComponentManager::GetComponent(entityID); } - rigidBodyComponent->rigidBody = world->createRigidBody(RP3D_TF); + rigidBodyComponent->rp3dBody = world->createRigidBody(RP3D_TF); + rigidBodyComponent->prevTransform = RP3D_TF; rigidBodyComponent->SyncRP3DAndSHADE(); // Reassign collider @@ -438,9 +405,8 @@ namespace SHADE // If a collider exists, remake the colliders with a collision body - world->destroyRigidBody(rigidBodyComponent->rigidBody); - rigidBodyComponent->rigidBody = nullptr; // this should be redundant + world->destroyRigidBody(reinterpret_cast(rigidBodyComponent->rp3dBody)); + rigidBodyComponent->rp3dBody = nullptr; // this should be redundant } - } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/SHPhysicsSystem.h index dac6836a..273eb54d 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.h @@ -11,14 +11,12 @@ #pragma once #include -#include #include // Project Headers #include "Math/SHQuaternion.h" #include "Components/SHRigidBodyComponent.h" - #include "Scene/SHSceneGraph.h" #include "ECS_Base/System/SHSystemRoutine.h" #include "ECS_Base/System/SHFixedSystemRoutine.h" @@ -31,6 +29,13 @@ namespace SHADE class SH_API SHPhysicsSystem : public SHSystem { + protected: + /*---------------------------------------------------------------------------------*/ + /* Friends */ + /*---------------------------------------------------------------------------------*/ + + friend class SHPhysicsObject; + public: /*---------------------------------------------------------------------------------*/ /* Type Definitions */ @@ -48,18 +53,7 @@ namespace SHADE /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHPhysicsSystem () = default; - ~SHPhysicsSystem () override = default; - - SHPhysicsSystem (const SHPhysicsSystem&) = delete; - SHPhysicsSystem (SHPhysicsSystem&&) = delete; - - /*---------------------------------------------------------------------------------*/ - /* Operator Overloads */ - /*---------------------------------------------------------------------------------*/ - - SHPhysicsSystem& operator= (const SHPhysicsSystem&) = delete; - SHPhysicsSystem& operator= (SHPhysicsSystem&&) = delete; + SHPhysicsSystem(); /*---------------------------------------------------------------------------------*/ /* Getter Functions */ @@ -67,7 +61,6 @@ namespace SHADE [[nodiscard]] bool IsSleepingEnabled () const noexcept; - //[[nodiscard]] double GetFixedUpdate () const noexcept; [[nodiscard]] SHVec3 GetWorldGravity () const noexcept; [[nodiscard]] uint16_t GetNumberVelocityIterations () const noexcept; [[nodiscard]] uint16_t GetNumberPositionIterations () const noexcept; @@ -92,11 +85,6 @@ namespace SHADE void Init () override; void Exit () override; - void AddRigidBodyComponent (EntityID id) noexcept; - void AddColliderComponent (EntityID id) noexcept; - void RemoveRigidBodyComponent (EntityID id) noexcept; - void RemoveColliderComponent (EntityID id) noexcept; - /*---------------------------------------------------------------------------------*/ /* System Routines */ /*---------------------------------------------------------------------------------*/ @@ -109,17 +97,6 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ PhysicsPreUpdate(); - ~PhysicsPreUpdate() = default; - - PhysicsPreUpdate(const PhysicsPreUpdate&) = delete; - PhysicsPreUpdate(PhysicsPreUpdate&&) = delete; - - /*-------------------------------------------------------------------------------*/ - /* Operator Overloads */ - /*-------------------------------------------------------------------------------*/ - - PhysicsPreUpdate& operator= (const PhysicsPreUpdate&) = delete; - PhysicsPreUpdate& operator= (PhysicsPreUpdate&&) = delete; /*-------------------------------------------------------------------------------*/ /* Function Members */ @@ -136,17 +113,6 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ PhysicsFixedUpdate(); - ~PhysicsFixedUpdate() = default; - - PhysicsFixedUpdate(const PhysicsFixedUpdate&) = delete; - PhysicsFixedUpdate(PhysicsFixedUpdate&&) = delete; - - /*-------------------------------------------------------------------------------*/ - /* Operator Overloads */ - /*-------------------------------------------------------------------------------*/ - - PhysicsFixedUpdate& operator= (const PhysicsFixedUpdate&) = delete; - PhysicsFixedUpdate& operator= (PhysicsFixedUpdate&&) = delete; /*-------------------------------------------------------------------------------*/ /* Function Members */ @@ -164,17 +130,6 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ PhysicsPostUpdate(); - ~PhysicsPostUpdate() = default; - - PhysicsPostUpdate(const PhysicsPostUpdate&) = delete; - PhysicsPostUpdate(PhysicsPostUpdate&&) = delete; - - /*-------------------------------------------------------------------------------*/ - /* Operator Overloads */ - /*-------------------------------------------------------------------------------*/ - - PhysicsPostUpdate& operator= (const PhysicsPostUpdate&) = delete; - PhysicsPostUpdate& operator= (PhysicsPostUpdate&&) = delete; /*-------------------------------------------------------------------------------*/ /* Function Members */ @@ -183,8 +138,7 @@ namespace SHADE void Execute(double dt) noexcept override; }; - - private: + protected: /*---------------------------------------------------------------------------------*/ /* Type Definitions */ /*---------------------------------------------------------------------------------*/ @@ -199,38 +153,41 @@ namespace SHADE EntityID entityID; }; - struct CachedTransform - { - SHVec3 position; - SHQuaternion orientation; - }; + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + void AddComponent (UpdateComponent comp, EntityID entityID) noexcept; + void RemoveComponent (UpdateComponent comp, EntityID entityID) noexcept; + + private: /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ - //double interpolationFactor; - //double fixedUpdate; + // TODO(Diren): Store interpFactor & fixedUpdate for modifiable fixedDT - double accumulatedTime; - double fixedDT; + double accumulatedTime; + double fixedDT; - rp3d::PhysicsCommon factory; - rp3d::PhysicsWorld* world; + rp3d::PhysicsCommon factory; + rp3d::PhysicsWorld* world; - std::queue updateQueue; - std::unordered_map prevTransforms; // used for interpolation + std::queue updateQueue; /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - void ClearUpdateQueue () noexcept; + void ClearUpdateQueue () noexcept; + void SyncActiveStates (const SHSceneGraph& sceneGraph) const noexcept; + void SyncTransforms (const SHSceneGraph& sceneGraph) const noexcept; + // TODO(Diren): Trigger handling - void AddRigidBody (EntityID entityID) const noexcept; - void AddCollider (EntityID entityID) const noexcept; - void RemoveRigidBody (EntityID entityID) const noexcept; - void RemoveCollider (EntityID entityID) const noexcept; + void AddRigidBody (EntityID entityID) const noexcept; + void AddCollider (EntityID entityID) const noexcept; + void RemoveRigidBody (EntityID entityID) const noexcept; + void RemoveCollider (EntityID entityID) const noexcept; };