From d59f4e88c267c957e36911b1fb2a1f6ca2372fbe Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sun, 5 Mar 2023 23:39:33 +0800 Subject: [PATCH 01/10] Added gravity scale Update react dependency --- Assets/Scenes/PhysicsTest.shade | 4 +++- .../Inspector/SHEditorComponentView.hpp | 4 ++++ .../PhysicsObject/SHPhysicsObjectManager.cpp | 1 + .../Physics/Interface/SHRigidBodyComponent.cpp | 15 +++++++++++++++ .../src/Physics/Interface/SHRigidBodyComponent.h | 3 +++ 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Assets/Scenes/PhysicsTest.shade b/Assets/Scenes/PhysicsTest.shade index 20903809..982556af 100644 --- a/Assets/Scenes/PhysicsTest.shade +++ b/Assets/Scenes/PhysicsTest.shade @@ -12,6 +12,7 @@ Type: Dynamic Drag: 0.00999999978 Angular Drag: 0.100000001 + Gravity Scale: 0.100000001 Use Gravity: true Interpolate: false Sleeping Enabled: true @@ -75,10 +76,10 @@ Yaw: 0 Roll: 0 Width: 1920 - Height: 1080 Near: 0.00999999978 Far: 10000 Perspective: true + FOV: 90 IsActive: true Scripts: ~ - EID: 65539 @@ -187,6 +188,7 @@ Type: Dynamic Drag: 0.00999999978 Angular Drag: 0.100000001 + Gravity Scale: 1 Use Gravity: true Interpolate: true Sleeping Enabled: true diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 8adb45b5..fe84db31 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -263,6 +263,10 @@ namespace SHADE if(rbType == SHRigidBodyComponent::Type::DYNAMIC) //Dynamic only fields { SHEditorWidgets::CheckBox("Use Gravity", [component]{return component->IsGravityEnabled();}, [component](bool const& value){component->SetGravityEnabled(value);}, "Gravity"); + + if (component->IsGravityEnabled()) + SHEditorWidgets::DragFloat("Gravity Scale", [component] {return component->GetGravityScale(); }, [component](float const& value) {component->SetGravityScale(value); }, "Gravity Scale"); + //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 diff --git a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp index b22741e9..a0b2f7cc 100644 --- a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp +++ b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp @@ -297,6 +297,7 @@ namespace SHADE rigidBodyComponent->SetInterpolate (rigidBodyComponent->IsInterpolating()); rigidBodyComponent->SetDrag (rigidBodyComponent->GetDrag()); rigidBodyComponent->SetAngularDrag (rigidBodyComponent->GetAngularDrag()); + rigidBodyComponent->SetGravityScale (rigidBodyComponent->GetGravityScale()); rigidBodyQueue.pop(); } diff --git a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp index ee4db90d..85c798db 100644 --- a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp @@ -114,6 +114,11 @@ namespace SHADE return angularDrag; } + float SHRigidBodyComponent::GetGravityScale() const noexcept + { + return gravityScale; + } + SHVec3 SHRigidBodyComponent::GetForce() const noexcept { return rigidBody ? SHVec3{ rigidBody->getForce() } : SHVec3::Zero; @@ -297,6 +302,15 @@ namespace SHADE rigidBody->setAngularDamping(newAngularDrag); } + void SHRigidBodyComponent::SetGravityScale(float newGravityScale) noexcept + { + gravityScale = newGravityScale; + + if (rigidBody) + rigidBody->setGravityScale(newGravityScale); + } + + void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept { if (type == Type::STATIC) @@ -408,6 +422,7 @@ RTTR_REGISTRATION .property("Type" , &SHRigidBodyComponent::GetType , &SHRigidBodyComponent::SetType ) .property("Drag" , &SHRigidBodyComponent::GetDrag , &SHRigidBodyComponent::SetDrag ) .property("Angular Drag" , &SHRigidBodyComponent::GetAngularDrag , &SHRigidBodyComponent::SetAngularDrag ) + .property("Gravity Scale" , &SHRigidBodyComponent::GetGravityScale , &SHRigidBodyComponent::SetGravityScale ) .property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetGravityEnabled ) .property("Interpolate" , &SHRigidBodyComponent::IsInterpolating , &SHRigidBodyComponent::SetInterpolate ) .property("Sleeping Enabled" , &SHRigidBodyComponent::IsAllowedToSleep , &SHRigidBodyComponent::SetIsAllowedToSleep) diff --git a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h index 6332d1e6..a1cbe786 100644 --- a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h @@ -93,6 +93,7 @@ namespace SHADE [[nodiscard]] float GetMass () const noexcept; [[nodiscard]] float GetDrag () const noexcept; [[nodiscard]] float GetAngularDrag () const noexcept; + [[nodiscard]] float GetGravityScale () const noexcept; [[nodiscard]] SHVec3 GetForce () const noexcept; [[nodiscard]] SHVec3 GetTorque () const noexcept; @@ -123,6 +124,7 @@ namespace SHADE void SetDrag (float newDrag) noexcept; void SetAngularDrag (float newAngularDrag) noexcept; + void SetGravityScale (float newGravityScale) noexcept; void SetLinearVelocity (const SHVec3& newLinearVelocity) noexcept; void SetAngularVelocity (const SHVec3& newAngularVelocity) noexcept; @@ -173,6 +175,7 @@ namespace SHADE // Used for storing serialised data uint8_t flags; // aZ aY aX lZ lY lX sleepEnabled gravity + float gravityScale; float drag; float angularDrag; From 550b99b3d79e272e5aa26bfffe74570170621c59 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Mon, 6 Mar 2023 17:44:40 +0800 Subject: [PATCH 02/10] Added a generic AABB class --- SHADE_Engine/src/Math/Geometry/SHAABB.cpp | 215 ++++++++++++++++++++++ SHADE_Engine/src/Math/Geometry/SHAABB.h | 172 +++++++++++++++++ 2 files changed, 387 insertions(+) create mode 100644 SHADE_Engine/src/Math/Geometry/SHAABB.cpp create mode 100644 SHADE_Engine/src/Math/Geometry/SHAABB.h diff --git a/SHADE_Engine/src/Math/Geometry/SHAABB.cpp b/SHADE_Engine/src/Math/Geometry/SHAABB.cpp new file mode 100644 index 00000000..9ec57073 --- /dev/null +++ b/SHADE_Engine/src/Math/Geometry/SHAABB.cpp @@ -0,0 +1,215 @@ +/**************************************************************************************** + * \file SHAABB.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a 3-Dimensional Axis Aligned Bounding Box + * + * \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 "SHAABB.h" +// Project Headers +#include "Math/SHMathHelpers.h" +#include "Math/SHRay.h" + +using namespace DirectX; + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHAABB::SHAABB() noexcept + { + Center = SHVec3::Zero; + Extents = SHVec3::One * 0.5f; + } + + SHAABB::SHAABB(const SHVec3& c, const SHVec3& hE) noexcept + { + Center = c; + Extents = hE; + } + + + SHAABB::SHAABB(const SHAABB& rhs) noexcept + { + if (this == &rhs) + return; + + Center = rhs.Center; + Extents = rhs.Extents; + } + + SHAABB::SHAABB(SHAABB&& rhs) noexcept + { + Center = rhs.Center; + Extents = rhs.Extents; + } + + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHAABB& SHAABB::operator=(const SHAABB& rhs) noexcept + { + Center = rhs.Center; + Extents = rhs.Extents; + + return *this; + } + + SHAABB& SHAABB::operator=(SHAABB&& rhs) noexcept + { + Center = rhs.Center; + Extents = rhs.Extents; + + return *this; + } + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHVec3 SHAABB::GetCenter() const noexcept + { + return Center; + } + + SHVec3 SHAABB::GetExtents() const noexcept + { + return Extents; + } + + SHVec3 SHAABB::GetMin() const noexcept + { + return SHVec3{ Center.x - Extents.x, Center.y - Extents.y, Center.z - Extents.z }; + } + + SHVec3 SHAABB::GetMax() const noexcept + { + return SHVec3{ Center.x + Extents.x, Center.y + Extents.y, Center.z + Extents.z }; + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHAABB::SetCenter(const SHVec3& newCenter) noexcept + { + Center = newCenter; + } + + void SHAABB::SetExtents(const SHVec3& newExtents) noexcept + { + Extents = newExtents; + } + + void SHAABB::SetMin(const SHVec3& min) noexcept + { + const SHVec3 MAX = GetMax(); + + Center = SHVec3::Lerp(min, MAX, 0.5f); + Extents = SHVec3::Abs((MAX - min) * 0.5f); + } + + void SHAABB::SetMax(const SHVec3& max) noexcept + { + const SHVec3 MIN = GetMin(); + + Center = SHVec3::Lerp(MIN, max, 0.5f); + Extents = SHVec3::Abs((max - MIN) * 0.5f); + } + + void SHAABB::SetMinMax(const SHVec3& min, const SHVec3& max) noexcept + { + Center = SHVec3::Lerp(min, max, 0.5f); + Extents = SHVec3::Abs((max - min) * 0.5f); + } + + std::vector SHAABB::GetVertices() const noexcept + { + std::vector vertices{ 8 }; + GetCorners(vertices.data()); + return vertices; + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + bool SHAABB::TestPoint(const SHVec3& point) const noexcept + { + return BoundingBox::Contains(point); + } + + SHRaycastResult SHAABB::Raycast(const SHRay& ray) const noexcept + { + SHRaycastResult result; + + result.hit = Intersects(ray.position, ray.direction, result.distance); + if (result.hit) + { + result.position = ray.position + ray.direction * result.distance; + result.angle = SHVec3::Angle(ray.position, result.position); + } + + return result; + } + + bool SHAABB::Contains(const SHAABB& rhs) const noexcept + { + return BoundingBox::Contains(rhs) == CONTAINS; + } + + float SHAABB::Volume() const noexcept + { + return 8.0f * (Extents.x * Extents.y * Extents.z); + } + + float SHAABB::SurfaceArea() const noexcept + { + return 8.0f * ((Extents.x * Extents.y) + + (Extents.x * Extents.z) + + (Extents.y * Extents.z)); + } + + /*-----------------------------------------------------------------------------------*/ + /* Static Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHAABB SHAABB::Combine(const SHAABB& lhs, const SHAABB& rhs) noexcept + { + SHAABB result; + CreateMerged(result, lhs, rhs); + return result; + } + + bool SHAABB::Intersect(const SHAABB& lhs, const SHAABB& rhs) noexcept + { + return lhs.Intersects(rhs); + } + + SHAABB SHAABB::BuildFromBoxes(const SHAABB* boxes, size_t numBoxes) noexcept + { + SHAABB result; + + for (size_t i = 1; i < numBoxes; ++i) + CreateMerged(result, boxes[i - 1], boxes[i]); + + return result; + } + + SHAABB SHAABB::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept + { + SHAABB result; + CreateFromPoints(result, numVertices, vertices, stride); + return result; + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Geometry/SHAABB.h b/SHADE_Engine/src/Math/Geometry/SHAABB.h new file mode 100644 index 00000000..36ae9aed --- /dev/null +++ b/SHADE_Engine/src/Math/Geometry/SHAABB.h @@ -0,0 +1,172 @@ +/**************************************************************************************** + * \file SHAABB.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a 3-Dimensional Axis Aligned Bounding Box + * + * \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/SHRay.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + /** + * @brief + * Encapsulates a 3D Axis-Aligned Bounding Box. + */ + class SH_API SHAABB : private DirectX::BoundingBox + { + public: + /*---------------------------------------------------------------------------------*/ + /* Static Data Members */ + /*---------------------------------------------------------------------------------*/ + + static constexpr size_t NUM_VERTICES = 8; + + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + ~SHAABB () noexcept = default; + + SHAABB () noexcept; + SHAABB (const SHVec3& center, const SHVec3& halfExtents) noexcept; + SHAABB (const SHAABB& rhs) noexcept; + SHAABB (SHAABB&& rhs) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHAABB& operator= (const SHAABB& rhs) noexcept; + SHAABB& operator= (SHAABB&& rhs) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Getter Functions */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] SHVec3 GetCenter () const noexcept; + [[nodiscard]] SHVec3 GetExtents () const noexcept; + [[nodiscard]] SHVec3 GetMin () const noexcept; + [[nodiscard]] SHVec3 GetMax () const noexcept; + [[nodiscard]] std::vector GetVertices () const noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*---------------------------------------------------------------------------------*/ + + void SetCenter (const SHVec3& newCenter) noexcept; + void SetExtents (const SHVec3& newExtents) noexcept; + void SetMin (const SHVec3& min) noexcept; + void SetMax (const SHVec3& max) noexcept; + void SetMinMax (const SHVec3& min, const SHVec3& max) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Member Functions */ + /*---------------------------------------------------------------------------------*/ + + /** + * @brief + * Checks if a point is inside the aabb. + * @param point + * The point to check. + * @return + * True if the point is inside the aabb. + */ + [[nodiscard]] bool TestPoint (const SHVec3& point) const noexcept; + + /** + * @brief + * Casts a ray against the aabb. + * @param ray + * The ray to cast. + * @return + * The result of the raycast.
+ * See the corresponding header for the contents of the raycast result object. + */ + [[nodiscard]] SHRaycastResult Raycast (const SHRay& ray) const noexcept; + + /** + * @brief + * Checks if an entire other aabb is contained by this aabb. + * @param rhs + * The aabb to check. + * @return + * True if the other sphere is completely contained by this aabb. + */ + [[nodiscard]] bool Contains (const SHAABB& rhs) const noexcept; + + /** + * @brief + * Calculates the volume of the aabb. + */ + [[nodiscard]] float Volume () const noexcept; + + /** + * @brief + * Calculates the surface area of the aabb. + */ + [[nodiscard]] float SurfaceArea () const noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Static Member Functions */ + /*---------------------------------------------------------------------------------*/ + + /** + * @brief + * Combines two aabbs to form a larger aabb. + * If one aabb is completely contained by the other, the result is the larger aabb. + * @return + * The combined aabb. + */ + [[nodiscard]] static SHAABB Combine (const SHAABB& lhs, const SHAABB& rhs) noexcept; + + /** + * @brief + * Checks if two aabbs are intersecting. + * @return + * True if they are intersecting. + */ + [[nodiscard]] static bool Intersect (const SHAABB& lhs, const SHAABB& rhs) noexcept; + + /** + * @brief + * Builds a single aabb from multiple aabbs. + * @param spheres + * The set of aabbs to build from. + * @param numSpheres + * The number of aabbs in the set to build from. + * @return + * An aabb that contains all the spheres in the set. + */ + [[nodiscard]] static SHAABB BuildFromBoxes (const SHAABB* boxes, size_t numBoxes) noexcept; + + /** + * @brief + * Builds a aabb from a set of vertices. + * @param vertices + * The vertices to build a aabb from. + * @param numVertices + * The number of vertices in the set to build from. + * @param stride + * The stride between each vertex, in the instance there is data in between each + * vertex that does not define the geometry of the object. + * @return + * An aabb that contains all the vertices in the set. + */ + [[nodiscard]] static SHAABB BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; + }; + + +} // namespace SHADE \ No newline at end of file From 78a3bf4575cfa93e2c3e7d801ee7a1ac5836afc7 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Mon, 6 Mar 2023 17:44:58 +0800 Subject: [PATCH 03/10] Added function to test an AABB against the physics world Update React Dependency --- .../src/Physics/System/SHPhysicsSystem.cpp | 24 +++++++++++++++++++ .../src/Physics/System/SHPhysicsSystem.h | 13 ++++++++++ 2 files changed, 37 insertions(+) diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index d63e669a..84b36ac5 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -172,6 +172,30 @@ namespace SHADE return results; } + bool SHPhysicsSystem::TestAABBOverlap(const SHAABB& aabb, uint16_t layers) + { + if (!worldState.world) + { + SHLOG_ERROR("Cannot test AABB overlap without a physics world!") + return false; + } + + // Create a temporary collider to test against the world + auto* tempRP3DBody = worldState.world->createCollisionBody(rp3d::Transform { aabb.GetCenter(), SHQuaternion::Identity }); + auto* tempRP3DBox = factory.createBoxShape(aabb.GetExtents()); + auto* tempRP3DCollider = tempRP3DBody->addCollider(tempRP3DBox, rp3d::Transform{}); + tempRP3DCollider->setCollisionCategoryBits(layers); + tempRP3DCollider->setCollideWithMaskBits(layers); + + // Test the temp collider against the world + const bool IS_COLLIDING = worldState.world->testOverlap(tempRP3DBody); + + tempRP3DBody->removeCollider(tempRP3DCollider); + factory.destroyBoxShape(tempRP3DBox); + worldState.world->destroyCollisionBody(tempRP3DBody); + + return IS_COLLIDING; + } /*-----------------------------------------------------------------------------------*/ /* Private Function Member Definitions */ diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index bd233bfe..06476c6b 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -18,6 +18,7 @@ // Project Headers #include "ECS_Base/System/SHSystemRoutine.h" #include "ECS_Base/System/SHFixedSystemRoutine.h" +#include "Math/Geometry/SHAABB.h" #include "Physics/Collision/SHCollisionInfo.h" #include "Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h" #include "Physics/RP3DWrapper/SHPhysicsWorld.h" @@ -92,6 +93,18 @@ namespace SHADE */ [[nodiscard]] const std::vector& Raycast(const SHRaycaster::RaycastInfo& info) noexcept; + /** + * \brief + * Tests if an AABB overlaps with anything in the scene. + * \param aabb + * The AABB to test. + * \param layers + * The layer(s) to test the overlap on. Defaults to all layers. + * \return + * True if there is any overlap. + */ + [[nodiscard]] bool TestAABBOverlap(const SHAABB& aabb, uint16_t layers = static_cast(SHCollisionTag::Layer::ALL)); + /*---------------------------------------------------------------------------------*/ /* System Routines */ /*---------------------------------------------------------------------------------*/ From e89f5df35f39ea1b97289d865c5d7ca58bd8f4b0 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Mon, 6 Mar 2023 18:17:13 +0800 Subject: [PATCH 04/10] Added physics constants --- ...ysicsWorld.cpp => SHPhysicsWorldState.cpp} | 2 +- ...SHPhysicsWorld.h => SHPhysicsWorldState.h} | 9 ++++--- SHADE_Engine/src/Physics/SHPhysicsConstants.h | 25 +++++++++++++++++++ .../src/Physics/System/SHPhysicsSystem.cpp | 7 +----- .../src/Physics/System/SHPhysicsSystem.h | 4 +-- .../System/SHPhysicsSystemInterface.cpp | 24 +++++++++--------- .../Physics/System/SHPhysicsSystemInterface.h | 12 ++++----- SHADE_Managed/src/Engine/Time.cxx | 4 +-- 8 files changed, 54 insertions(+), 33 deletions(-) rename SHADE_Engine/src/Physics/RP3DWrapper/{SHPhysicsWorld.cpp => SHPhysicsWorldState.cpp} (98%) rename SHADE_Engine/src/Physics/RP3DWrapper/{SHPhysicsWorld.h => SHPhysicsWorldState.h} (89%) create mode 100644 SHADE_Engine/src/Physics/SHPhysicsConstants.h diff --git a/SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorld.cpp b/SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorldState.cpp similarity index 98% rename from SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorld.cpp rename to SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorldState.cpp index 85e76702..82a9aa26 100644 --- a/SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorld.cpp +++ b/SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorldState.cpp @@ -11,7 +11,7 @@ #include // Primary Header -#include "SHPhysicsWorld.h" +#include "SHPhysicsWorldState.h" namespace SHADE { diff --git a/SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorld.h b/SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorldState.h similarity index 89% rename from SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorld.h rename to SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorldState.h index 09a2b260..40483a8c 100644 --- a/SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorld.h +++ b/SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorldState.h @@ -1,7 +1,7 @@ /**************************************************************************************** - * \file SHPhysicsWorld.h + * \file SHPhysicsWorldState.h * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Interface for a Physics World. + * \brief Interface for a Physics World State. * * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or * disclosure of this file or its contents without the prior written consent @@ -14,6 +14,7 @@ // Project Headers #include "Math/Vector/SHVec3.h" +#include "Physics/SHPhysicsConstants.h" namespace SHADE { @@ -37,8 +38,8 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ SHVec3 gravity = SHVec3{ 0.0f, -9.81f, 0.0f }; - uint16_t numVelocitySolverIterations = 10; - uint16_t numPositionSolverIterations = 5; + uint16_t numVelocitySolverIterations = SHPhysicsConstants::DEFAULT_VELOCITY_ITERATIONS; + uint16_t numPositionSolverIterations = SHPhysicsConstants::DEFAULT_POSITION_ITERATIONS; bool sleepingEnabled = true; }; diff --git a/SHADE_Engine/src/Physics/SHPhysicsConstants.h b/SHADE_Engine/src/Physics/SHPhysicsConstants.h new file mode 100644 index 00000000..fe3b9ee5 --- /dev/null +++ b/SHADE_Engine/src/Physics/SHPhysicsConstants.h @@ -0,0 +1,25 @@ +/**************************************************************************************** + * \file SHPhysicsConstants.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Declaration of Constants used for physics simulations + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#pragma once + +// Project Headers +#include "Math/Vector/SHVec3.h" + +namespace SHADE +{ + struct SHPhysicsConstants + { + static constexpr double DEFAULT_FIXED_DT = 1.0 / 60.0; + + static constexpr int DEFAULT_VELOCITY_ITERATIONS = 10; + static constexpr int DEFAULT_POSITION_ITERATIONS = 5; + }; +} diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index 84b36ac5..de654e0c 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -34,7 +34,7 @@ namespace SHADE SHPhysicsSystem::SHPhysicsSystem() noexcept : worldUpdated { false } , interpolationFactor { 0.0 } - , fixedDT { DEFAULT_FIXED_STEP } + , fixedDT { SHPhysicsConstants::DEFAULT_FIXED_DT } { // Add more events here to register them @@ -63,11 +63,6 @@ namespace SHADE return fixedDT; } - double SHPhysicsSystem::GetDefaultFixedDT() const noexcept - { - return DEFAULT_FIXED_STEP; - } - const std::vector& SHPhysicsSystem::GetAllCollisionInfo() const noexcept { return collisionListener.GetCollisionInfoContainer(); diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index 06476c6b..00a252aa 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -21,7 +21,7 @@ #include "Math/Geometry/SHAABB.h" #include "Physics/Collision/SHCollisionInfo.h" #include "Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h" -#include "Physics/RP3DWrapper/SHPhysicsWorld.h" +#include "Physics/RP3DWrapper/SHPhysicsWorldState.h" #include "Physics/RP3DWrapper/SHCollisionListener.h" #include "Physics/RP3DWrapper/SHRaycaster.h" #include "Scene/SHSceneGraph.h" @@ -59,7 +59,6 @@ namespace SHADE [[nodiscard]] double GetFixedUpdateRate () const noexcept; [[nodiscard]] double GetFixedDT () const noexcept; - [[nodiscard]] double GetDefaultFixedDT () const noexcept; [[nodiscard]] const std::vector& GetAllTriggerInfo () const noexcept; [[nodiscard]] const std::vector& GetAllCollisionInfo () const noexcept; @@ -70,6 +69,7 @@ namespace SHADE void SetFixedUpdateRate (double fixedUpdateRate) noexcept; void SetFixedDT (double fixedDt) noexcept; + /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp index fa578836..88502292 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp @@ -60,21 +60,11 @@ namespace SHADE return 0.0; } - double SHPhysicsSystemInterface::GetDeafultFixedDT() noexcept + void SHPhysicsSystemInterface::SetFixedDT(double fixedDT) noexcept { auto* physicsSystem = SHSystemManager::GetSystem(); if (physicsSystem) - return physicsSystem->GetDefaultFixedDT(); - - SHLOGV_WARNING("Failed to get defualt fixed delta time. 0.0 returned instead."); - return 0.0; - } - - void SHPhysicsSystemInterface::SetFixedDT(double value) noexcept - { - auto* physicsSystem = SHSystemManager::GetSystem(); - if (physicsSystem) - physicsSystem->SetFixedDT(value); + physicsSystem->SetFixedDT(fixedDT); SHLOGV_WARNING("Failed to set fixed delta time."); } @@ -89,6 +79,16 @@ namespace SHADE return 0.0; } + void SHPhysicsSystemInterface::SetFixedUpdateRate(double fixedUpdateRate) noexcept + { + auto* physicsSystem = SHSystemManager::GetSystem(); + if (physicsSystem) + return physicsSystem->SetFixedUpdateRate(fixedUpdateRate); + + SHLOGV_WARNING("Failed to set fixed update rate."); + } + + const std::vector& SHPhysicsSystemInterface::Raycast(const RaycastInfo& info) noexcept { static std::vector emptyVec; diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h index 6040a9c2..3b26d3e3 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h @@ -90,12 +90,12 @@ namespace SHADE /* Static Usage Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] static const std::vector& GetCollisionInfo () noexcept; - [[nodiscard]] static const std::vector& GetTriggerInfo () noexcept; - [[nodiscard]] static double GetFixedDT () noexcept; - [[nodiscard]] static void SetFixedDT (double value) noexcept; - [[nodiscard]] static double GetDeafultFixedDT () noexcept; - [[nodiscard]] static int GetFixedUpdateRate () noexcept; + [[nodiscard]] static const std::vector& GetCollisionInfo () noexcept; + [[nodiscard]] static const std::vector& GetTriggerInfo () noexcept; + [[nodiscard]] static double GetFixedDT () noexcept; + [[nodiscard]] static void SetFixedDT (double fixedDT) noexcept; + [[nodiscard]] static int GetFixedUpdateRate () noexcept; + [[nodiscard]] static void SetFixedUpdateRate (double fixedUpdateRate) noexcept; [[nodiscard]] static const std::vector& Raycast (const RaycastInfo& info) noexcept; }; diff --git a/SHADE_Managed/src/Engine/Time.cxx b/SHADE_Managed/src/Engine/Time.cxx index 41a3b1c0..27cf1e22 100644 --- a/SHADE_Managed/src/Engine/Time.cxx +++ b/SHADE_Managed/src/Engine/Time.cxx @@ -17,6 +17,7 @@ of DigiPen Institute of Technology is prohibited. // External Dependencies #include "FRC/SHFramerateController.h" #include "Physics/System/SHPhysicsSystemInterface.h" +#include "Physics/SHPhysicsConstants.h" // Primary Header #include "Time.hxx" @@ -47,7 +48,6 @@ namespace SHADE double Time::DefaultFixDeltaTime::get() { - return SHPhysicsSystemInterface::GetDeafultFixedDT(); + return SHPhysicsConstants::DEFAULT_FIXED_DT; } - } \ No newline at end of file From 33ccdccd8ad9119763575109b766cdb48929cba0 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Tue, 7 Mar 2023 03:23:40 +0800 Subject: [PATCH 05/10] Expanded Physics Settings Editor Menu needs to be resized...idgi... --- .../EditorWindow/MenuBar/SHEditorMenuBar.cpp | 61 ++++++++++-- .../src/Physics/System/SHPhysicsSystem.cpp | 44 +++++++++ .../src/Physics/System/SHPhysicsSystem.h | 23 +++-- .../System/SHPhysicsSystemInterface.cpp | 93 +++++++++++++++++-- .../Physics/System/SHPhysicsSystemInterface.h | 24 +++-- SHADE_Managed/src/Physics/Physics.cxx | 36 ++++++- SHADE_Managed/src/Physics/Physics.hxx | 18 +++- 7 files changed, 264 insertions(+), 35 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp index 6072c6a8..21cc85f4 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp @@ -25,6 +25,7 @@ #include "Serialization/SHSerialization.h" #include "Serialization/Configurations/SHConfigurationManager.h" #include "Editor/EditorWindow/SHEditorWindowManager.h" +#include "Physics/System/SHPhysicsSystem.h" #include "Physics/System/SHPhysicsDebugDrawSystem.h" #include "Camera/SHCameraSystem.h" #include "Tools/Utilities/SHClipboardUtilities.h" @@ -359,21 +360,63 @@ namespace SHADE { if (ImGui::BeginMenu("Physics Settings")) { + if (auto* physicsSystem = SHSystemManager::GetSystem()) + { + SHEditorWidgets::DragVec3 + ( + "Gravity", { "X", "Y", "Z" }, + [physicsSystem] {return physicsSystem->GetGravity(); }, + [physicsSystem](SHVec3 const& value) { physicsSystem->SetGravity(value); } + , false, "Global Gravity", 0.1f, "%.3f", 0.0f, 0.0f + ); + + SHEditorWidgets::SliderScalar + ( + "Velocity Iterations", ImGuiDataType_U16, (uint16_t)1, (uint16_t)32, + [physicsSystem] { return physicsSystem->GetNumVelocityIterations(); }, + [physicsSystem](uint16_t value) { physicsSystem->SetNumVelocityIterations(value); }, + "Number of times velocity is solved per collision. Higher values increase precision at the cost of performance.", + "%zu" + ); + + SHEditorWidgets::SliderScalar + ( + "Position Iterations", ImGuiDataType_U16, (uint16_t)1, (uint16_t)32, + [physicsSystem] { return physicsSystem->GetNumPositionIterations(); }, + [physicsSystem](uint16_t value) { physicsSystem->SetNumPositionIterations(value); }, + "Number of times position is solved per collision. Higher values increase precision at the cost of performance.", + "%zu" + ); + + SHEditorWidgets::CheckBox + ( + "Sleeping Enabled", + [physicsSystem] { return physicsSystem->IsSleepingEnabled(); }, + [physicsSystem](bool value) { physicsSystem->EnableSleeping(value); }, + "If bodies are allowed to sleep. Sleeping increases performance of the simulation and should be left enabled." + ); + } + if (auto* physicsDebugDraw = SHSystemManager::GetSystem()) { - bool drawColliders = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDERS); - if (ImGui::Checkbox("Draw Colliders", &drawColliders)) - physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDERS, drawColliders); + if(ImGui::CollapsingHeader("Debug Draw", ImGuiTreeNodeFlags_DefaultOpen)) + { + bool drawColliders = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDERS); + if (ImGui::Checkbox("Draw Colliders", &drawColliders)) + physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDERS, drawColliders); - bool drawContactPoints = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACTS); - if (ImGui::Checkbox("Draw Contact Points", &drawContactPoints)) - physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACTS, drawContactPoints); + bool drawContactPoints = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACTS); + if (ImGui::Checkbox("Draw Contact Points", &drawContactPoints)) + physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACTS, drawContactPoints); - bool drawRays = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS); - if (ImGui::Checkbox("Draw Rays", &drawRays)) - physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays); + bool drawRays = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS); + if (ImGui::Checkbox("Draw Rays", &drawRays)) + physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays); + } } + + ImGui::EndMenu(); } } diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index de654e0c..e51fdab9 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -73,6 +73,26 @@ namespace SHADE return collisionListener.GetTriggerInfoContainer(); } + const SHVec3& SHPhysicsSystem::GetGravity() const noexcept + { + return worldState.settings.gravity; + } + + uint16_t SHPhysicsSystem::GetNumVelocityIterations() const noexcept + { + return worldState.settings.numVelocitySolverIterations; + } + + uint16_t SHPhysicsSystem::GetNumPositionIterations() const noexcept + { + return worldState.settings.numPositionSolverIterations; + } + + bool SHPhysicsSystem::IsSleepingEnabled() const noexcept + { + return worldState.settings.sleepingEnabled; + } + /*-----------------------------------------------------------------------------------*/ /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -112,6 +132,30 @@ namespace SHADE } } + void SHPhysicsSystem::SetGravity(const SHVec3& gravity) noexcept + { + worldState.settings.gravity = gravity; + worldState.UpdateSettings(); + } + + void SHPhysicsSystem::SetNumVelocityIterations(uint16_t value) noexcept + { + worldState.settings.numVelocitySolverIterations = value; + worldState.UpdateSettings(); + } + + void SHPhysicsSystem::SetNumPositionIterations(uint16_t value) noexcept + { + worldState.settings.numPositionSolverIterations = value; + worldState.UpdateSettings(); + } + + void SHPhysicsSystem::EnableSleeping(bool sleepingAllowed) noexcept + { + worldState.settings.sleepingEnabled = sleepingAllowed; + worldState.UpdateSettings(); + } + /*-----------------------------------------------------------------------------------*/ /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index 00a252aa..fe1e9c5c 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -57,18 +57,29 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] double GetFixedUpdateRate () const noexcept; - [[nodiscard]] double GetFixedDT () const noexcept; + [[nodiscard]] double GetFixedUpdateRate () const noexcept; + [[nodiscard]] double GetFixedDT () const noexcept; - [[nodiscard]] const std::vector& GetAllTriggerInfo () const noexcept; - [[nodiscard]] const std::vector& GetAllCollisionInfo () const noexcept; + [[nodiscard]] const std::vector& GetAllTriggerInfo () const noexcept; + [[nodiscard]] const std::vector& GetAllCollisionInfo () const noexcept; + + // World Settings + [[nodiscard]] const SHVec3& GetGravity () const noexcept; + [[nodiscard]] uint16_t GetNumVelocityIterations () const noexcept; + [[nodiscard]] uint16_t GetNumPositionIterations () const noexcept; + [[nodiscard]] bool IsSleepingEnabled () const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetFixedUpdateRate (double fixedUpdateRate) noexcept; - void SetFixedDT (double fixedDt) noexcept; + void SetFixedUpdateRate (double fixedUpdateRate) noexcept; + void SetFixedDT (double fixedDt) noexcept; + + void SetGravity (const SHVec3& gravity) noexcept; + void SetNumVelocityIterations (uint16_t value) noexcept; + void SetNumPositionIterations (uint16_t value) noexcept; + void EnableSleeping (bool sleepingAllowed) noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp index 88502292..db8cad4e 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp @@ -60,14 +60,7 @@ namespace SHADE return 0.0; } - void SHPhysicsSystemInterface::SetFixedDT(double fixedDT) noexcept - { - auto* physicsSystem = SHSystemManager::GetSystem(); - if (physicsSystem) - physicsSystem->SetFixedDT(fixedDT); - - SHLOGV_WARNING("Failed to set fixed delta time."); - } + int SHPhysicsSystemInterface::GetFixedUpdateRate() noexcept { @@ -79,6 +72,55 @@ namespace SHADE return 0.0; } + SHVec3 SHPhysicsSystemInterface::GetGravity() noexcept + { + auto* physicsSystem = SHSystemManager::GetSystem(); + if (physicsSystem) + return physicsSystem->GetGravity(); + + SHLOGV_WARNING("Failed to get gravity. Zero Vec3 returned instead."); + return SHVec3::Zero; + } + + uint16_t SHPhysicsSystemInterface::GetNumVelocityIterations() noexcept + { + auto* physicsSystem = SHSystemManager::GetSystem(); + if (physicsSystem) + return physicsSystem->GetNumVelocityIterations(); + + SHLOGV_WARNING("Failed to get number of velocity iterations. 0 returned instead."); + return 0; + } + + uint16_t SHPhysicsSystemInterface::GetNumPositionIterations() noexcept + { + auto* physicsSystem = SHSystemManager::GetSystem(); + if (physicsSystem) + return physicsSystem->GetNumPositionIterations(); + + SHLOGV_WARNING("Failed to get number of position iterations. 0 returned instead."); + return 0; + } + + bool SHPhysicsSystemInterface::IsSleepingEnabled() noexcept + { + auto* physicsSystem = SHSystemManager::GetSystem(); + if (physicsSystem) + return physicsSystem->IsSleepingEnabled(); + + SHLOGV_WARNING("Failed to check if sleeping is enabled. False returned instead."); + return false; + } + + void SHPhysicsSystemInterface::SetFixedDT(double fixedDT) noexcept + { + auto* physicsSystem = SHSystemManager::GetSystem(); + if (physicsSystem) + physicsSystem->SetFixedDT(fixedDT); + + SHLOGV_WARNING("Failed to set fixed delta time."); + } + void SHPhysicsSystemInterface::SetFixedUpdateRate(double fixedUpdateRate) noexcept { auto* physicsSystem = SHSystemManager::GetSystem(); @@ -88,6 +130,41 @@ namespace SHADE SHLOGV_WARNING("Failed to set fixed update rate."); } + void SHPhysicsSystemInterface::SetGravity(const SHVec3& gravity) noexcept + { + auto* physicsSystem = SHSystemManager::GetSystem(); + if (physicsSystem) + return physicsSystem->SetGravity(gravity); + + SHLOGV_WARNING("Failed to set gravity."); + } + + void SHPhysicsSystemInterface::SetNumVelocityIterations(uint16_t value) noexcept + { + auto* physicsSystem = SHSystemManager::GetSystem(); + if (physicsSystem) + return physicsSystem->SetNumVelocityIterations(value); + + SHLOGV_WARNING("Failed to set number of velocity iterations."); + } + + void SHPhysicsSystemInterface::SetNumPositionIterations(uint16_t value) noexcept + { + auto* physicsSystem = SHSystemManager::GetSystem(); + if (physicsSystem) + return physicsSystem->SetNumPositionIterations(value); + + SHLOGV_WARNING("Failed to set number of position iterations."); + } + + void SHPhysicsSystemInterface::EnableSleeping(bool sleepingAllowed) noexcept + { + auto* physicsSystem = SHSystemManager::GetSystem(); + if (physicsSystem) + return physicsSystem->EnableSleeping(sleepingAllowed); + + SHLOGV_WARNING("Failed to set global sleeping state."); + } const std::vector& SHPhysicsSystemInterface::Raycast(const RaycastInfo& info) noexcept { diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h index 3b26d3e3..5867f0c2 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h @@ -90,13 +90,23 @@ namespace SHADE /* Static Usage Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] static const std::vector& GetCollisionInfo () noexcept; - [[nodiscard]] static const std::vector& GetTriggerInfo () noexcept; - [[nodiscard]] static double GetFixedDT () noexcept; - [[nodiscard]] static void SetFixedDT (double fixedDT) noexcept; - [[nodiscard]] static int GetFixedUpdateRate () noexcept; - [[nodiscard]] static void SetFixedUpdateRate (double fixedUpdateRate) noexcept; - [[nodiscard]] static const std::vector& Raycast (const RaycastInfo& info) noexcept; + [[nodiscard]] static const std::vector& GetCollisionInfo () noexcept; + [[nodiscard]] static const std::vector& GetTriggerInfo () noexcept; + [[nodiscard]] static double GetFixedDT () noexcept; + [[nodiscard]] static int GetFixedUpdateRate () noexcept; + [[nodiscard]] static SHVec3 GetGravity () noexcept; + [[nodiscard]] static uint16_t GetNumVelocityIterations () noexcept; + [[nodiscard]] static uint16_t GetNumPositionIterations () noexcept; + [[nodiscard]] static bool IsSleepingEnabled () noexcept; + + static void SetFixedDT (double fixedDT) noexcept; + static void SetFixedUpdateRate (double fixedUpdateRate) noexcept; + static void SetGravity (const SHVec3& gravity) noexcept; + static void SetNumVelocityIterations (uint16_t value) noexcept; + static void SetNumPositionIterations (uint16_t value) noexcept; + static void EnableSleeping (bool sleepingAllowed) noexcept; + + [[nodiscard]] static const std::vector& Raycast (const RaycastInfo& info) noexcept; }; } diff --git a/SHADE_Managed/src/Physics/Physics.cxx b/SHADE_Managed/src/Physics/Physics.cxx index 7b2349a6..66e8645b 100644 --- a/SHADE_Managed/src/Physics/Physics.cxx +++ b/SHADE_Managed/src/Physics/Physics.cxx @@ -31,14 +31,42 @@ namespace SHADE Vector3 Physics::Gravity::get() { - // TODO(Diren) - - return Vector3::Zero; + return Convert::ToCLI(SHPhysicsSystemInterface::GetGravity()); } void Physics::Gravity::set(Vector3 value) { - (void)value; + SHPhysicsSystemInterface::SetGravity(Convert::ToNative(value)); + } + + uint16_t Physics::VelocityIterations::get() + { + return SHPhysicsSystemInterface::GetNumVelocityIterations(); + } + + void Physics::VelocityIterations::set(uint16_t value) + { + SHPhysicsSystemInterface::SetNumVelocityIterations(value); + } + + uint16_t Physics::PositionIterations::get() + { + return SHPhysicsSystemInterface::GetNumPositionIterations(); + } + + void Physics::PositionIterations::set(uint16_t value) + { + SHPhysicsSystemInterface::SetNumPositionIterations(value); + } + + bool Physics::SleepingEnabled::get() + { + return SHPhysicsSystemInterface::IsSleepingEnabled(); + } + + void Physics::SleepingEnabled::set(bool value) + { + SHPhysicsSystemInterface::EnableSleeping(value); } /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Physics/Physics.hxx b/SHADE_Managed/src/Physics/Physics.hxx index 7f5e1609..cc4cfc5c 100644 --- a/SHADE_Managed/src/Physics/Physics.hxx +++ b/SHADE_Managed/src/Physics/Physics.hxx @@ -33,7 +33,23 @@ namespace SHADE void set(Vector3 value); } - // TODO(Diren): Add more properties for physics system settings. + static property uint16_t VelocityIterations + { + uint16_t get(); + void set(uint16_t value); + } + + static property uint16_t PositionIterations + { + uint16_t get(); + void set(uint16_t value); + } + + static property bool SleepingEnabled + { + bool get(); + void set(bool value); + } /*---------------------------------------------------------------------------------*/ /* Raycast Function Members */ From 2197a3bcb9015dc30eee0ee4ab578859732eb628 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Tue, 7 Mar 2023 04:51:58 +0800 Subject: [PATCH 06/10] Added capsule collider Debug draw is a bit wonky. Further polish needed, --- Assets/Scenes/PhysicsTest.shade | 9 +- .../Inspector/SHEditorComponentView.hpp | 45 +++-- .../src/Physics/Collision/Shapes/SHBox.cpp | 6 +- .../src/Physics/Collision/Shapes/SHBox.h | 4 - .../Physics/Collision/Shapes/SHCapsule.cpp | 166 ++++++++++++++++++ .../src/Physics/Collision/Shapes/SHCapsule.h | 82 +++++++++ .../Collision/Shapes/SHCollisionShape.cpp | 4 +- .../Collision/Shapes/SHCollisionShape.h | 1 + .../PhysicsObject/SHPhysicsObjectManager.cpp | 19 +- .../Physics/Interface/SHColliderComponent.cpp | 44 +++++ .../Physics/Interface/SHColliderComponent.h | 18 ++ .../System/SHPhysicsDebugDrawSystem.cpp | 23 ++- .../Physics/System/SHPhysicsDebugDrawSystem.h | 14 +- .../src/Serialization/SHYAMLConverters.h | 24 ++- 14 files changed, 404 insertions(+), 55 deletions(-) create mode 100644 SHADE_Engine/src/Physics/Collision/Shapes/SHCapsule.cpp create mode 100644 SHADE_Engine/src/Physics/Collision/Shapes/SHCapsule.h diff --git a/Assets/Scenes/PhysicsTest.shade b/Assets/Scenes/PhysicsTest.shade index 982556af..91afbfa3 100644 --- a/Assets/Scenes/PhysicsTest.shade +++ b/Assets/Scenes/PhysicsTest.shade @@ -5,14 +5,14 @@ Components: Transform Component: Translate: {x: 0, y: 7, z: 0} - Rotate: {x: 1.48352981, y: 0, z: 0} + Rotate: {x: 0, y: 0, z: 0} Scale: {x: 0.999999344, y: 0.999999821, z: 0.999999523} IsActive: true RigidBody Component: Type: Dynamic Drag: 0.00999999978 Angular Drag: 0.100000001 - Gravity Scale: 0.100000001 + Gravity Scale: 1 Use Gravity: true Interpolate: false Sleeping Enabled: true @@ -27,8 +27,9 @@ Colliders: - Is Trigger: false Collision Tag: 0 - Type: Box - Half Extents: {x: 1, y: 1, z: 1} + Type: Capsule + Radius: 1 + Height: 2 Friction: 0.400000006 Bounciness: 0 Density: 1 diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index fe84db31..b671baf4 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -15,6 +15,7 @@ #include "Editor/SHEditorWidgets.hpp" #include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" #include "Physics/Interface/SHColliderComponent.h" #include "Reflection/SHReflectionMetadata.h" #include "Resource/SHResourceManager.h" @@ -25,6 +26,7 @@ #include "Animation/SHAnimatorComponent.h" #include "Physics/Collision/Shapes/SHBox.h" #include "Physics/Collision/Shapes/SHSphere.h" +#include "Physics/Collision/Shapes/SHCapsule.h" #include "../SHEditorWindowManager.h" #include "../AssetBrowser/SHAssetBrowser.h" #include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h" @@ -375,12 +377,26 @@ namespace SHADE ( "Radius", [sphereShape] { return sphereShape->GetRelativeRadius(); }, - [sphereShape](float const& value) { sphereShape->SetRelativeRadius(value); }); + [sphereShape](float const& value) { sphereShape->SetRelativeRadius(value); } + ); + } + else if (collisionShape->GetType() == SHCollisionShape::Type::CAPSULE) + { + SHEditorWidgets::BeginPanel(std::format("{} Capsule #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); + auto* capsuleShape = dynamic_cast(collisionShape); + SHEditorWidgets::DragFloat + ( + "Radius", + [capsuleShape] { return capsuleShape->GetRelativeRadius(); }, + [capsuleShape](float const& value) { capsuleShape->SetRelativeRadius(value); } + ); + SHEditorWidgets::DragFloat + ( + "Height", + [capsuleShape] { return capsuleShape->GetRelativeHeight(); }, + [capsuleShape](float const& value) { capsuleShape->SetRelativeHeight(value); } + ); } - //else if (collisionShape->GetType() == SHCollisionShape::Type::CAPSULE) - //{ - - //} { SHEditorWidgets::CheckBox("Is Trigger", [collisionShape] { return collisionShape->IsTrigger(); }, [collisionShape](bool value) { collisionShape->SetIsTrigger(value); }); @@ -423,25 +439,20 @@ namespace SHADE if (ImGui::BeginMenu("Add Collider")) { - int newColl = -1; + int newCollider = -1; if (ImGui::Selectable("Box Collider")) { - newColl = component->AddBoxCollisionShape(SHVec3::One); + newCollider = component->AddBoxCollisionShape(SHVec3::One); } if (ImGui::Selectable("Sphere Collider")) { - newColl = component->AddSphereCollisionShape(1.0f); + newCollider = component->AddSphereCollisionShape(1.0f); + } + if (ImGui::Selectable("Capsule Collider")) + { + newCollider = component->AddCapsuleCollisionShape(1.0f, 2.0f); } - - //No idea why this doesn't work - //if (newColl > 0) - //{ - // auto newCollisionShape = component->GetCollisionShape(newColl); - // auto prevCollisionShapeInSeq = component->GetCollisionShape(newColl - 1); - // newCollisionShape.SetCollisionTag(SHCollisionTagMatrix::GetTag(prevCollisionShapeInSeq.GetCollisionTag().GetName())); - - //} ImGui::EndMenu(); } diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp index e45d6ef3..6b6921f8 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp @@ -1,5 +1,5 @@ /**************************************************************************************** - * \file SHBoxCollisionShape.cpp + * \file SHBox.cpp * \author Diren D Bharwani, diren.dbharwani, 390002520 * \brief Implementation for a Box Collision Shape. * @@ -34,10 +34,6 @@ namespace SHADE dynamic_cast(rp3dCollider->getCollisionShape())->setHalfExtents(SHVec3::One * 0.5f); } - /*-----------------------------------------------------------------------------------*/ - /* Operator Overload Definitions */ - /*-----------------------------------------------------------------------------------*/ - /*-----------------------------------------------------------------------------------*/ /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.h b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.h index 7cb425d5..fe7cd40d 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.h +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.h @@ -40,10 +40,6 @@ namespace SHADE SHBox () noexcept; ~SHBox () override = default; - /*---------------------------------------------------------------------------------*/ - /* Operator Overloads */ - /*---------------------------------------------------------------------------------*/ - /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHCapsule.cpp b/SHADE_Engine/src/Physics/Collision/Shapes/SHCapsule.cpp new file mode 100644 index 00000000..767b8507 --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHCapsule.cpp @@ -0,0 +1,166 @@ +/**************************************************************************************** + * \file SHCapsule.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Capsule Collision Shape. + * + * \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 + +#include + +// Primary Header +#include "SHCapsule.h" + +// Project Headers +#include "Math/SHMathHelpers.h" +#include "Math/SHMatrix.h" +#include "Physics/Interface/SHColliderComponent.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHCapsule::SHCapsule() noexcept + : SHCollisionShape ( Type::CAPSULE) + , relativeRadius { 1.0f } + , relativeHeight { 2.0f } + , scale { SHVec3::One } + { + if (rp3dCollider) + { + auto* rp3dCapsule = dynamic_cast(rp3dCollider->getCollisionShape()); + rp3dCapsule->setRadius(0.5f); + rp3dCapsule->setHeight(2.0f); + } + } + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + float SHCapsule::GetWorldRadius() const noexcept + { + if (rp3dCollider) + return dynamic_cast(rp3dCollider->getCollisionShape())->getRadius(); + + const float MAX_SCALE = SHMath::Max(scale.x, scale.z); + return relativeRadius * MAX_SCALE * 0.5f; + } + + float SHCapsule::GetRelativeRadius() const noexcept + { + return relativeRadius; + } + + float SHCapsule::GetWorldHeight() const noexcept + { + if (rp3dCollider) + return dynamic_cast(rp3dCollider->getCollisionShape())->getHeight(); + + return relativeHeight * scale.y; + } + + float SHCapsule::GetRelativeHeight() const noexcept + { + return relativeHeight; + } + + SHVec3 SHCapsule::GetWorldCentroid() const noexcept + { + const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset); + const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position); + return SHVec3::Transform(positionOffset, TRS); + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHCapsule::SetWorldRadius(float newWorldRadius) noexcept + { + if (rp3dCollider) + dynamic_cast(rp3dCollider->getCollisionShape())->setRadius(newWorldRadius); + + // Recompute Relative radius + const float MAX_SCALE = SHMath::Max(scale.x, scale.z); + relativeRadius = 2.0f * newWorldRadius / MAX_SCALE; + } + + void SHCapsule::SetRelativeRadius(float newRelativeRadius) noexcept + { + relativeRadius = newRelativeRadius; + + // Recompute world radius + if (rp3dCollider) + { + auto* rp3dCapsule = dynamic_cast(rp3dCollider->getCollisionShape()); + + const float MAX_SCALE = SHMath::Max(scale.x, scale.z); + rp3dCapsule->setRadius(relativeRadius * MAX_SCALE * 0.5f); + } + } + + void SHCapsule::SetWorldHeight(float newWorldHeight) noexcept + { + if (rp3dCollider) + dynamic_cast(rp3dCollider->getCollisionShape())->setHeight(newWorldHeight); + + relativeHeight = newWorldHeight / scale.y; + } + + void SHCapsule::SetRelativeHeight(float newRelativeHeight) noexcept + { + relativeHeight = newRelativeHeight; + + if (rp3dCollider) + dynamic_cast(rp3dCollider->getCollisionShape())->setHeight(relativeHeight * scale.y); + } + + void SHCapsule::SetScale(const SHVec3& newScale) noexcept + { + scale = SHVec3::Abs(newScale); + + // Recompute world radius & Height + if (rp3dCollider) + { + // Get max scale component + const float MAX_SCALE = SHMath::Max(scale.x, scale.z); + + auto* rp3dCapsule = dynamic_cast(rp3dCollider->getCollisionShape()); + rp3dCapsule->setRadius(relativeRadius * MAX_SCALE * 0.5f); + rp3dCapsule->setHeight(relativeHeight * scale.y); + } + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Member Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHCapsule::Update() noexcept + { + const SHTransform& PARENT_TRANSFORM = collider->GetTransform(); + SetScale(PARENT_TRANSFORM.scale); + + SHCollisionShape::Update(); + } + + SHMatrix SHCapsule::GetTRS() const noexcept + { + // The scale of a Capsule would probably be the radius set in the x and z axis, with the height set in the y axis. + // Arbitrary for debug drawing as we specify the position, rotation, height and radius instead. + + const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset); + const SHVec3 SCALE = SHVec3{ GetWorldRadius(), GetWorldHeight(), GetWorldRadius() }; + + const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position); + const SHVec3 POSITION = SHVec3::Transform(positionOffset, TRS); + + return SHMatrix::Transform(POSITION, ROTATION, SCALE); + } +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHCapsule.h b/SHADE_Engine/src/Physics/Collision/Shapes/SHCapsule.h new file mode 100644 index 00000000..06d5fffb --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHCapsule.h @@ -0,0 +1,82 @@ +/**************************************************************************************** + * \file SHCapsule.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Capsule Collision Shape. + * + * \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 "SHCollisionShape.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + /** + * @brief + * Encapsulate a Capsule Shape used for Physics Simulations. + */ + class SH_API SHCapsule final : public SHCollisionShape + { + private: + /*---------------------------------------------------------------------------------*/ + /* Friends */ + /*---------------------------------------------------------------------------------*/ + + friend class SHColliderComponent; + + public: + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHCapsule () noexcept; + ~SHCapsule () override = default; + + /*---------------------------------------------------------------------------------*/ + /* Getter Functions */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] float GetWorldRadius () const noexcept; + [[nodiscard]] float GetRelativeRadius () const noexcept; + [[nodiscard]] float GetWorldHeight () const noexcept; + [[nodiscard]] float GetRelativeHeight () const noexcept; + + [[nodiscard]] SHVec3 GetWorldCentroid () const noexcept override; + + /*---------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*---------------------------------------------------------------------------------*/ + + void SetWorldRadius (float newWorldRadius) noexcept; + void SetRelativeRadius (float newRelativeRadius) noexcept; + void SetWorldHeight (float newWorldHeight) noexcept; + void SetRelativeHeight (float newRelativeHeight) noexcept; + void SetScale (const SHVec3& newScale) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + void Update () noexcept override; + [[nodiscard]] SHMatrix GetTRS () const noexcept override; + + private: + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + float relativeRadius; + float relativeHeight; + SHVec3 scale; + }; + + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp index bd67d42f..7cd8bd4d 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp @@ -237,9 +237,9 @@ RTTR_REGISTRATION registration::enumeration("Collider Type") ( + value("Sphere", SHCollisionShape::Type::SPHERE), value("Box", SHCollisionShape::Type::BOX), - value("Sphere", SHCollisionShape::Type::SPHERE) - // TODO(Diren): Add More Shapes + value("Capsule", SHCollisionShape::Type::CAPSULE) ); registration::class_("Collider") diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h index 8c5fdc22..c7fb7156 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h @@ -53,6 +53,7 @@ namespace SHADE { SPHERE , BOX + , CAPSULE , COUNT , INVALID = -1 diff --git a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp index a0b2f7cc..4043d88d 100644 --- a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp +++ b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp @@ -18,6 +18,7 @@ #include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h" #include "Physics/Collision/Shapes/SHSphere.h" #include "Physics/Collision/Shapes/SHBox.h" +#include "Physics/Collision/Shapes/SHCapsule.h" #include "Physics/Interface/SHColliderComponent.h" #include "Physics/Interface/SHRigidBodyComponent.h" #include "Tools/Utilities/SHUtilities.h" @@ -228,7 +229,7 @@ namespace SHADE { SHColliderDef::ShapeDef shapeDef { - .type = shape->GetType() + .type = shape->GetType() }; colliderDef.shapes.emplace_back(shapeDef); @@ -368,6 +369,22 @@ namespace SHADE break; } + case SHCollisionShape::Type::CAPSULE: + { + auto* capsuleShape = dynamic_cast(collisionShape); + + const float MAX_SCALE = SHMath::Max({ colliderComponent->transform.scale.x, colliderComponent->transform.scale.y, colliderComponent->transform.scale.z }); + const float WORLD_RADIUS = capsuleShape->GetRelativeRadius() * MAX_SCALE * 0.5f; + const float WORLD_HEIGHT = capsuleShape->GetRelativeHeight() * colliderComponent->transform.scale.y; + + rp3d::CapsuleShape* rp3dCapsule = factory->createCapsuleShape(WORLD_RADIUS, WORLD_HEIGHT); + + const rp3d::Transform OFFSETS{ capsuleShape->GetPositionOffset(), SHQuaternion::FromEuler(capsuleShape->GetRotationOffset()) }; + capsuleShape->rp3dCollider = physicsObject->body->addCollider(rp3dCapsule, OFFSETS); + capsuleShape->rp3dCollider->setIsTrigger(capsuleShape->IsTrigger()); + + break; + } default: break; } diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp index 895f57d0..9cefe40e 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp @@ -20,6 +20,7 @@ #include "Physics/SHPhysicsEvents.h" #include "Physics/Collision/Shapes/SHSphere.h" #include "Physics/Collision/Shapes/SHBox.h" +#include "Physics/Collision/Shapes/SHCapsule.h" namespace SHADE { @@ -232,6 +233,49 @@ namespace SHADE return static_cast(NEW_INDEX); } + int SHColliderComponent::AddCapsuleCollisionShape(float relativeRadius, float relativeHeight, const SHVec3& posOffset, const SHVec3& rotOffset) + { + const uint32_t NEW_INDEX = static_cast(shapes.size()); + + // Create collision shape + shapes.emplace_back(new SHCapsule{}); + auto* newCapsule = dynamic_cast(shapes.back()); + + newCapsule->collider = this; + newCapsule->positionOffset = posOffset; + newCapsule->rotationOffset = rotOffset; + newCapsule->relativeRadius = relativeRadius; + newCapsule->relativeHeight = relativeHeight; + newCapsule->scale = SHVec3::Abs(transform.scale); + + // Broadcast Event for adding a shape + const SHPhysicsColliderAddedEvent EVENT_DATA + { + .entityID = GetEID() + , .colliderType = SHCollisionShape::Type::CAPSULE + , .colliderIndex = static_cast(NEW_INDEX) + }; + + SHEventManager::BroadcastEvent(EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT); + + if (factory) + { + const float MAX_SCALE = SHMath::Max(newCapsule->scale.x, newCapsule->scale.z); + const float WORLD_RADIUS = relativeRadius * MAX_SCALE * 0.5f; + const float WORLD_HEIGHT = relativeHeight * newCapsule->scale.y; + + rp3d::CapsuleShape* rp3dCapsule = factory->createCapsuleShape(WORLD_RADIUS, WORLD_HEIGHT); + + const rp3d::Transform OFFSETS{ posOffset, SHQuaternion::FromEuler(rotOffset) }; + newCapsule->rp3dCollider = collisionBody->addCollider(rp3dCapsule, OFFSETS); + + dynamic_cast(collisionBody)->updateMassPropertiesFromColliders(); + } + + return static_cast(NEW_INDEX); + } + + void SHColliderComponent::RemoveCollisionShape(int index) { const int NUM_SHAPES = static_cast(shapes.size()); diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h index 9a141964..1ec534cb 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h @@ -142,6 +142,24 @@ namespace SHADE */ int AddBoxCollisionShape (const SHVec3& relativeExtents, const SHVec3& posOffset = SHVec3::Zero, const SHVec3& rotOffset = SHVec3::Zero); + /** + * @brief + * Adds a capsule collision shape. + * @param relativeRadius + * The relative radius is constructed with respect to the world scale.
+ * Radius = max(scale.x, scale.y, scale.z) * 0.5 * relativeRadius + * @param relativeHeight + * The relative height is constructed with respect to the scale in the y-axis
+ * Height = relativeHeight * scale.y + * @param posOffset + * The position offset of the box from the center of the collider. Defaults to a Zero Vector. + * @param rotOffset + * The rotation offset of the box from the rotation of the collider. Defaults to a Zero Vector. + * @return + * The index of the newly added shape. + */ + int AddCapsuleCollisionShape (float relativeRadius, float relativeHeight, const SHVec3& posOffset = SHVec3::Zero, const SHVec3& rotOffset = SHVec3::Zero); + /** * @brief * Removes a shape from the container. Removal reduces the size of the container. diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp index cff3933e..8fde0249 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp @@ -17,6 +17,7 @@ #include "ECS_Base/Managers/SHSystemManager.h" #include "Math/Transform/SHTransformComponent.h" #include "Physics/SHPhysicsEvents.h" +#include "Physics/Collision/Shapes/SHCapsule.h" #include "Tools/Utilities/SHUtilities.h" namespace SHADE @@ -88,11 +89,6 @@ namespace SHADE } - void SHPhysicsDebugDrawSystem::AddRaycast(const SHRay& ray, const SHPhysicsRaycastResult& result) noexcept - { - - } - /*-----------------------------------------------------------------------------------*/ /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -139,10 +135,19 @@ namespace SHADE debugDrawSystem->DrawWireCube(SHAPE->GetTRS(), DRAW_COLOUR, true); break; } - //case SHCollisionShape::Type::CAPSULE: - //{ - // break; - //} + case SHCollisionShape::Type::CAPSULE: + { + + const auto* CAPSULE_SHAPE = dynamic_cast(SHAPE); + + SHVec3 position, scale; + SHQuaternion rotation; + SHAPE->GetTRS().Decompose(position, rotation, scale); + + debugDrawSystem->DrawWireCapsule(position, rotation, CAPSULE_SHAPE->GetWorldHeight(), CAPSULE_SHAPE->GetWorldRadius(), DRAW_COLOUR, true); + + break; + } default: break; } } diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h index 8c2c9b78..252ff682 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h @@ -64,8 +64,6 @@ namespace SHADE void Init () override; void Exit () override; - void AddRaycast (const SHRay& ray, const SHPhysicsRaycastResult& result) noexcept; - /*---------------------------------------------------------------------------------*/ /* System Routines */ /*---------------------------------------------------------------------------------*/ @@ -119,13 +117,11 @@ namespace SHADE /* Data Members */ /*---------------------------------------------------------------------------------*/ - static constexpr uint8_t ACTIVE_FLAG = 0x01; + static constexpr uint8_t ACTIVE_FLAG = 0x01; + static const SHColour DEBUG_DRAW_COLOURS[static_cast(Colours::COUNT)]; - static const SHColour DEBUG_DRAW_COLOURS[static_cast(Colours::COUNT)]; - - // 0 0 0 drawBroadphase drawRaycasts drawContacts drawAllColliders debugDrawActive + // 0 0 0 0 drawRaycasts drawContacts drawAllColliders debugDrawActive uint8_t flags; - Colliders collidersToDraw; /*---------------------------------------------------------------------------------*/ @@ -133,9 +129,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ SHEventHandle onColliderDraw(SHEventPtr onColliderDrawEvent); - - static void drawCollider (SHDebugDrawSystem* debugDrawSystem, const SHColliderComponent& collider) noexcept; - static void drawRaycast (SHDebugDrawSystem* debugDrawSystem, const DebugDrawInfo::Raycast& raycastInfo) noexcept; + static void drawCollider (SHDebugDrawSystem* debugDrawSystem, const SHColliderComponent& collider) noexcept; }; diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index bd714fd3..b1ae92e0 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -16,6 +16,7 @@ #include "Animation/SHAnimatorComponent.h" #include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h" #include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h" +#include "Physics/Collision/Shapes/SHCapsule.h" namespace YAML { @@ -127,6 +128,7 @@ namespace YAML static constexpr const char* Type = "Type"; static constexpr const char* HalfExtents = "Half Extents"; static constexpr const char* Radius = "Radius"; + static constexpr const char* Height = "Height"; static constexpr const char* Friction = "Friction"; static constexpr const char* Bounciness = "Bounciness"; @@ -161,7 +163,13 @@ namespace YAML node[Radius] = SPHERE_SHAPE.GetRelativeRadius(); } break; - //case SHCollisionShape::Type::CAPSULE: break; + case SHCollisionShape::Type::CAPSULE: + { + const auto& CAPSULE_SHAPE = dynamic_cast(rhs); + node[Radius] = CAPSULE_SHAPE.GetRelativeRadius(); + node[Height] = CAPSULE_SHAPE.GetRelativeHeight(); + } + break; default:; } @@ -203,7 +211,17 @@ namespace YAML dynamic_cast(rhs).SetRelativeRadius(node[Radius].as()); } break; - //case SHCollisionShape::Type::CAPSULE: break; + case SHCollisionShape::Type::CAPSULE: + { + auto& capsule = dynamic_cast(rhs); + + if (node[Radius].IsDefined()) + capsule.SetRelativeRadius(node[Radius].as()); + + if (node[Height].IsDefined()) + capsule.SetRelativeHeight(node[Height].as()); + } + break; default:; } if (node[Friction].IsDefined()) @@ -258,7 +276,7 @@ namespace YAML { case SHCollisionShape::Type::BOX: rhs.AddBoxCollisionShape(SHVec3::One); break; case SHCollisionShape::Type::SPHERE: rhs.AddSphereCollisionShape(1.0f); break; - //case SHCollisionShape::Type::CAPSULE: break; + case SHCollisionShape::Type::CAPSULE: rhs.AddCapsuleCollisionShape(1.0f, 2.0f); break; default:; } YAML::convert::decode(colliderNode, rhs.GetCollisionShape(numColliders++)); From 2147c2c34bddbd0a0ebfa165d65f8e8ead81c8ed Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Tue, 7 Mar 2023 05:00:43 +0800 Subject: [PATCH 07/10] Fixed capsule debug draw Height is distance between centers --- .../src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp index 83ff2d5c..840da97d 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp @@ -378,7 +378,7 @@ namespace SHADE SHQuaternion circleOrientation = SHQuaternion::FromEuler(SHVec3(SHMath::DegreesToRadians(90.0), 0.0f, 0.0f)) * rotation; // Compute top and bottom of the cylinder - const SHVec3 HALF_UP = LOCAL_UP * (height * 0.5f - radius); + const SHVec3 HALF_UP = LOCAL_UP * (height * 0.5f); const SHVec3 TOP_POS = position + HALF_UP; const SHVec3 BOT_POS = position - HALF_UP; From cc2afbcf9f738f51392b1e7a15caf5e9bf6d7ff7 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Tue, 7 Mar 2023 14:13:06 +0800 Subject: [PATCH 08/10] Fixed duplicate collision calls --- .../System/Routines/SHPhysicsPostUpdateRoutine.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPostUpdateRoutine.cpp b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPostUpdateRoutine.cpp index 740df811..3dfe169a 100644 --- a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPostUpdateRoutine.cpp +++ b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPostUpdateRoutine.cpp @@ -105,14 +105,14 @@ namespace SHADE * TODO: Test if the scene graph transforms abides by setting world position. Collisions will ignore the scene graph hierarchy. */ } + + // Collision & Trigger messages + if (scriptingSystem != nullptr) + scriptingSystem->ExecuteCollisionFunctions(); + + // Since this function never runs when editor in not in play, execute the function anyway + physicsSystem->collisionListener.CleanContainers(); } - - // Collision & Trigger messages - if (scriptingSystem != nullptr) - scriptingSystem->ExecuteCollisionFunctions(); - - // Since this function never runs when editor in not in play, execute the function anyway - physicsSystem->collisionListener.CleanContainers(); } } // namespace SHADE \ No newline at end of file From 50dafa555a7c980dc644b6ce02dac36420b29563 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Tue, 7 Mar 2023 18:46:36 +0800 Subject: [PATCH 09/10] Fixed conversion warnings --- .../Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp index 840da97d..d9a740ac 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp @@ -375,7 +375,7 @@ namespace SHADE const SHVec3 LOCAL_FORWARD = SHVec3::Rotate(SHVec3::Forward, rotation); // Rotate the circle - SHQuaternion circleOrientation = SHQuaternion::FromEuler(SHVec3(SHMath::DegreesToRadians(90.0), 0.0f, 0.0f)) * rotation; + SHQuaternion circleOrientation = SHQuaternion::FromEuler(SHVec3(SHMath::DegreesToRadians(90.0f), 0.0f, 0.0f)) * rotation; // Compute top and bottom of the cylinder const SHVec3 HALF_UP = LOCAL_UP * (height * 0.5f); @@ -383,7 +383,7 @@ namespace SHADE const SHVec3 BOT_POS = position - HALF_UP; // Render circles - const SHVec3 CIRCLE_SCALE = SHVec3(radius * 2.0f, radius * 2.0, radius * 2.0); + const SHVec3 CIRCLE_SCALE = SHVec3(radius * 2.0f, radius * 2.0f, radius * 2.0f); drawCircle(meshBatch, SHMatrix::Transform(TOP_POS, circleOrientation, CIRCLE_SCALE), color); drawCircle(meshBatch, SHMatrix::Transform(BOT_POS, circleOrientation, CIRCLE_SCALE), color); @@ -394,7 +394,7 @@ namespace SHADE drawLine(lineBatch, TOP_POS - LOCAL_FORWARD * radius, BOT_POS - LOCAL_FORWARD * radius, color); // Render caps - const SHVec3 RADIUS_SCALE = SHVec3(radius * 2.0, radius * 2.0f, radius * 2.0); + const SHVec3 RADIUS_SCALE = SHVec3(radius * 2.0f, radius * 2.0f, radius * 2.0f); const SHMatrix TOP_CAP_MAT = SHMatrix::Transform(TOP_POS, rotation, RADIUS_SCALE); drawMesh ( @@ -404,7 +404,7 @@ namespace SHADE const SHMatrix BOT_CAP_MAT = SHMatrix::Transform ( BOT_POS, - SHQuaternion::FromEuler(SHVec3(SHMath::DegreesToRadians(180.0), 0.0f, 0.0f)) * rotation, + SHQuaternion::FromEuler(SHVec3(SHMath::DegreesToRadians(180.0f), 0.0f, 0.0f)) * rotation, RADIUS_SCALE ); drawMesh From c36345c60cc1c1c0d0db1141134e9b56d5f691a5 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Tue, 7 Mar 2023 18:48:06 +0800 Subject: [PATCH 10/10] Added a simulate body method Raycast effectiveness is untested, but simulation logic matches standard 3D rigid body simulation methods --- .../src/Camera/SHCameraArmComponent.h | 4 +- SHADE_Engine/src/Physics/SHPhysicsConstants.h | 4 +- .../src/Physics/System/SHPhysicsSystem.cpp | 129 ++++++++++++++++++ .../src/Physics/System/SHPhysicsSystem.h | 36 ++++- 4 files changed, 165 insertions(+), 8 deletions(-) diff --git a/SHADE_Engine/src/Camera/SHCameraArmComponent.h b/SHADE_Engine/src/Camera/SHCameraArmComponent.h index 9d8ec853..76f27360 100644 --- a/SHADE_Engine/src/Camera/SHCameraArmComponent.h +++ b/SHADE_Engine/src/Camera/SHCameraArmComponent.h @@ -9,9 +9,7 @@ namespace SHADE { - - class SHBox; - class SHRay; + struct SHRay; class SH_API SHCameraArmComponent final: public SHComponent { diff --git a/SHADE_Engine/src/Physics/SHPhysicsConstants.h b/SHADE_Engine/src/Physics/SHPhysicsConstants.h index fe3b9ee5..072c7755 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsConstants.h +++ b/SHADE_Engine/src/Physics/SHPhysicsConstants.h @@ -10,14 +10,12 @@ #pragma once -// Project Headers -#include "Math/Vector/SHVec3.h" - namespace SHADE { struct SHPhysicsConstants { static constexpr double DEFAULT_FIXED_DT = 1.0 / 60.0; + static constexpr double DEFAULT_FIXED_UPDATE_RATE = 60.0; static constexpr int DEFAULT_VELOCITY_ITERATIONS = 10; static constexpr int DEFAULT_POSITION_ITERATIONS = 5; diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index e51fdab9..787a9f78 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -236,6 +236,135 @@ namespace SHADE return IS_COLLIDING; } + void SHPhysicsSystem::SimulateBody(std::vector& positions, std::vector& orientations, const SimulateBodyInfo& simInfo) + { + // Check for a valid rigidbody + const auto* rigidBody = SHComponentManager::GetComponent_s(simInfo.bodyEID); + if (!rigidBody) + { + SHLOG_WARNING("Entity {} does not have a rigid body to simulate!", simInfo.bodyEID) + return; + } + + // Ignore non-dynamic bodies + if (rigidBody->type != SHRigidBodyComponent::Type::DYNAMIC) + { + SHLOG_WARNING("Entity {} is not a dynamic body. We cannot simulate non-dynamic bodies!", simInfo.bodyEID) + return; + } + + // Prepare simulation info (I'm basically declaring an entire body here) + SHVec3 bodyPosition = rigidBody->GetPosition(); + SHQuaternion bodyOrientation = SHQuaternion::FromEuler(rigidBody->GetRotation()); + SHVec3 linearVelocity = rigidBody->GetLinearVelocity(); + SHVec3 angularVelocity = rigidBody->GetAngularVelocity(); + float invMass = 1.0f / rigidBody->GetMass(); + SHVec3 localInvInertia = rigidBody->rigidBody->getLocalInertiaTensor(); + SHVec3 worldInvInertia = SHVec3::One; + SHVec3 localCentroid = rigidBody->rigidBody->getLocalCenterOfMass(); + SHVec3 worldCentroid = SHVec3::One; + SHVec3 appliedForce = simInfo.force; + SHVec3 appliedTorque = simInfo.torque; + SHVec3 accumulatedForce = SHVec3::Zero; + SHVec3 accumulatedTorque = SHVec3::Zero; + + const SHVec3& LINEAR_LOCK = rigidBody->rigidBody->getLinearLockAxisFactor(); + const SHVec3& ANGULAR_LOCK = rigidBody->rigidBody->getAngularLockAxisFactor(); + + // Invert the inertia + for (size_t i = 0; i < SHVec3::SIZE; ++i) + localInvInertia[i] = 1.0f / localInvInertia[i]; + + + // Build raycast layer from colliders. If none exist....then this never stops simulating technically. + // I'm too lazy to handle that case, so I'll just throw an error. + uint16_t raycastLayers = 0; + if (const auto* colliders = SHComponentManager::GetComponent_s(simInfo.bodyEID); colliders) + { + const auto& shapes = colliders->GetCollisionShapes(); + for (auto& shape : shapes) + raycastLayers |= shape->GetCollisionTag().GetMask(); + } + else + { + SHLOG_WARNING("Unable to simulate body {} without a collider (it will simulate forever!)", simInfo.bodyEID) + return; + } + + // Raycast direction is always in the direction of the linear velocity + // Raycast distance is the length of the velocity + SHRaycaster::RaycastInfo raycastInfo; + raycastInfo.continuous = false; + raycastInfo.layers = raycastLayers; + + bool terminate = true; + do + { + raycastInfo.distance = linearVelocity.Length(); + raycastInfo.ray.position = bodyPosition; + raycastInfo.ray.direction = SHVec3::Normalise(linearVelocity); + + terminate = !Raycast(raycastInfo).empty(); + if (terminate) + break; + + // Compute world space data + const SHMatrix R = SHMatrix::Rotate(bodyOrientation); + const SHMatrix RT = SHMatrix::Transpose(R); + + SHMatrix localInertiaTensor = SHMatrix::Identity; + + // Set the diagonals + localInertiaTensor.m[0][0] = localInvInertia.x; + localInertiaTensor.m[1][1] = localInvInertia.y; + localInertiaTensor.m[2][2] = localInvInertia.z; + + localInertiaTensor *= RT; + const SHVec3 DIAGONALS { localInertiaTensor.m[0][0], localInertiaTensor.m[1][1], localInertiaTensor.m[2][2] }; + + worldInvInertia = R * DIAGONALS; + + // Compute world centroid + worldCentroid = (R * localCentroid) + bodyPosition; + + // Apply forces + accumulatedForce += appliedForce; + angularVelocity += worldInvInertia * SHVec3::Cross(bodyPosition + simInfo.forceOffset, simInfo.force); + accumulatedTorque += appliedTorque; + + // Integrate Velocities + // Integrate forces and gravity into linear velocity + const SHVec3 LINEAR_ACCELERATION = accumulatedForce * invMass; + const SHVec3 GRAVITATIONAL_ACCELERATION = rigidBody->IsGravityEnabled() ? worldState.settings.gravity * rigidBody->GetGravityScale() : SHVec3::Zero; + + linearVelocity += (LINEAR_ACCELERATION + GRAVITATIONAL_ACCELERATION) * simInfo.timeStep * LINEAR_LOCK; + angularVelocity += worldInvInertia * (accumulatedTorque * simInfo.timeStep); + + // Apply drag (exponentially applied) + linearVelocity *= 1.0f / (1.0f + simInfo.timeStep * rigidBody->drag); + angularVelocity *= 1.0f / (1.0f + simInfo.timeStep * rigidBody->angularDrag); + + // Integrate Positions & Orientations + const SHQuaternion QV = SHQuaternion{ angularVelocity.x * simInfo.timeStep, angularVelocity.y * simInfo.timeStep, angularVelocity.z * simInfo.timeStep, 0.0f } * 0.5f; + + bodyPosition += linearVelocity * simInfo.timeStep; + bodyOrientation += bodyOrientation * QV; + bodyOrientation = SHQuaternion::Normalise(bodyOrientation); + + // Clear forces after the first frame + if (!simInfo.continuousForce) + { + accumulatedForce = SHVec3::Zero; + accumulatedTorque = SHVec3::Zero; + appliedForce = SHVec3::Zero; + appliedTorque = SHVec3::Zero; + } + + positions.emplace_back(bodyPosition); + + } while (true); + } + /*-----------------------------------------------------------------------------------*/ /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index fe1e9c5c..d95203b9 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -44,14 +44,34 @@ namespace SHADE friend class SHRaycaster; public: - + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + + /** + * @brief + * Used to simulate the motion of a rigid body until it hits something. + */ + struct SimulateBodyInfo + { + EntityID bodyEID = MAX_EID; + + SHVec3 force = SHVec3::Zero; + SHVec3 forceOffset = SHVec3::Zero; + SHVec3 torque = SHVec3::Zero; + + // Whether or not to clear the force after the first iteration + bool continuousForce = false; + float timeStep = static_cast(SHPhysicsConstants::DEFAULT_FIXED_DT); + }; + /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ SHPhysicsSystem () noexcept; - ~SHPhysicsSystem() noexcept; + ~SHPhysicsSystem() noexcept override; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ @@ -116,6 +136,18 @@ namespace SHADE */ [[nodiscard]] bool TestAABBOverlap(const SHAABB& aabb, uint16_t layers = static_cast(SHCollisionTag::Layer::ALL)); + /** + * @brief + * Simulates the motion of a body until it collides with something. + * @param positions + * The output vector for the position of the body in each timestep. + * @param orientations + * The output vector for the orientations of the body in each timestep. + * @param simInfo + * The information for simulating the body. + */ + void SimulateBody(std::vector& positions, std::vector& orientations, const SimulateBodyInfo& simInfo); + /*---------------------------------------------------------------------------------*/ /* System Routines */ /*---------------------------------------------------------------------------------*/