diff --git a/Assets/Scenes/M2Scene.shade b/Assets/Scenes/M2Scene.shade index 21050428..bf910737 100644 --- a/Assets/Scenes/M2Scene.shade +++ b/Assets/Scenes/M2Scene.shade @@ -223,9 +223,4 @@ Bounciness: 0 Density: 1 Position Offset: {x: 0, y: 0.5, z: 0} - Scripts: - - Type: Item - currCategory: 0 - - Type: PickAndThrow - throwForce: [100, 200, 100] - item: 51000 \ No newline at end of file + Scripts: ~ \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 2e55ea7a..6091556e 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -223,7 +223,7 @@ namespace SHADE { if (!component) return; - + ImGui::PushID(component); const auto componentType = rttr::type::get(*component); SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active"); ImGui::SameLine(); @@ -246,7 +246,7 @@ namespace SHADE if (collider->GetType() == SHCollisionShape::Type::BOX) { SHEditorWidgets::BeginPanel(std::format("{} Box #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); - const auto* BOX = reinterpret_cast(collider->GetShape()); + const auto* BOX = reinterpret_cast(collider->GetShape()); SHEditorWidgets::DragVec3 ( "Half Extents", { "X", "Y", "Z" }, @@ -256,7 +256,7 @@ namespace SHADE else if (collider->GetType() == SHCollisionShape::Type::SPHERE) { SHEditorWidgets::BeginPanel(std::format("{} Sphere #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); - const auto* SPHERE = reinterpret_cast(collider->GetShape()); + const auto* SPHERE = reinterpret_cast(collider->GetShape()); SHEditorWidgets::DragFloat ( "Radius", @@ -322,6 +322,7 @@ namespace SHADE } } else DrawContextMenu(component); + ImGui::PopID(); } template<> diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp b/SHADE_Engine/src/Math/Geometry/SHBox.cpp similarity index 71% rename from SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp rename to SHADE_Engine/src/Math/Geometry/SHBox.cpp index 5bbf5e15..cf094a9d 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp +++ b/SHADE_Engine/src/Math/Geometry/SHBox.cpp @@ -11,7 +11,7 @@ #include // Primary Header -#include "SHBoundingBox.h" +#include "SHBox.h" // Project Headers #include "Math/SHMathHelpers.h" #include "Math/SHRay.h" @@ -24,13 +24,13 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingBox::SHBoundingBox() noexcept + SHBox::SHBox() noexcept : RelativeExtents { SHVec3::One } { type = Type::BOX; } - SHBoundingBox::SHBoundingBox(const SHVec3& c, const SHVec3& hE) noexcept + SHBox::SHBox(const SHVec3& c, const SHVec3& hE) noexcept : RelativeExtents { SHVec3::One } { type = Type::BOX; @@ -40,7 +40,7 @@ namespace SHADE } - SHBoundingBox::SHBoundingBox(const SHBoundingBox& rhs) noexcept + SHBox::SHBox(const SHBox& rhs) noexcept { if (this == &rhs) return; @@ -52,7 +52,7 @@ namespace SHADE RelativeExtents = rhs.RelativeExtents; } - SHBoundingBox::SHBoundingBox(SHBoundingBox&& rhs) noexcept + SHBox::SHBox(SHBox&& rhs) noexcept { type = Type::BOX; @@ -65,7 +65,7 @@ namespace SHADE /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingBox& SHBoundingBox::operator=(const SHBoundingBox& rhs) noexcept + SHBox& SHBox::operator=(const SHBox& rhs) noexcept { if (rhs.type != Type::BOX) { @@ -81,7 +81,7 @@ namespace SHADE return *this; } - SHBoundingBox& SHBoundingBox::operator=(SHBoundingBox&& rhs) noexcept + SHBox& SHBox::operator=(SHBox&& rhs) noexcept { if (rhs.type != Type::BOX) { @@ -101,27 +101,27 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - SHVec3 SHBoundingBox::GetCenter() const noexcept + SHVec3 SHBox::GetCenter() const noexcept { return Center; } - SHVec3 SHBoundingBox::GetWorldExtents() const noexcept + SHVec3 SHBox::GetWorldExtents() const noexcept { return Extents; } - const SHVec3& SHBoundingBox::GetRelativeExtents() const noexcept + const SHVec3& SHBox::GetRelativeExtents() const noexcept { return RelativeExtents; } - SHVec3 SHBoundingBox::GetMin() const noexcept + SHVec3 SHBox::GetMin() const noexcept { return SHVec3{ Center.x - Extents.x, Center.y - Extents.y, Center.z - Extents.z }; } - SHVec3 SHBoundingBox::GetMax() const noexcept + SHVec3 SHBox::GetMax() const noexcept { return SHVec3{ Center.x + Extents.x, Center.y + Extents.y, Center.z + Extents.z }; } @@ -130,22 +130,22 @@ namespace SHADE /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHBoundingBox::SetCenter(const SHVec3& newCenter) noexcept + void SHBox::SetCenter(const SHVec3& newCenter) noexcept { Center = newCenter; } - void SHBoundingBox::SetWorldExtents(const SHVec3& newWorldExtents) noexcept + void SHBox::SetWorldExtents(const SHVec3& newWorldExtents) noexcept { Extents = newWorldExtents; } - void SHBoundingBox::SetRelativeExtents(const SHVec3& newRelativeExtents) noexcept + void SHBox::SetRelativeExtents(const SHVec3& newRelativeExtents) noexcept { RelativeExtents = newRelativeExtents; } - void SHBoundingBox::SetMin(const SHVec3& min) noexcept + void SHBox::SetMin(const SHVec3& min) noexcept { const SHVec3 MAX = GetMax(); @@ -153,7 +153,7 @@ namespace SHADE Extents = SHVec3::Abs((MAX - min) * 0.5f); } - void SHBoundingBox::SetMax(const SHVec3& max) noexcept + void SHBox::SetMax(const SHVec3& max) noexcept { const SHVec3 MIN = GetMin(); @@ -161,13 +161,13 @@ namespace SHADE Extents = SHVec3::Abs((max - MIN) * 0.5f); } - void SHBoundingBox::SetMinMax(const SHVec3& min, const SHVec3& max) noexcept + void SHBox::SetMinMax(const SHVec3& min, const SHVec3& max) noexcept { Center = SHVec3::Lerp(min, max, 0.5f); Extents = SHVec3::Abs((max - min) * 0.5f); } - std::vector SHBoundingBox::GetVertices() const noexcept + std::vector SHBox::GetVertices() const noexcept { std::vector vertices{ 8 }; GetCorners(vertices.data()); @@ -178,27 +178,27 @@ namespace SHADE /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - bool SHBoundingBox::TestPoint(const SHVec3& point) noexcept + bool SHBox::TestPoint(const SHVec3& point) noexcept { return BoundingBox::Contains(point); } - bool SHBoundingBox::Raycast(const SHRay& ray, float& distance) noexcept + bool SHBox::Raycast(const SHRay& ray, float& distance) noexcept { return BoundingBox::Intersects(ray.position, ray.direction, distance); } - bool SHBoundingBox::Contains(const SHBoundingBox& rhs) const noexcept + bool SHBox::Contains(const SHBox& rhs) const noexcept { return BoundingBox::Contains(rhs); } - float SHBoundingBox::Volume() const noexcept + float SHBox::Volume() const noexcept { return 8.0f * (Extents.x * Extents.y * Extents.z); } - float SHBoundingBox::SurfaceArea() const noexcept + float SHBox::SurfaceArea() const noexcept { return 8.0f * ((Extents.x * Extents.y) + (Extents.x * Extents.z) @@ -209,21 +209,21 @@ namespace SHADE /* Static Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingBox SHBoundingBox::Combine(const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept + SHBox SHBox::Combine(const SHBox& lhs, const SHBox& rhs) noexcept { - SHBoundingBox result; + SHBox result; CreateMerged(result, lhs, rhs); return result; } - bool SHBoundingBox::Intersect(const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept + bool SHBox::Intersect(const SHBox& lhs, const SHBox& rhs) noexcept { return lhs.Intersects(rhs); } - SHBoundingBox SHBoundingBox::BuildFromBoxes(const SHBoundingBox* boxes, size_t numBoxes) noexcept + SHBox SHBox::BuildFromBoxes(const SHBox* boxes, size_t numBoxes) noexcept { - SHBoundingBox result; + SHBox result; for (size_t i = 1; i < numBoxes; ++i) CreateMerged(result, boxes[i - 1], boxes[i]); @@ -231,9 +231,9 @@ namespace SHADE return result; } - SHBoundingBox SHBoundingBox::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept + SHBox SHBox::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept { - SHBoundingBox result; + SHBox result; CreateFromPoints(result, numVertices, vertices, stride); return result; } diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.h b/SHADE_Engine/src/Math/Geometry/SHBox.h similarity index 80% rename from SHADE_Engine/src/Math/Geometry/SHBoundingBox.h rename to SHADE_Engine/src/Math/Geometry/SHBox.h index e2757c17..0ea950ab 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.h +++ b/SHADE_Engine/src/Math/Geometry/SHBox.h @@ -22,8 +22,8 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - class SH_API SHBoundingBox : public SHShape, - private DirectX::BoundingBox + class SH_API SHBox : public SHShape, + private DirectX::BoundingBox { public: /*---------------------------------------------------------------------------------*/ @@ -36,19 +36,19 @@ namespace SHADE /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - ~SHBoundingBox () override = default; + ~SHBox () override = default; - SHBoundingBox () noexcept; - SHBoundingBox (const SHVec3& center, const SHVec3& halfExtents) noexcept; - SHBoundingBox (const SHBoundingBox& rhs) noexcept; - SHBoundingBox (SHBoundingBox&& rhs) noexcept; + SHBox () noexcept; + SHBox (const SHVec3& center, const SHVec3& halfExtents) noexcept; + SHBox (const SHBox& rhs) noexcept; + SHBox (SHBox&& rhs) noexcept; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ /*---------------------------------------------------------------------------------*/ - SHBoundingBox& operator= (const SHBoundingBox& rhs) noexcept; - SHBoundingBox& operator= (SHBoundingBox&& rhs) noexcept; + SHBox& operator= (const SHBox& rhs) noexcept; + SHBox& operator= (SHBox&& rhs) noexcept; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ @@ -79,7 +79,7 @@ namespace SHADE [[nodiscard]] bool TestPoint (const SHVec3& point) noexcept override; [[nodiscard]] bool Raycast (const SHRay& ray, float& distance) noexcept override; - [[nodiscard]] bool Contains (const SHBoundingBox& rhs) const noexcept; + [[nodiscard]] bool Contains (const SHBox& rhs) const noexcept; [[nodiscard]] float Volume () const noexcept; [[nodiscard]] float SurfaceArea () const noexcept; @@ -87,10 +87,10 @@ namespace SHADE /* Static Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] static SHBoundingBox Combine (const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept; - [[nodiscard]] static bool Intersect (const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept; - [[nodiscard]] static SHBoundingBox BuildFromBoxes (const SHBoundingBox* boxes, size_t numBoxes) noexcept; - [[nodiscard]] static SHBoundingBox BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; + [[nodiscard]] static SHBox Combine (const SHBox& lhs, const SHBox& rhs) noexcept; + [[nodiscard]] static bool Intersect (const SHBox& lhs, const SHBox& rhs) noexcept; + [[nodiscard]] static SHBox BuildFromBoxes (const SHBox* boxes, size_t numBoxes) noexcept; + [[nodiscard]] static SHBox BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp b/SHADE_Engine/src/Math/Geometry/SHSphere.cpp similarity index 70% rename from SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp rename to SHADE_Engine/src/Math/Geometry/SHSphere.cpp index f843a6bb..d310e30e 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp +++ b/SHADE_Engine/src/Math/Geometry/SHSphere.cpp @@ -11,7 +11,7 @@ #include // Primary Header -#include "SHBoundingSphere.h" +#include "SHSphere.h" // Project Headers #include "Math/SHMathHelpers.h" #include "Math/SHRay.h" @@ -24,13 +24,13 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingSphere::SHBoundingSphere() noexcept + SHSphere::SHSphere() noexcept : RelativeRadius { 1.0f } { type = Type::SPHERE; } - SHBoundingSphere::SHBoundingSphere(const SHVec3& center, float radius) noexcept + SHSphere::SHSphere(const SHVec3& center, float radius) noexcept : RelativeRadius { 1.0f } { type = Type::SPHERE; @@ -39,7 +39,7 @@ namespace SHADE Radius = radius; } - SHBoundingSphere::SHBoundingSphere(const SHBoundingSphere& rhs) noexcept + SHSphere::SHSphere(const SHSphere& rhs) noexcept { if (this == &rhs) return; @@ -51,7 +51,7 @@ namespace SHADE RelativeRadius = rhs.RelativeRadius; } - SHBoundingSphere::SHBoundingSphere(SHBoundingSphere&& rhs) noexcept + SHSphere::SHSphere(SHSphere&& rhs) noexcept { type = Type::SPHERE; @@ -64,7 +64,7 @@ namespace SHADE /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingSphere& SHBoundingSphere::operator=(const SHBoundingSphere& rhs) noexcept + SHSphere& SHSphere::operator=(const SHSphere& rhs) noexcept { if (rhs.type != Type::SPHERE) { @@ -80,7 +80,7 @@ namespace SHADE return *this; } - SHBoundingSphere& SHBoundingSphere::operator=(SHBoundingSphere&& rhs) noexcept + SHSphere& SHSphere::operator=(SHSphere&& rhs) noexcept { if (rhs.type != Type::SPHERE) { @@ -100,17 +100,17 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - SHVec3 SHBoundingSphere::GetCenter() const noexcept + SHVec3 SHSphere::GetCenter() const noexcept { return Center; } - float SHBoundingSphere::GetWorldRadius() const noexcept + float SHSphere::GetWorldRadius() const noexcept { return Radius; } - float SHBoundingSphere::GetRelativeRadius() const noexcept + float SHSphere::GetRelativeRadius() const noexcept { return RelativeRadius; } @@ -119,17 +119,17 @@ namespace SHADE /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHBoundingSphere::SetCenter(const SHVec3& center) noexcept + void SHSphere::SetCenter(const SHVec3& center) noexcept { Center = center; } - void SHBoundingSphere::SetWorldRadius(float newWorldRadius) noexcept + void SHSphere::SetWorldRadius(float newWorldRadius) noexcept { Radius = newWorldRadius; } - void SHBoundingSphere::SetRelativeRadius(float newRelativeRadius) noexcept + void SHSphere::SetRelativeRadius(float newRelativeRadius) noexcept { RelativeRadius = newRelativeRadius; } @@ -138,27 +138,27 @@ namespace SHADE /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - bool SHBoundingSphere::TestPoint(const SHVec3& point) noexcept + bool SHSphere::TestPoint(const SHVec3& point) noexcept { return BoundingSphere::Contains(point); } - bool SHBoundingSphere::Raycast(const SHRay& ray, float& distance) noexcept + bool SHSphere::Raycast(const SHRay& ray, float& distance) noexcept { return Intersects(ray.position, ray.direction, distance); } - bool SHBoundingSphere::Contains(const SHBoundingSphere& rhs) const noexcept + bool SHSphere::Contains(const SHSphere& rhs) const noexcept { return BoundingSphere::Contains(rhs); } - float SHBoundingSphere::Volume() const noexcept + float SHSphere::Volume() const noexcept { return (4.0f / 3.0f) * SHMath::PI * (Radius * Radius * Radius); } - float SHBoundingSphere::SurfaceArea() const noexcept + float SHSphere::SurfaceArea() const noexcept { return 4.0f * SHMath::PI * (Radius * Radius); } @@ -167,21 +167,21 @@ namespace SHADE /* Static Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingSphere SHBoundingSphere::Combine(const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept + SHSphere SHSphere::Combine(const SHSphere& lhs, const SHSphere& rhs) noexcept { - SHBoundingSphere result; + SHSphere result; CreateMerged(result, lhs, rhs); return result; } - bool SHBoundingSphere::Intersect(const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept + bool SHSphere::Intersect(const SHSphere& lhs, const SHSphere& rhs) noexcept { return lhs.Intersects(rhs); } - SHBoundingSphere SHBoundingSphere::BuildFromSpheres(const SHBoundingSphere* spheres, size_t numSpheres) noexcept + SHSphere SHSphere::BuildFromSpheres(const SHSphere* spheres, size_t numSpheres) noexcept { - SHBoundingSphere result; + SHSphere result; for (size_t i = 1; i < numSpheres; ++i) CreateMerged(result, spheres[i - 1], spheres[i]); @@ -189,9 +189,9 @@ namespace SHADE return result; } - SHBoundingSphere SHBoundingSphere::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept + SHSphere SHSphere::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept { - SHBoundingSphere result; + SHSphere result; CreateFromPoints(result, numVertices, vertices, stride); return result; } diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h b/SHADE_Engine/src/Math/Geometry/SHSphere.h similarity index 76% rename from SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h rename to SHADE_Engine/src/Math/Geometry/SHSphere.h index d94722d6..c13076aa 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h +++ b/SHADE_Engine/src/Math/Geometry/SHSphere.h @@ -22,27 +22,27 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - class SH_API SHBoundingSphere : public SHShape, - private DirectX::BoundingSphere + class SH_API SHSphere : public SHShape, + private DirectX::BoundingSphere { public: /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHBoundingSphere () noexcept; - SHBoundingSphere (const SHVec3& center, float radius) noexcept; - SHBoundingSphere (const SHBoundingSphere& rhs) noexcept; - SHBoundingSphere (SHBoundingSphere&& rhs) noexcept; + SHSphere () noexcept; + SHSphere (const SHVec3& center, float radius) noexcept; + SHSphere (const SHSphere& rhs) noexcept; + SHSphere (SHSphere&& rhs) noexcept; - ~SHBoundingSphere () override = default; + ~SHSphere () override = default; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ /*---------------------------------------------------------------------------------*/ - SHBoundingSphere& operator= (const SHBoundingSphere& rhs) noexcept; - SHBoundingSphere& operator= (SHBoundingSphere&& rhs) noexcept; + SHSphere& operator= (const SHSphere& rhs) noexcept; + SHSphere& operator= (SHSphere&& rhs) noexcept; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ @@ -67,7 +67,7 @@ namespace SHADE [[nodiscard]] bool TestPoint (const SHVec3& point) noexcept override; [[nodiscard]] bool Raycast (const SHRay& ray, float& distance) noexcept override; - [[nodiscard]] bool Contains (const SHBoundingSphere& rhs) const noexcept; + [[nodiscard]] bool Contains (const SHSphere& rhs) const noexcept; [[nodiscard]] float Volume () const noexcept; [[nodiscard]] float SurfaceArea () const noexcept; @@ -76,10 +76,10 @@ namespace SHADE /* Static Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] static SHBoundingSphere Combine (const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept; - [[nodiscard]] static bool Intersect (const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept; - [[nodiscard]] static SHBoundingSphere BuildFromSpheres (const SHBoundingSphere* spheres, size_t numSpheres) noexcept; - [[nodiscard]] static SHBoundingSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; + [[nodiscard]] static SHSphere Combine (const SHSphere& lhs, const SHSphere& rhs) noexcept; + [[nodiscard]] static bool Intersect (const SHSphere& lhs, const SHSphere& rhs) noexcept; + [[nodiscard]] static SHSphere BuildFromSpheres (const SHSphere* spheres, size_t numSpheres) noexcept; + [[nodiscard]] static SHSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp index 1c8149ad..877d238f 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp @@ -95,7 +95,7 @@ namespace SHADE { case SHCollisionShape::Type::BOX: { - auto* box = reinterpret_cast(collisionShape.shape); + auto* box = reinterpret_cast(collisionShape.shape); const SHVec3& RELATIVE_EXTENTS = box->GetRelativeExtents(); // Recompute world extents based on new scale and fixed relative extents @@ -106,7 +106,7 @@ namespace SHADE } case SHCollisionShape::Type::SPHERE: { - auto* sphere = reinterpret_cast(collisionShape.shape); + auto* sphere = reinterpret_cast(collisionShape.shape); const float RELATIVE_RADIUS = sphere->GetRelativeRadius(); // Recompute world radius based on new scale and fixed radius diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h index 88dc306f..0781f3cf 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h @@ -14,8 +14,8 @@ // Project Headers #include "ECS_Base/Components/SHComponent.h" -#include "Math/Geometry/SHBoundingBox.h" -#include "Math/Geometry/SHBoundingSphere.h" +#include "Math/Geometry/SHBox.h" +#include "Math/Geometry/SHSphere.h" #include "SHCollisionShape.h" //namespace SHADE diff --git a/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp b/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp index 1ea2a7d3..2edca110 100644 --- a/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp @@ -13,8 +13,8 @@ // Primary Header #include "SHCollisionShape.h" // Project Headers -#include "Math/Geometry/SHBoundingBox.h" -#include "Math/Geometry/SHBoundingSphere.h" +#include "Math/Geometry/SHBox.h" +#include "Math/Geometry/SHSphere.h" #include "Math/SHMathHelpers.h" #include "Reflection/SHReflectionMetadata.h" #include "SHColliderComponent.h" @@ -37,12 +37,12 @@ namespace SHADE { case Type::BOX: { - shape = new SHBoundingBox{ SHVec3::Zero, SHVec3::One }; + shape = new SHBox{ SHVec3::Zero, SHVec3::One }; break; } case Type::SPHERE: { - shape = new SHBoundingSphere{ SHVec3::Zero, 0.5f }; + shape = new SHSphere{ SHVec3::Zero, 0.5f }; break; } default: break; @@ -186,10 +186,10 @@ namespace SHADE type = Type::BOX; delete shape; - shape = new SHBoundingBox{ positionOffset, WORLD_EXTENTS }; + shape = new SHBox{ positionOffset, WORLD_EXTENTS }; } - auto* box = reinterpret_cast(shape); + auto* box = reinterpret_cast(shape); box->SetWorldExtents(WORLD_EXTENTS); box->SetRelativeExtents(halfExtents); } @@ -209,10 +209,10 @@ namespace SHADE type = Type::SPHERE; delete shape; - shape = new SHBoundingSphere{ positionOffset, WORLD_RADIUS }; + shape = new SHSphere{ positionOffset, WORLD_RADIUS }; } - auto* sphere = reinterpret_cast(shape); + auto* sphere = reinterpret_cast(shape); sphere->SetWorldRadius(WORLD_RADIUS); } @@ -255,12 +255,12 @@ namespace SHADE { case Type::BOX: { - reinterpret_cast(shape)->SetCenter(positionOffset); + reinterpret_cast(shape)->SetCenter(positionOffset); break; } case Type::SPHERE: { - reinterpret_cast(shape)->SetCenter(positionOffset); + reinterpret_cast(shape)->SetCenter(positionOffset); break; } default: break; @@ -283,16 +283,16 @@ namespace SHADE { case Type::BOX: { - const auto* RHS_BOX = reinterpret_cast(rhs); + const auto* RHS_BOX = reinterpret_cast(rhs); - shape = new SHBoundingBox{ positionOffset, RHS_BOX->GetWorldExtents() }; + shape = new SHBox{ positionOffset, RHS_BOX->GetWorldExtents() }; break; } case Type::SPHERE: { - const auto* RHS_SPHERE = reinterpret_cast(rhs); + const auto* RHS_SPHERE = reinterpret_cast(rhs); - shape = new SHBoundingSphere{ positionOffset, RHS_SPHERE->GetWorldRadius() }; + shape = new SHSphere{ positionOffset, RHS_SPHERE->GetWorldRadius() }; break; } default: break; diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp index 0c9fa405..346ab4cb 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp @@ -16,6 +16,7 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHComponentManager.h" +#include "Scene/SHSceneManager.h" namespace SHADE @@ -25,10 +26,11 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept - : entityID { eid } - , factory { physicsFactory } - , world { physicsWorld } - , rp3dBody { nullptr } + : entityID { eid } + , collidersActive { true } + , factory { physicsFactory } + , world { physicsWorld } + , rp3dBody { nullptr } { // Implicitly create a static body. @@ -148,6 +150,10 @@ namespace SHADE void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent& component) const noexcept { + // This state is synced in the pre-update routine + if (!rp3dBody->isActive()) + return; + if (component.dirtyFlags == 0) return; @@ -267,6 +273,10 @@ namespace SHADE void SHPhysicsObject::SyncColliders(SHColliderComponent& component) const noexcept { + // This state is synced in the pre-update routine + if (!rp3dBody->isActive()) + return; + int index = 0; for (auto& collisionShape : component.collisionShapes) { @@ -299,7 +309,7 @@ namespace SHADE , boxShape.GetRotationOffset() }; - const auto* BOX = reinterpret_cast(boxShape.GetShape()); + const auto* BOX = reinterpret_cast(boxShape.GetShape()); rp3d::BoxShape* newBox = factory->createBoxShape(BOX->GetWorldExtents()); rp3dBody->addCollider(newBox, OFFSETS); @@ -307,7 +317,7 @@ namespace SHADE void SHPhysicsObject::syncBoxShape(int index, SHCollisionShape& boxShape) const noexcept { - const auto* BOX = reinterpret_cast(boxShape.GetShape()); + const auto* BOX = reinterpret_cast(boxShape.GetShape()); auto* rp3dCollider = rp3dBody->getCollider(index); auto* rp3dBox = reinterpret_cast(rp3dCollider->getCollisionShape()); @@ -332,7 +342,7 @@ namespace SHADE , sphereShape.GetRotationOffset() }; - const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); + const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); rp3d::SphereShape* newSphere = factory->createSphereShape(SPHERE->GetWorldRadius()); rp3dBody->addCollider(newSphere, OFFSETS); @@ -340,7 +350,7 @@ namespace SHADE void SHPhysicsObject::syncSphereShape(int index, SHCollisionShape& sphereShape) const noexcept { - const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); + const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); auto* rp3dCollider = rp3dBody->getCollider(index); auto* rp3dSphere = reinterpret_cast(rp3dCollider->getCollisionShape()); diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h index f18a0738..fefc983f 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h @@ -84,12 +84,13 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ EntityID entityID; + bool collidersActive; // Only used to sync with SHADE components rp3d::PhysicsCommon* factory; rp3d::PhysicsWorld* world; rp3d::RigidBody* rp3dBody; - rp3d::Transform prevTransform; // Cached transform for interpolation + rp3d::Transform prevTransform; // Cached transform for interpolation /*---------------------------------------------------------------------------------*/ /* Function Members */ diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp index 13f525e6..f8a4040f 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp @@ -167,6 +167,7 @@ namespace SHADE if (!COMPONENT_GROUP.rigidBodyComponent && !COMPONENT_GROUP.colliderComponent) { destroyPhysicsObject(COMMAND.eid); + wakeAllObjects(); continue; } @@ -176,6 +177,10 @@ namespace SHADE physicsObject = createPhysicsObject(COMMAND.eid); componentFunc[SHUtilities::ConvertEnum(COMMAND.command)][SHUtilities::ConvertEnum(COMMAND.component)](COMMAND, physicsObject, COMPONENT_GROUP); + + // If any removal was done, wake all objects + if (COMMAND.command == QueueCommand::Command::REMOVE) + wakeAllObjects(); } } @@ -297,5 +302,11 @@ namespace SHADE physicsObject->RemoveCollisionShape(command.shapeIndex); } + void SHPhysicsObjectManager::wakeAllObjects() noexcept + { + for (auto& physicsObject : physicsObjects | std::views::values) + physicsObject.GetRigidBody()->setIsSleeping(false); + } + } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h index d8c9b805..641fd9df 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h @@ -165,6 +165,8 @@ namespace SHADE SHPhysicsObject* createPhysicsObject (EntityID eid) noexcept; void destroyPhysicsObject (EntityID eid) noexcept; + void wakeAllObjects () noexcept; + static void addRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); static void addCollider (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); static void removeRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); @@ -172,6 +174,8 @@ namespace SHADE static void addCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); static void removeCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); + + }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp index ff441ac2..44875289 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp @@ -16,6 +16,7 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" #include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h" +#include "Scene/SHSceneManager.h" namespace SHADE { @@ -122,6 +123,10 @@ namespace SHADE const auto& COLLIDER_SET = SHComponentManager::GetDense(); for (const auto& COLLIDER : COLLIDER_SET) { + // Skip inactive colliders + if (!SHSceneManager::CheckNodeAndComponentsActive(COLLIDER.GetEID())) + continue; + for (auto& collisionShape : COLLIDER.GetCollisionShapes()) { switch (collisionShape.GetType()) @@ -176,7 +181,7 @@ namespace SHADE return; } - auto* BOX = reinterpret_cast(collisionShape.GetShape()); + auto* BOX = reinterpret_cast(collisionShape.GetShape()); // Calculate final position & orientation const SHVec3 FINAL_POS = colliderComponent.GetPosition() + collisionShape.GetPositionOffset(); @@ -216,7 +221,7 @@ namespace SHADE return; } - auto* SPHERE = reinterpret_cast(collisionShape.GetShape()); + auto* SPHERE = reinterpret_cast(collisionShape.GetShape()); const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN; diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index 34f0c698..5f679655 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -20,6 +20,7 @@ #include "Editor/SHEditor.h" #include "Physics/SHPhysicsEvents.h" #include "Scene/SHSceneManager.h" +#include "Scripting/SHScriptEngine.h" /*-------------------------------------------------------------------------------------*/ /* Local Helper Functions */ @@ -34,16 +35,16 @@ namespace SHADE SHPhysicsSystem::SHPhysicsSystem() : worldUpdated { false } , interpolationFactor { 0.0 } - , fixedDT { 60.0 } + , fixedDT { DEFAULT_FIXED_STEP } {} /*-----------------------------------------------------------------------------------*/ /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - double SHPhysicsSystem::GetFixedDT() const noexcept + double SHPhysicsSystem::GetFixedUpdateRate() const noexcept { - return fixedDT; + return 1.0 / fixedDT; } const SHPhysicsWorldState::WorldSettings& SHPhysicsSystem::GetWorldSettings() const noexcept @@ -76,9 +77,9 @@ namespace SHADE /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHPhysicsSystem::SetFixedDT(double fixedUpdateRate) noexcept + void SHPhysicsSystem::SetFixedUpdateRate(double fixedUpdateRate) noexcept { - fixedDT = fixedUpdateRate; + fixedDT = 1.0 / fixedUpdateRate; } void SHPhysicsSystem::SetWorldSettings(const SHPhysicsWorldState::WorldSettings& settings) noexcept @@ -126,6 +127,45 @@ namespace SHADE worldState.DestroyWorld(factory); } + void SHPhysicsSystem::ForceUpdate() + { + if (!worldState.world) + { + SHLOGV_ERROR("Unable to force update without a Physics world!") + return; + } + + auto* scriptingSystem = SHSystemManager::GetSystem(); + if (scriptingSystem == nullptr) + { + SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!"); + } + + // Force the physics world to update once + if (scriptingSystem != nullptr) + scriptingSystem->ExecuteFixedUpdates(); + + worldState.world->update(static_cast(fixedDT)); + + // Sync transforms. No interpolation applied here + for (auto& [entityID, physicsObject] : objectManager.physicsObjects) + { + auto* transformComponent = SHComponentManager::GetComponent_s(entityID); + auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); + auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); + + postUpdateSyncTransforms + ( + physicsObject + , transformComponent + , rigidBodyComponent + , colliderComponent + , 1.0 // We use 1.0 here to avoid any interpolation + ); + } + } + + void SHPhysicsSystem::AddCollisionShape(EntityID eid, int shapeIndex) { static const auto ADD_SHAPE = [&](EntityID entityID, int index) @@ -185,44 +225,51 @@ namespace SHADE void SHPhysicsSystem::AddForce(EntityID eid, const SHVec3& force) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); - + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyWorldForceAtCenterOfMass(force); } void SHPhysicsSystem::AddForceAtLocalPos(EntityID eid, const SHVec3& force, const SHVec3& localPos) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyWorldForceAtLocalPosition(force, localPos); } void SHPhysicsSystem::AddForceAtWorldPos(EntityID eid, const SHVec3& force, const SHVec3& worldPos) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyWorldForceAtWorldPosition(force, worldPos); } void SHPhysicsSystem::AddRelativeForce(EntityID eid, const SHVec3& relativeForce) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyLocalForceAtCenterOfMass(relativeForce); } void SHPhysicsSystem::AddRelativeForceAtLocalPos(EntityID eid, const SHVec3& relativeForce, const SHVec3& localPos) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyLocalForceAtLocalPosition(relativeForce, localPos); } void SHPhysicsSystem::AddRelativeForceAtWorldPos(EntityID eid, const SHVec3& relativeForce, const SHVec3& worldPos) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyLocalForceAtWorldPosition(relativeForce, worldPos); } void SHPhysicsSystem::AddTorque(EntityID eid, const SHVec3& torque) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyWorldTorque(torque); } void SHPhysicsSystem::AddRelativeTorque(EntityID eid, const SHVec3& relativeTorque) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyLocalTorque(relativeTorque); } /*-----------------------------------------------------------------------------------*/ @@ -339,5 +386,93 @@ namespace SHADE return onStopEvent->handle; } + void SHPhysicsSystem::preUpdateSyncTransform + ( + SHPhysicsObject& physicsObject + , SHTransformComponent* transformComponent + , SHRigidBodyComponent* rigidBodyComponent + , SHColliderComponent* colliderComponent + ) noexcept + { + if (!transformComponent) + return; + + const SHVec3& WORLD_POS = transformComponent->GetWorldPosition(); + const SHQuaternion& WORLD_ROT = transformComponent->GetWorldOrientation(); + const SHVec3& WORLD_SCL = transformComponent->GetWorldScale(); + + const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT }; + physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM); + + if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) + { + rigidBodyComponent->position = WORLD_POS; + rigidBodyComponent->orientation = WORLD_ROT; + } + + if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) + { + colliderComponent->position = WORLD_POS; + colliderComponent->orientation = WORLD_ROT; + colliderComponent->scale = WORLD_SCL; + + colliderComponent->RecomputeCollisionShapes(); + } + } + + void SHPhysicsSystem::postUpdateSyncTransforms + ( + SHPhysicsObject& physicsObject + , SHTransformComponent* transformComponent + , SHRigidBodyComponent* rigidBodyComponent + , SHColliderComponent* colliderComponent + , double interpolationFactor + ) noexcept + { + const rp3d::Transform& CURRENT_TF = physicsObject.GetRigidBody()->getTransform(); + auto renderPos = CURRENT_TF.getPosition(); + auto renderRot = CURRENT_TF.getOrientation(); + + // Cache transforms + if (physicsObject.GetRigidBody()->isActive()) + physicsObject.prevTransform = CURRENT_TF; + + // Sync with rigid bodies + if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) + { + // Skip static bodies + if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC) + return; + + // Check if transform should be interpolated + if (rigidBodyComponent->IsInterpolating()) + { + // Interpolate transforms between current and predicted next transform + + const rp3d::Transform PREV_TF = physicsObject.prevTransform; + const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast(interpolationFactor)); + + renderPos = INTERPOLATED_TF.getPosition(); + renderRot = INTERPOLATED_TF.getOrientation(); + } + + rigidBodyComponent->position = CURRENT_TF.getPosition(); + rigidBodyComponent->orientation = CURRENT_TF.getOrientation(); + } + + // Sync with colliders + if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) + { + colliderComponent->position = CURRENT_TF.getPosition(); + colliderComponent->orientation = CURRENT_TF.getOrientation(); + } + + // Set transform for rendering + if (transformComponent) + { + transformComponent->SetWorldPosition(renderPos); + transformComponent->SetWorldOrientation(renderRot); + } + } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index 4254efc7..3891ff48 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -55,7 +55,7 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] double GetFixedDT () const noexcept; + [[nodiscard]] double GetFixedUpdateRate () const noexcept; [[nodiscard]] const SHPhysicsWorldState::WorldSettings& GetWorldSettings () const noexcept; [[nodiscard]] const std::vector& GetAllCollisionInfo () const noexcept; @@ -67,8 +67,8 @@ namespace SHADE /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetFixedDT (double fixedUpdateRate) noexcept; - void SetWorldSettings (const SHPhysicsWorldState::WorldSettings& settings) noexcept; + void SetFixedUpdateRate (double fixedUpdateRate) noexcept; + void SetWorldSettings (const SHPhysicsWorldState::WorldSettings& settings) noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ @@ -77,6 +77,8 @@ namespace SHADE void Init () override; void Exit () override; + void ForceUpdate (); + // Specific Handling for Collision Shapes as they are not under the Component System void AddCollisionShape (EntityID eid, int shapeIndex); @@ -120,15 +122,9 @@ namespace SHADE /* Function Members */ /*-------------------------------------------------------------------------------*/ - static void syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept; - - static void preUpdateSyncTransform - ( - SHPhysicsObject& physicsObject - , SHTransformComponent& transformComponent - , SHRigidBodyComponent* rigidBodyComponent - , SHColliderComponent* colliderComponent - ) noexcept; + void syncRigidBodyActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept; + void syncColliderActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept; + static void syncOnPlay (EntityID eid, SHPhysicsObject& physicsObject) noexcept; }; class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine @@ -161,20 +157,6 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ void Execute(double dt) noexcept override; - - private: - /*-------------------------------------------------------------------------------*/ - /* Function Members */ - /*-------------------------------------------------------------------------------*/ - - static void postUpdateSyncTransforms - ( - SHPhysicsObject& physicsObject - , SHTransformComponent& transformComponent - , SHRigidBodyComponent* rigidBodyComponent - , SHColliderComponent* colliderComponent - , double interpolationFactor - ) noexcept; }; private: @@ -208,5 +190,24 @@ namespace SHADE SHEventHandle onPlay (SHEventPtr onPlayEvent); SHEventHandle onStop (SHEventPtr onStopEvent); + + + static void preUpdateSyncTransform + ( + SHPhysicsObject& physicsObject + , SHTransformComponent* transformComponent + , SHRigidBodyComponent* rigidBodyComponent + , SHColliderComponent* colliderComponent + ) noexcept; + + static void postUpdateSyncTransforms + ( + SHPhysicsObject& physicsObject + , SHTransformComponent* transformComponent + , SHRigidBodyComponent* rigidBodyComponent + , SHColliderComponent* colliderComponent + , double interpolationFactor + ) noexcept; + }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp index 30d29167..b142d54c 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp @@ -55,7 +55,7 @@ namespace SHADE auto phySystem = SHSystemManager::GetSystem(); if (phySystem) { - return phySystem->GetFixedDT(); + return phySystem->GetFixedUpdateRate(); } SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get fixed delta time. 0.0 returned instead."); diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp index 059202e5..a42da3a6 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp @@ -15,6 +15,7 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" #include "Editor/SHEditor.h" +#include "Scene/SHSceneManager.h" #include "Scripting/SHScriptEngine.h" namespace SHADE @@ -43,65 +44,13 @@ namespace SHADE { auto* physicsSystem = reinterpret_cast(GetSystem()); - #ifdef SHEDITOR - - auto* editor = SHSystemManager::GetSystem(); - - // Only Sync on Play. - // Otherwise, Components are only holding data until the world is built on play. - - if (editor) - { - if (editor->editorState != SHEditor::State::STOP) - { - physicsSystem->objectManager.UpdateCommands(); - - for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) - { - // Ensure a valid physics Object - if (physicsObject.rp3dBody == nullptr) - continue; - - syncOnPlay(entityID, physicsObject); - } - } - else - { - auto& rigidBodyDense = SHComponentManager::GetDense(); - auto& colliderDense = SHComponentManager::GetDense(); - - for (auto& rigidBodyComponent : rigidBodyDense) - { - const auto* TRANSFORM = SHComponentManager::GetComponent_s(rigidBodyComponent.GetEID()); - - if (TRANSFORM && TRANSFORM->HasChanged()) - { - rigidBodyComponent.position = TRANSFORM->GetWorldPosition(); - rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation(); - } - } - - for (auto& colliderComponent : colliderDense) - { - const auto* TRANSFORM = SHComponentManager::GetComponent_s(colliderComponent.GetEID()); - - if (TRANSFORM && TRANSFORM->HasChanged()) - { - colliderComponent.position = TRANSFORM->GetWorldPosition(); - colliderComponent.orientation = TRANSFORM->GetWorldOrientation(); - colliderComponent.scale = TRANSFORM->GetWorldScale(); - - colliderComponent.RecomputeCollisionShapes(); - } - } - } - } - - #else - - // Always sync Rigid Body & Collider Components with Physics Objects - // Do not check for an editor here + #ifdef SHEDITOR + // Only Sync on Play. + // Otherwise, Components are only holding data until the world is built on play. + const auto* EDITOR = SHSystemManager::GetSystem(); + if (EDITOR && EDITOR->editorState != SHEditor::State::STOP) + { physicsSystem->objectManager.UpdateCommands(); for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) @@ -110,10 +59,64 @@ namespace SHADE if (physicsObject.rp3dBody == nullptr) continue; + // Sync active states between SHADE & RP3D + syncRigidBodyActive(entityID, physicsObject); + syncColliderActive(entityID, physicsObject); + syncOnPlay(entityID, physicsObject); } + } + else + { + auto& rigidBodyDense = SHComponentManager::GetDense(); + auto& colliderDense = SHComponentManager::GetDense(); - #endif + for (auto& rigidBodyComponent : rigidBodyDense) + { + const auto* TRANSFORM = SHComponentManager::GetComponent_s(rigidBodyComponent.GetEID()); + + if (TRANSFORM && TRANSFORM->HasChanged()) + { + rigidBodyComponent.position = TRANSFORM->GetWorldPosition(); + rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation(); + } + } + + for (auto& colliderComponent : colliderDense) + { + const auto* TRANSFORM = SHComponentManager::GetComponent_s(colliderComponent.GetEID()); + + if (TRANSFORM && TRANSFORM->HasChanged()) + { + colliderComponent.position = TRANSFORM->GetWorldPosition(); + colliderComponent.orientation = TRANSFORM->GetWorldOrientation(); + colliderComponent.scale = TRANSFORM->GetWorldScale(); + + colliderComponent.RecomputeCollisionShapes(); + } + } + } + + #else + + // Always sync Rigid Body & Collider Components with Physics Objects + // Do not check for an editor here + + physicsSystem->objectManager.UpdateCommands(); + + for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) + { + // Ensure a valid physics Object + if (physicsObject.rp3dBody == nullptr) + continue; + + syncRigidBodyActive(entityID, physicsObject); + syncColliderActive(entityID, physicsObject); + + syncOnPlay(entityID, physicsObject); + } + + #endif } void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept @@ -125,18 +128,26 @@ namespace SHADE SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!"); } - fixedTimeStep = 1.0 / physicsSystem->fixedDT; + const double FIXED_DT = physicsSystem->fixedDT; accumulatedTime += dt; int count = 0; - while (accumulatedTime > fixedTimeStep) + while (accumulatedTime > FIXED_DT) { if (scriptingSystem != nullptr) scriptingSystem->ExecuteFixedUpdates(); - physicsSystem->worldState.world->update(static_cast(fixedTimeStep)); + physicsSystem->worldState.world->update(static_cast(FIXED_DT)); - accumulatedTime -= fixedTimeStep; + // Clear all forces of every body in the scene after each update + for (auto& physicsObject : physicsSystem->objectManager.physicsObjects | std::views::values) + { + auto* rp3dRigidBody = physicsObject.GetRigidBody(); + rp3dRigidBody->resetForce(); + rp3dRigidBody->resetTorque(); + } + + accumulatedTime -= FIXED_DT; ++count; } @@ -165,17 +176,14 @@ namespace SHADE auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); - if (transformComponent) - { - postUpdateSyncTransforms - ( - physicsObject - , *transformComponent - , rigidBodyComponent - , colliderComponent - , physicsSystem->interpolationFactor - ); - } + postUpdateSyncTransforms + ( + physicsObject + , transformComponent + , rigidBodyComponent + , colliderComponent + , physicsSystem->interpolationFactor + ); } // Collision & Trigger messages @@ -191,6 +199,48 @@ namespace SHADE /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ + void SHPhysicsSystem::PhysicsPreUpdate::syncRigidBodyActive(EntityID eid, SHPhysicsObject& physicsObject) const noexcept + { + if (!SHComponentManager::HasComponent(eid)) + return; + + const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive(eid); + const bool IS_RP3D_BODY_ACTIVE = physicsObject.GetRigidBody()->isActive(); + + if (IS_ACTIVE_IN_SCENE != IS_RP3D_BODY_ACTIVE) + physicsObject.GetRigidBody()->setIsActive(IS_ACTIVE_IN_SCENE); + } + + void SHPhysicsSystem::PhysicsPreUpdate::syncColliderActive(EntityID eid, SHPhysicsObject& physicsObject) const noexcept + { + const auto* COLLIDER = SHComponentManager::GetComponent_s(eid); + if (!COLLIDER) + return; + + const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive(eid); + const bool IS_RP3D_COLLIDER_ACTIVE = physicsObject.collidersActive; + + if (IS_ACTIVE_IN_SCENE != IS_RP3D_COLLIDER_ACTIVE) + { + // HACK: If active state turned off, remove all collision shapes. If turned on, add them back. + auto* physicsSystem = reinterpret_cast(GetSystem()); + + const int NUM_SHAPES = static_cast(COLLIDER->GetCollisionShapes().size()); + if (IS_ACTIVE_IN_SCENE) + { + for (int i = 0; i < NUM_SHAPES; ++i) + physicsSystem->objectManager.AddCollisionShape(eid, i); + } + else + { + for (int i = NUM_SHAPES - 1; i >= 0; --i) + physicsSystem->objectManager.RemoveCollisionShape(eid, i); + } + + physicsObject.collidersActive = IS_ACTIVE_IN_SCENE; + } + } + void SHPhysicsSystem::PhysicsPreUpdate::syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept { auto* transformComponent = SHComponentManager::GetComponent_s(eid); @@ -203,7 +253,7 @@ namespace SHADE preUpdateSyncTransform ( physicsObject - , *transformComponent + , transformComponent , rigidBodyComponent , colliderComponent ); @@ -217,99 +267,4 @@ namespace SHADE if (colliderComponent) physicsObject.SyncColliders(*colliderComponent); } - - void SHPhysicsSystem::PhysicsPreUpdate::preUpdateSyncTransform - ( - SHPhysicsObject& physicsObject - , SHTransformComponent& transformComponent - , SHRigidBodyComponent* rigidBodyComponent - , SHColliderComponent* colliderComponent - ) noexcept - { - const SHVec3& WORLD_POS = transformComponent.GetWorldPosition(); - const SHQuaternion& WORLD_ROT = transformComponent.GetWorldOrientation(); - const SHVec3& WORLD_SCL = transformComponent.GetWorldScale(); - - const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT }; - physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM); - - if (rigidBodyComponent) - { - rigidBodyComponent->position = WORLD_POS; - rigidBodyComponent->orientation = WORLD_ROT; - } - - if (colliderComponent) - { - colliderComponent->position = WORLD_POS; - colliderComponent->orientation = WORLD_ROT; - colliderComponent->scale = WORLD_SCL; - - colliderComponent->RecomputeCollisionShapes(); - } - } - - void SHPhysicsSystem::PhysicsPostUpdate::postUpdateSyncTransforms - ( - SHPhysicsObject& physicsObject - , SHTransformComponent& transformComponent - , SHRigidBodyComponent* rigidBodyComponent - , SHColliderComponent* colliderComponent - , double interpolationFactor - ) noexcept - { - rp3d::Vector3 rp3dPos; - rp3d::Quaternion rp3dRot; - - const rp3d::Transform CURRENT_TF = physicsObject.rp3dBody->getTransform(); - - // Check if transform should be interpolated - - if (rigidBodyComponent) - { - // Skip static bodies - if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC) - return; - - if (rigidBodyComponent->IsInterpolating()) - { - // Interpolate transforms between current and predicted next transform - - const rp3d::Transform PREV_TF = physicsObject.prevTransform; - const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast(interpolationFactor)); - - rp3dPos = INTERPOLATED_TF.getPosition(); - rp3dRot = INTERPOLATED_TF.getOrientation(); - } - else - { - rp3dPos = CURRENT_TF.getPosition(); - rp3dRot = CURRENT_TF.getOrientation(); - } - - rigidBodyComponent->position = CURRENT_TF.getPosition(); - rigidBodyComponent->orientation = CURRENT_TF.getOrientation(); - - if (colliderComponent) - { - // Sync with colliders - - colliderComponent->position = CURRENT_TF.getPosition(); - colliderComponent->orientation = CURRENT_TF.getOrientation(); - } - } - else - { - rp3dPos = CURRENT_TF.getPosition(); - rp3dRot = CURRENT_TF.getOrientation(); - } - - // Convert RP3D Transform to SHADE - transformComponent.SetWorldPosition(rp3dPos); - transformComponent.SetWorldOrientation(rp3dRot); - - // Cache transforms - physicsObject.prevTransform = CURRENT_TF; - } - } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index 0f8933e2..ce406c77 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -1,8 +1,8 @@ #pragma once #include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" -#include "Math/Geometry/SHBoundingBox.h" -#include "Math/Geometry/SHBoundingSphere.h" +#include "Math/Geometry/SHBox.h" +#include "Math/Geometry/SHSphere.h" #include "Physics/Interface/SHCollisionShape.h" #include "Resource/SHResourceManager.h" #include "Math/Vector/SHVec2.h" @@ -130,13 +130,13 @@ namespace YAML { case SHCollisionShape::Type::BOX: { - const auto* BOX = reinterpret_cast(rhs.GetShape()); + const auto* BOX = reinterpret_cast(rhs.GetShape()); node[HalfExtents] = BOX->GetRelativeExtents(); } break; case SHCollisionShape::Type::SPHERE: { - const auto* SPHERE = reinterpret_cast(rhs.GetShape()); + const auto* SPHERE = reinterpret_cast(rhs.GetShape()); node[Radius] = SPHERE->GetRelativeRadius(); } break; diff --git a/SHADE_Managed/src/Components/Collider.cxx b/SHADE_Managed/src/Components/Collider.cxx index 0e916b7b..1a53f9e1 100644 --- a/SHADE_Managed/src/Components/Collider.cxx +++ b/SHADE_Managed/src/Components/Collider.cxx @@ -47,35 +47,35 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ Vector3 BoxCollider::Center::get() { - return Convert::ToCLI(getNativeBoundObject().GetCenter()); + return Convert::ToCLI(getNativeBoundObject().GetCenter()); } void BoxCollider::Center::set(Vector3 value) { - getNativeBoundObject().SetCenter(Convert::ToNative(value)); + getNativeBoundObject().SetCenter(Convert::ToNative(value)); } Vector3 BoxCollider::HalfExtents::get() { - return Convert::ToCLI(getNativeBoundObject().GetWorldExtents()); + return Convert::ToCLI(getNativeBoundObject().GetWorldExtents()); } void BoxCollider::HalfExtents::set(Vector3 value) { - getNativeBoundObject().SetWorldExtents(Convert::ToNative(value)); + getNativeBoundObject().SetWorldExtents(Convert::ToNative(value)); } Vector3 BoxCollider::Min::get() { - return Convert::ToCLI(getNativeBoundObject().GetMin()); + return Convert::ToCLI(getNativeBoundObject().GetMin()); } void BoxCollider::Min::set(Vector3 value) { - getNativeBoundObject().SetMin(Convert::ToNative(value)); + getNativeBoundObject().SetMin(Convert::ToNative(value)); } Vector3 BoxCollider::Max::get() { - return Convert::ToCLI(getNativeBoundObject().GetMax()); + return Convert::ToCLI(getNativeBoundObject().GetMax()); } void BoxCollider::Max::set(Vector3 value) { - getNativeBoundObject().SetMax(Convert::ToNative(value)); + getNativeBoundObject().SetMax(Convert::ToNative(value)); } /*---------------------------------------------------------------------------------*/ @@ -83,11 +83,11 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ bool BoxCollider::TestPoint(Vector3 point) { - return getNativeBoundObject().TestPoint(Convert::ToNative(point)); + return getNativeBoundObject().TestPoint(Convert::ToNative(point)); } bool BoxCollider::Raycast(Ray ray, float maxDistance) { - return getNativeBoundObject().Raycast(Convert::ToNative(ray), maxDistance); + return getNativeBoundObject().Raycast(Convert::ToNative(ray), maxDistance); } /*---------------------------------------------------------------------------------*/ @@ -95,19 +95,19 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ Vector3 SphereCollider::Center::get() { - return Convert::ToCLI(getNativeBoundObject().GetCenter()); + return Convert::ToCLI(getNativeBoundObject().GetCenter()); } void SphereCollider::Center::set(Vector3 value) { - getNativeBoundObject().SetCenter(Convert::ToNative(value)); + getNativeBoundObject().SetCenter(Convert::ToNative(value)); } float SphereCollider::Radius::get() { - return getNativeBoundObject().GetWorldRadius(); + return getNativeBoundObject().GetWorldRadius(); } void SphereCollider::Radius::set(float value) { - getNativeBoundObject().SetWorldRadius(value); + getNativeBoundObject().SetWorldRadius(value); } /*---------------------------------------------------------------------------------*/ @@ -115,11 +115,11 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ bool SphereCollider::TestPoint(Vector3 point) { - return getNativeBoundObject().TestPoint(Convert::ToNative(point)); + return getNativeBoundObject().TestPoint(Convert::ToNative(point)); } bool SphereCollider::Raycast(Ray ray, float maxDistance) { - return getNativeBoundObject().Raycast(Convert::ToNative(ray), maxDistance); + return getNativeBoundObject().Raycast(Convert::ToNative(ray), maxDistance); } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Components/RigidBody.cxx b/SHADE_Managed/src/Components/RigidBody.cxx index 12861600..a88a2503 100644 --- a/SHADE_Managed/src/Components/RigidBody.cxx +++ b/SHADE_Managed/src/Components/RigidBody.cxx @@ -189,7 +189,11 @@ namespace SHADE { GetNativeComponent()->AddRelativeForceAtWorldPos(Convert::ToNative(relativeForce), Convert::ToNative(worldPos)); } - + + Vector3 RigidBody::GetForce() + { + return Convert::ToCLI(GetNativeComponent()->GetForce()); + } /*---------------------------------------------------------------------------------*/ /* Torque Functions */ /*---------------------------------------------------------------------------------*/ @@ -202,4 +206,10 @@ namespace SHADE { GetNativeComponent()->AddRelativeTorque(Convert::ToNative(relativeTorque)); } + + Vector3 RigidBody::GetTorque() + { + return Convert::ToCLI(GetNativeComponent()->GetTorque()); + } + } \ No newline at end of file diff --git a/SHADE_Managed/src/Components/RigidBody.hxx b/SHADE_Managed/src/Components/RigidBody.hxx index f2953bbd..50147033 100644 --- a/SHADE_Managed/src/Components/RigidBody.hxx +++ b/SHADE_Managed/src/Components/RigidBody.hxx @@ -145,11 +145,15 @@ namespace SHADE void AddRelativeForceAtLocalPos(Vector3 relativeForce, Vector3 localPos); void AddRelativeForceAtWorldPos(Vector3 relativeForce, Vector3 worldPos); + Vector3 GetForce(); + /*-----------------------------------------------------------------------------*/ /* Torque Functions */ /*-----------------------------------------------------------------------------*/ void AddTorque(Vector3 force); void AddRelativeTorque(Vector3 relativeForce); + + Vector3 GetTorque(); }; } \ No newline at end of file