diff --git a/SHADE_Application/src/Scenes/SBMainScene.cpp b/SHADE_Application/src/Scenes/SBMainScene.cpp index 6c875518..dd713980 100644 --- a/SHADE_Application/src/Scenes/SBMainScene.cpp +++ b/SHADE_Application/src/Scenes/SBMainScene.cpp @@ -11,7 +11,7 @@ #include "Scripting/SHScriptEngine.h" #include "Math/Transform/SHTransformComponent.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" -#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" #include "Physics/Interface/SHColliderComponent.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h" #include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h" diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index 9e3fa8ab..a300e6b9 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -10,7 +10,7 @@ #include "Scripting/SHScriptEngine.h" #include "Math/Transform/SHTransformComponent.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" -#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" #include "Physics/Interface/SHColliderComponent.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h" @@ -92,7 +92,7 @@ namespace Sandbox floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC); - floorCollider.AddBoundingBox(); + //floorCollider.AddBoundingBox(); // Create blank entity with a script //testObj = SHADE::SHEntityManager::CreateEntity(); @@ -113,9 +113,9 @@ namespace Sandbox racoonTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f }); racoonTransform.SetWorldPosition({ -3.0f, -2.0f, -5.0f }); - racoonCollider.AddBoundingBox(); - racoonCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f,0.5f,0.0f)); - racoonCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); + //racoonCollider.AddBoundingBox(); + //racoonCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f,0.5f,0.0f)); + //racoonCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); auto racoonItemLocation = SHEntityManager::CreateEntity(); auto& racoonItemLocationTransform = *SHComponentManager::GetComponent_s(racoonItemLocation); @@ -138,15 +138,15 @@ namespace Sandbox itemTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f }); itemTransform.SetWorldPosition({ 0.0f, -2.0f, -5.0f }); - itemCollider.AddBoundingBox(); - itemCollider.AddBoundingBox(SHVec3(2.0f,2.0f,2.0f)); - itemCollider.GetCollisionShape(1).SetIsTrigger(true); + //itemCollider.AddBoundingBox(); + //itemCollider.AddBoundingBox(SHVec3(2.0f,2.0f,2.0f)); + //itemCollider.GetCollisionShape(1).SetIsTrigger(true); - itemCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); - itemCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); + //itemCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); + //itemCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); - itemCollider.GetCollisionShape(1).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); - itemCollider.GetCollisionShape(1).SetBoundingBox(SHVec3(1.0f, 1.0f, 1.0f)); + //itemCollider.GetCollisionShape(1).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); + //itemCollider.GetCollisionShape(1).SetBoundingBox(SHVec3(1.0f, 1.0f, 1.0f)); itemRigidBody.SetInterpolate(false); itemRigidBody.SetFreezeRotationX(true); @@ -167,9 +167,9 @@ namespace Sandbox AITransform.SetWorldScale({ 2.0f, 2.0f, 2.0f }); AITransform.SetWorldPosition({ -8.0f, -2.0f, 2.5f }); - AICollider.AddBoundingBox(); - AICollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); - AICollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); + //AICollider.AddBoundingBox(); + //AICollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); + //AICollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); AIRigidBody.SetInterpolate(false); AIRigidBody.SetFreezeRotationX(true); diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 71d607f5..774697f1 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -322,37 +322,37 @@ namespace SHADE { DrawContextMenu(component); - auto& colliders = component->GetCollisionShapes(); - int const size = static_cast(colliders.size()); - ImGui::BeginChild("Collision Shapes", { 0.0f, colliders.empty() ? 1.0f : 250.0f }, true); + auto* colliders = component->GetCollisionShapes(); + int const size = colliders ? static_cast(colliders->size()) : 0; + ImGui::BeginChild("Collision Shapes", { 0.0f, colliders->empty() ? 1.0f : 250.0f }, true); std::optional colliderToDelete{ std::nullopt }; for (int i{}; i < size; ++i) { ImGui::PushID(i); - SHCollisionShape* collider = &component->GetCollisionShape(i); + SHCollisionShape* collider = component->GetCollisionShape(i); auto cursorPos = ImGui::GetCursorPos(); //collider->IsTrigger 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()); - SHEditorWidgets::DragVec3 - ( - "Half Extents", { "X", "Y", "Z" }, - [BOX] { return BOX->GetRelativeExtents(); }, - [collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); }); + //SHEditorWidgets::BeginPanel(std::format("{} Box #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); + // + //const auto* BOX = reinterpret_cast(collider->GetShape()); + //SHEditorWidgets::DragVec3 + //( + // "Half Extents", { "X", "Y", "Z" }, + // [BOX] { return BOX->GetRelativeExtents(); }, + // [collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); }); } 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()); + auto* SPHERE = reinterpret_cast(collider); SHEditorWidgets::DragFloat ( "Radius", [SPHERE] { return SPHERE->GetRelativeRadius(); }, - [collider](float const& value) { collider->SetBoundingSphere(value); }); + [SPHERE](float const& value) { SPHERE->SetRelativeRadius(value); }); } else if (collider->GetType() == SHCollisionShape::Type::CAPSULE) { @@ -393,7 +393,7 @@ namespace SHADE } if (colliderToDelete.has_value()) { - component->RemoveCollider(colliderToDelete.value()); + component->GetCollider()->RemoveCollisionShape(colliderToDelete.value()); } ImGui::EndChild(); @@ -401,11 +401,11 @@ namespace SHADE { if (ImGui::Selectable("Box Collider")) { - component->AddBoundingBox(); + //component->AddBoundingBox(); } if (ImGui::Selectable("Sphere Collider")) { - component->AddBoundingSphere(); + component->GetCollider()->AddSphereCollisionShape(1.0f); } ImGui::EndMenu(); } diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp index f0d3e3e5..83647da7 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp @@ -14,7 +14,7 @@ #include "Scripting/SHScriptEngine.h" #include "ECS_Base/Managers/SHSystemManager.h" -#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" #include "Physics/Interface/SHColliderComponent.h" #include "Camera/SHCameraComponent.h" #include "Camera/SHCameraArmComponent.h" diff --git a/SHADE_Engine/src/Math/Geometry/SHSphere.cpp b/SHADE_Engine/src/Math/Geometry/SHSphere.cpp index 54935251..7dca00c0 100644 --- a/SHADE_Engine/src/Math/Geometry/SHSphere.cpp +++ b/SHADE_Engine/src/Math/Geometry/SHSphere.cpp @@ -25,13 +25,11 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHSphere::SHSphere() noexcept - : RelativeRadius { 1.0f } { type = Type::SPHERE; } SHSphere::SHSphere(const SHVec3& center, float radius) noexcept - : RelativeRadius { 1.0f } { type = Type::SPHERE; @@ -48,7 +46,6 @@ namespace SHADE Center = rhs.Center; Radius = rhs.Radius; - RelativeRadius = rhs.RelativeRadius; } SHSphere::SHSphere(SHSphere&& rhs) noexcept @@ -57,7 +54,6 @@ namespace SHADE Center = rhs.Center; Radius = rhs.Radius; - RelativeRadius = rhs.RelativeRadius; } /*-----------------------------------------------------------------------------------*/ @@ -74,7 +70,6 @@ namespace SHADE { Center = rhs.Center; Radius = rhs.Radius; - RelativeRadius = rhs.RelativeRadius; } return *this; @@ -90,50 +85,11 @@ namespace SHADE { Center = rhs.Center; Radius = rhs.Radius; - RelativeRadius = rhs.RelativeRadius; } return *this; } - /*-----------------------------------------------------------------------------------*/ - /* Getter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHVec3 SHSphere::GetCenter() const noexcept - { - return Center; - } - - float SHSphere::GetWorldRadius() const noexcept - { - return Radius; - } - - float SHSphere::GetRelativeRadius() const noexcept - { - return RelativeRadius; - } - - /*-----------------------------------------------------------------------------------*/ - /* Setter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHSphere::SetCenter(const SHVec3& center) noexcept - { - Center = center; - } - - void SHSphere::SetWorldRadius(float newWorldRadius) noexcept - { - Radius = newWorldRadius; - } - - void SHSphere::SetRelativeRadius(float newRelativeRadius) noexcept - { - RelativeRadius = newRelativeRadius; - } - /*-----------------------------------------------------------------------------------*/ /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/Geometry/SHSphere.h b/SHADE_Engine/src/Math/Geometry/SHSphere.h index e056f21a..91771a21 100644 --- a/SHADE_Engine/src/Math/Geometry/SHSphere.h +++ b/SHADE_Engine/src/Math/Geometry/SHSphere.h @@ -23,7 +23,7 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ class SH_API SHSphere : public SHShape, - private DirectX::BoundingSphere + public DirectX::BoundingSphere { public: /*---------------------------------------------------------------------------------*/ @@ -32,8 +32,8 @@ namespace SHADE SHSphere () noexcept; SHSphere (const SHVec3& center, float radius) noexcept; - SHSphere (const SHSphere& rhs) noexcept; - SHSphere (SHSphere&& rhs) noexcept; + SHSphere (const SHSphere& rhs) noexcept; + SHSphere (SHSphere&& rhs) noexcept; ~SHSphere () override = default; @@ -44,49 +44,100 @@ namespace SHADE SHSphere& operator= (const SHSphere& rhs) noexcept; SHSphere& operator= (SHSphere&& rhs) noexcept; - /*---------------------------------------------------------------------------------*/ - /* Getter Functions */ - /*---------------------------------------------------------------------------------*/ - - [[nodiscard]] SHVec3 GetCenter () const noexcept; - [[nodiscard]] float GetWorldRadius () const noexcept; - [[nodiscard]] float GetRelativeRadius () const noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Setter Functions */ - /*---------------------------------------------------------------------------------*/ - - void SetCenter (const SHVec3& center) noexcept; - void SetWorldRadius (float newWorldRadius) noexcept; - void SetRelativeRadius (float newRelativeRadius) noexcept; - /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ + /** + * @brief + * Checks if a point is inside the sphere. + * @param point + * The point to check. + * @return + * True if the point is inside the sphere. + */ [[nodiscard]] bool TestPoint (const SHVec3& point) const noexcept override; - [[nodiscard]] SHRaycastResult Raycast(const SHRay& ray) const noexcept override; - [[nodiscard]] bool Contains (const SHSphere& rhs) const noexcept; - [[nodiscard]] float Volume () const noexcept; - [[nodiscard]] float SurfaceArea () const noexcept; + /** + * @brief + * Casts a ray against the sphere. + * @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 override; + + /** + * @brief + * Checks if an entire other sphere is contained by this sphere. + * @param rhs + * The sphere to check. + * @return + * True if the other sphere is completely contained by this sphere. + */ + [[nodiscard]] bool Contains (const SHSphere& rhs) const noexcept; + + /** + * @brief + * Calculates the volume of the sphere. + */ + [[nodiscard]] float Volume () const noexcept; + + /** + * @brief + * Calculates the surface area of the sphere. + */ + [[nodiscard]] float SurfaceArea () const noexcept; /*---------------------------------------------------------------------------------*/ /* Static Function Members */ /*---------------------------------------------------------------------------------*/ - [[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; + /** + * @brief + * Combines two spheres to form a larger sphere. + * If one sphere is completely contained by the other, the result is the larger sphere. + * @return + * The combined sphere. + */ + [[nodiscard]] static SHSphere Combine (const SHSphere& lhs, const SHSphere& rhs) noexcept; + + /** + * @brief + * Checks if two spheres are intersecting. + * @return + * True if they are intersecting. + */ + [[nodiscard]] static bool Intersect (const SHSphere& lhs, const SHSphere& rhs) noexcept; + + /** + * @brief + * Builds a single sphere from multiple spheres. + * @param spheres + * The set of spheres to build from. + * @param numSpheres + * The number of spheres in the set to build from. + * @return + * A sphere that contains all the spheres in the set. + */ + [[nodiscard]] static SHSphere BuildFromSpheres (const SHSphere* spheres, size_t numSpheres) noexcept; + + /** + * @brief + * Builds a sphere from a set of vertices. + * @param vertices + * The vertices to build a sphere 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 + * A sphere that contains all the vertices in the set. + */ [[nodiscard]] static SHSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; - - private: - /*---------------------------------------------------------------------------------*/ - /* Data Members */ - /*---------------------------------------------------------------------------------*/ - - float RelativeRadius; - }; } // namespace SHADE diff --git a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.cpp b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.cpp new file mode 100644 index 00000000..845634fe --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.cpp @@ -0,0 +1,191 @@ +/**************************************************************************************** + * \file SHCollider.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Collider. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#include + +// Primary Header +#include "SHCollisionShape.h" + +// Project Headers +#include "Physics/Collision/SHCollisionTagMatrix.h" +#include "Reflection/SHReflectionMetadata.h" +#include "Tools/Utilities/SHUtilities.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHCollisionShape::SHCollisionShape(SHCollisionShapeID id, Type colliderType) + : id { id } + , flags { 0 } + , collisionTag { SHCollisionTagMatrix::GetTag(0) } + { + flags |= 1U << SHUtilities::ConvertEnum(colliderType); + } + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + float SHCollisionShape::GetFriction() const noexcept + { + return material.GetFriction(); + } + + float SHCollisionShape::GetBounciness() const noexcept + { + return material.GetBounciness(); + } + + float SHCollisionShape::GetDensity() const noexcept + { + return material.GetDensity(); + } + + const SHPhysicsMaterial& SHCollisionShape::GetMaterial() const noexcept + { + return material; + } + + const SHVec3& SHCollisionShape::GetPositionOffset() const noexcept + { + return positionOffset; + } + + const SHVec3& SHCollisionShape::GetRotationOffset() const noexcept + { + return rotationOffset; + } + + SHCollisionShape::Type SHCollisionShape::GetType() const noexcept + { + for (int i = 0; i < SHUtilities::ConvertEnum(Type::COUNT); ++i) + { + const uint8_t FLAG_VALUE = 1U << SHUtilities::ConvertEnum(static_cast(i)); + + if (flags & FLAG_VALUE) + return static_cast(i); + } + + return Type::INVALID; + } + + bool SHCollisionShape::IsTrigger() const noexcept + { + static constexpr int FLAG_POS = 3; + static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS; + + return flags & FLAG_VALUE; + } + + bool SHCollisionShape::IsColliding() const noexcept + { + static constexpr int FLAG_POS = 4; + static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS; + + return flags & FLAG_VALUE; + } + + bool SHCollisionShape::GetDebugDrawState() const noexcept + { + static constexpr int FLAG_POS = 6; + static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS; + + return flags & FLAG_VALUE; + } + + const SHCollisionTag& SHCollisionShape::GetCollisionTag() const noexcept + { + return *collisionTag; + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHCollisionShape::SetFriction(float friction) noexcept + { + material.SetFriction(friction); + } + + void SHCollisionShape::SetBounciness(float bounciness) noexcept + { + material.SetBounciness(bounciness); + } + + void SHCollisionShape::SetDensity(float density) noexcept + { + material.SetDensity(density); + } + + void SHCollisionShape::SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept + { + material = newMaterial; + } + + void SHCollisionShape::SetPositionOffset(const SHVec3& posOffset) noexcept + { + positionOffset = posOffset; + } + + void SHCollisionShape::SetRotationOffset(const SHVec3& rotOffset) noexcept + { + rotationOffset = rotOffset; + } + + void SHCollisionShape::SetIsTrigger(bool isTrigger) noexcept + { + static constexpr int FLAG_POS = 3; + static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS; + + isTrigger ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE; + } + + void SHCollisionShape::SetDebugDrawState(bool isDebugDrawing) noexcept + { + static constexpr int FLAG_POS = 6; + static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS; + + isDebugDrawing ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE; + } + + void SHCollisionShape::SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept + { + collisionTag = newCollisionTag; + } + + /*-----------------------------------------------------------------------------------*/ + /* Private Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + +} // namespace SHADE + +RTTR_REGISTRATION +{ + using namespace SHADE; + using namespace rttr; + + registration::enumeration("Collider Type") + ( + value("Box", SHCollisionShape::Type::BOX), + value("Sphere", SHCollisionShape::Type::SPHERE) + // TODO(Diren): Add More Shapes + ); + + registration::class_("Collider") + .property("IsTrigger" , &SHCollisionShape::IsTrigger , &SHCollisionShape::SetIsTrigger ) + .property("Friction" , &SHCollisionShape::GetFriction , &SHCollisionShape::SetFriction ) + .property("Bounciness" , &SHCollisionShape::GetBounciness , &SHCollisionShape::SetBounciness ) + .property("Density" , &SHCollisionShape::GetDensity , &SHCollisionShape::SetDensity ) + .property("Position Offset" , &SHCollisionShape::GetPositionOffset, &SHCollisionShape::SetPositionOffset) + .property("Rotation Offset" , &SHCollisionShape::GetRotationOffset, &SHCollisionShape::SetRotationOffset) (metadata(META::angleInRad, true)); +} \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Interface/SHCollisionShape.h b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.h similarity index 75% rename from SHADE_Engine/src/Physics/Interface/SHCollisionShape.h rename to SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.h index 597814a6..420c0d6e 100644 --- a/SHADE_Engine/src/Physics/Interface/SHCollisionShape.h +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.h @@ -1,7 +1,7 @@ /**************************************************************************************** - * \file SHCollider.h + * \file SHCollisionShape.h * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Interface for a Collider. + * \brief Interface for a Base CollisionShape Class. * * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or * disclosure of this file or its contents without the prior written consent @@ -16,8 +16,9 @@ #include "ECS_Base/Entity/SHEntity.h" #include "Math/Geometry/SHShape.h" #include "Math/SHQuaternion.h" -#include "SHPhysicsMaterial.h" #include "Physics/Collision/SHCollisionTags.h" +#include "Physics/Collision/SHPhysicsMaterial.h" +#include "SHCollisionShapeID.h" namespace SHADE { @@ -34,7 +35,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ friend class SHColliderComponent; - friend class SHPhysicsObject; + friend class SHCollisionShapeFactory; public: /*---------------------------------------------------------------------------------*/ @@ -46,87 +47,87 @@ namespace SHADE BOX , SPHERE , CAPSULE + + , COUNT + , INVALID = -1 }; /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHCollisionShape (EntityID eid, Type colliderType = Type::BOX, const SHPhysicsMaterial& physicsMaterial = SHPhysicsMaterial::DEFAULT); + SHCollisionShape (SHCollisionShapeID id, Type colliderType = Type::BOX); - SHCollisionShape (const SHCollisionShape& rhs) noexcept; - SHCollisionShape (SHCollisionShape&& rhs) noexcept; - ~SHCollisionShape () noexcept; + SHCollisionShape (const SHCollisionShape& rhs) noexcept = default; + SHCollisionShape (SHCollisionShape&& rhs) noexcept = default; + virtual ~SHCollisionShape () noexcept = default; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ /*---------------------------------------------------------------------------------*/ - SHCollisionShape& operator=(const SHCollisionShape& rhs) noexcept; - SHCollisionShape& operator=(SHCollisionShape&& rhs) noexcept; + SHCollisionShape& operator=(const SHCollisionShape& rhs) noexcept = default; + SHCollisionShape& operator=(SHCollisionShape&& rhs) noexcept = default; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] bool HasChanged () const noexcept; - - [[nodiscard]] bool IsTrigger () const noexcept; - - [[nodiscard]] Type GetType () const noexcept; - - [[nodiscard]] const SHCollisionTag& GetCollisionTag () const noexcept; + // Material Properties + // TODO: Remove individual setters once instanced materials are supported [[nodiscard]] float GetFriction () const noexcept; [[nodiscard]] float GetBounciness () const noexcept; [[nodiscard]] float GetDensity () const noexcept; [[nodiscard]] const SHPhysicsMaterial& GetMaterial () const noexcept; + // Offsets + [[nodiscard]] const SHVec3& GetPositionOffset () const noexcept; [[nodiscard]] const SHVec3& GetRotationOffset () const noexcept; - [[nodiscard]] const SHShape* GetShape () const noexcept; + // Flags + + [[nodiscard]] Type GetType () const noexcept; + [[nodiscard]] bool IsTrigger () const noexcept; + [[nodiscard]] bool IsColliding () const noexcept; + [[nodiscard]] bool GetDebugDrawState () const noexcept; + + + [[nodiscard]] const SHCollisionTag& GetCollisionTag () const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetBoundingBox (const SHVec3& halfExtents); - void SetBoundingSphere (float radius); - - void SetIsTrigger (bool isTrigger) noexcept; - void SetCollisionTag (SHCollisionTag* newCollisionTag) noexcept; void SetFriction (float friction) noexcept; void SetBounciness (float bounciness) noexcept; void SetDensity (float density) noexcept; void SetMaterial (const SHPhysicsMaterial& newMaterial) noexcept; - void SetPositionOffset (const SHVec3& posOffset) noexcept; - void SetRotationOffset (const SHVec3& rotOffset) noexcept; + void SetPositionOffset (const SHVec3& posOffset) noexcept; + void SetRotationOffset (const SHVec3& rotOffset) noexcept; - private: + // Flags + void SetIsTrigger (bool isTrigger) noexcept; + void SetDebugDrawState (bool isDebugDrawing) noexcept; + + void SetCollisionTag (SHCollisionTag* newCollisionTag) noexcept; + + protected: /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ - Type type; - EntityID entityID; // The entity this collider belongs to - bool isTrigger; - bool dirty; + SHCollisionShapeID id; - SHShape* shape; - SHPhysicsMaterial material; + SHPhysicsMaterial material; - SHVec3 positionOffset; - SHVec3 rotationOffset; + SHVec3 positionOffset; + SHVec3 rotationOffset; - SHCollisionTag* collisionTag; - - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - - void CopyShape(const SHShape* rhs); + uint8_t flags; // 0 debugDraw wasColliding isColliding trigger capsule sphere box + SHCollisionTag* collisionTag; RTTR_ENABLE() }; diff --git a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShapeFactory.cpp b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShapeFactory.cpp new file mode 100644 index 00000000..293d5c2a --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShapeFactory.cpp @@ -0,0 +1,77 @@ +/**************************************************************************************** + * \file SHCollisionShapeFactory.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Collison Shape Factory Class. + * + * \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 "SHCollisionShapeFactory.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHCollisionShapeFactory::~SHCollisionShapeFactory() noexcept + { + // Free all shapes in each container + for (auto* sphereCollisionShape : spheres | std::views::values) + DestroyShape(sphereCollisionShape); + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Member Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHSphereCollisionShape* SHCollisionShapeFactory::CreateSphere(SHCollisionShapeID id, const SHSphereCreateInfo& createInfo) + { + const auto RESULT = spheres.emplace(id, new SHSphereCollisionShape{ id }); + if (RESULT.second) + { + SHSphereCollisionShape* sphere = RESULT.first->second; + + sphere->Center = createInfo.Center; + sphere->Radius = createInfo.Radius; + sphere->relativeRadius = createInfo.RelativeRadius; + sphere->scale = createInfo.Scale; + + return sphere; + } + + return spheres.find(id)->second; + } + + void SHCollisionShapeFactory::DestroyShape(SHCollisionShape* shape) + { + switch (shape->GetType()) + { + case SHCollisionShape::Type::BOX: + { + break; + } + case SHCollisionShape::Type::SPHERE: + { + SHSphereCollisionShape* sphere = spheres.find(shape->id)->second; + + delete sphere; + sphere = nullptr; + + spheres.erase(shape->id); + + break; + } + case SHCollisionShape::Type::CAPSULE: + { + break; + } + default: break; + } + } +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShapeFactory.h b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShapeFactory.h new file mode 100644 index 00000000..f5820317 --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShapeFactory.h @@ -0,0 +1,86 @@ +/**************************************************************************************** + * \file SHCollisionShapeFactory.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Collison Shape Factory Class. + * + * \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 Header +#include "SHSphereCollisionShape.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + /** + * @brief + * Encapsulates a class for Creating and Destroying Collision Shapes.
+ * All memory for collision shapes are handled in this factory class.
+ * TODO: Support instancing of shapes + */ + class SH_API SHCollisionShapeFactory final + { + public: + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHCollisionShapeFactory () noexcept = default; + ~SHCollisionShapeFactory () noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + /** + * @brief + * Creates a sphere collision shape. + * @param id + * The ID of the shape. + * @param createInfo + * The info to create the sphere with. + * @return + * A newly sphere collision shape. + */ + SHSphereCollisionShape* CreateSphere (SHCollisionShapeID id, const SHSphereCreateInfo& createInfo); + + /** + * @brief + * Destroys a collision shape. + * * @param eid + * The entity the shape belongs to. + * @param shapeID + * The ID of the shape. + * @param shape + * The shape to destroy. + */ + void DestroyShape (SHCollisionShape* shape); + + private: + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + + // We use unordered maps for fast lookup when deleting. + // Since we are not instancing shapes (yet?), I'd rather not iterate through an entire vector to find the shape. + + using Spheres = std::unordered_map; + + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + Spheres spheres; + // TODO: Add boxes, capsules and hulls + }; + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShapeID.h b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShapeID.h new file mode 100644 index 00000000..a0f78177 --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShapeID.h @@ -0,0 +1,101 @@ +/**************************************************************************************** + * \file SHCollisionShapeKey.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Collison Shape ID Class and it's hashing function + * + * \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 "ECS_Base/Entity/SHEntity.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-----------------------------------------------------------------------------------*/ + + struct SHCollisionShapeIDHash; + + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + /** + * @brief + * Encapsulates an identifier for a collision shape. + */ + union SHCollisionShapeID + { + private: + /*---------------------------------------------------------------------------------*/ + /* Friends */ + /*---------------------------------------------------------------------------------*/ + + friend struct SHCollisionShapeIDHash; + + public: + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHCollisionShapeID (EntityID eid, uint32_t shapeID) noexcept; + SHCollisionShapeID (const SHCollisionShapeID& rhs) noexcept; + SHCollisionShapeID (SHCollisionShapeID&& rhs) noexcept; + + ~SHCollisionShapeID () noexcept = default; + + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHCollisionShapeID& operator=(const SHCollisionShapeID& rhs) noexcept; + SHCollisionShapeID& operator=(SHCollisionShapeID&& rhs) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Member Functions */ + /*---------------------------------------------------------------------------------*/ + + bool operator==(const SHCollisionShapeID& rhs) const; + + private: + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + + struct IDs + { + public: + EntityID entityID = MAX_EID; + uint32_t shapeID = std::numeric_limits::max(); + }; + + + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + uint64_t value; + IDs ids; + }; + + /** + * @brief + * Encapsulates a functor to hash a CollisionShapeKey + */ + struct SHCollisionShapeIDHash + { + public: + /*---------------------------------------------------------------------------------*/ + /* Member Functions */ + /*---------------------------------------------------------------------------------*/ + + std::size_t operator()(const SHCollisionShapeID& id) const; + }; + +} // namespace SHADE + +#include "SHCollisionShapeID.hpp" diff --git a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShapeID.hpp b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShapeID.hpp new file mode 100644 index 00000000..234b2f6f --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShapeID.hpp @@ -0,0 +1,66 @@ +/**************************************************************************************** + * \file SHCollisionShapeKey.hpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Inlined Implementations for a Collison Shape ID Class and + * it's hashing function. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#pragma once + +// Primary Header +#include "SHCollisionShapeID.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + inline SHCollisionShapeID::SHCollisionShapeID(EntityID eid, uint32_t shapeID) noexcept + : ids { eid, shapeID } + {} + + inline SHCollisionShapeID::SHCollisionShapeID(const SHCollisionShapeID& rhs) noexcept + : ids { rhs.ids.entityID, rhs.ids.shapeID } + {} + + inline SHCollisionShapeID::SHCollisionShapeID(SHCollisionShapeID&& rhs) noexcept + : ids { rhs.ids.entityID, rhs.ids.shapeID } + {} + + + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + + inline SHCollisionShapeID& SHCollisionShapeID::operator=(const SHCollisionShapeID& rhs) noexcept + { + if (this == &rhs) + return *this; + + value = rhs.value; + + return *this; + } + + inline SHCollisionShapeID& SHCollisionShapeID::operator=(SHCollisionShapeID&& rhs) noexcept + { + value = rhs.value; + + return *this; + } + + inline bool SHCollisionShapeID::operator==(const SHCollisionShapeID& rhs) const + { + return value == rhs.value; + } + + inline std::size_t SHCollisionShapeIDHash::operator()(const SHCollisionShapeID& id) const + { + return std::hash()(id.value); + } +} diff --git a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.cpp b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.cpp new file mode 100644 index 00000000..3f79b381 --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.cpp @@ -0,0 +1,183 @@ +/**************************************************************************************** + * \file SHSphereCollisionShape.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Sphere 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 + +// Primary Header +#include "SHSphereCollisionShape.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHSphereCollisionShape::SHSphereCollisionShape(SHCollisionShapeID id) noexcept + : SHCollisionShape (id, SHCollisionShape::Type::SPHERE) + , SHSphere () + , relativeRadius { 1.0f } + , scale { 1.0f } + {} + + SHSphereCollisionShape::SHSphereCollisionShape(const SHSphereCollisionShape& rhs) noexcept + : SHCollisionShape (rhs.id, SHCollisionShape::Type::SPHERE) + , SHSphere (rhs.Center, rhs.Radius) + , relativeRadius { rhs.relativeRadius } + , scale { rhs.scale } + { + + material = rhs.material; + positionOffset = rhs.positionOffset; + rotationOffset = rhs.rotationOffset; + flags = rhs.flags; + // Since all collision tags are taken from the matrix, we do not need to do a deep copy here. + collisionTag = rhs.collisionTag; + } + + SHSphereCollisionShape::SHSphereCollisionShape(SHSphereCollisionShape&& rhs) noexcept + : SHCollisionShape (rhs.id, SHCollisionShape::Type::SPHERE) + , SHSphere (rhs.Center, rhs.Radius) + , relativeRadius { rhs.relativeRadius } + , scale { rhs.scale } + { + + material = rhs.material; + positionOffset = rhs.positionOffset; + rotationOffset = rhs.rotationOffset; + flags = rhs.flags; + // Since all collision tags are taken from the matrix, we do not need to do a deep copy here. + collisionTag = rhs.collisionTag; + } + + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHSphereCollisionShape& SHSphereCollisionShape::operator=(const SHSphereCollisionShape& rhs) noexcept + { + if (this == &rhs) + return *this; + + // Collision Shape Properties + + id = rhs.id; + material = rhs.material; + positionOffset = rhs.positionOffset; + rotationOffset = rhs.rotationOffset; + flags = rhs.flags; + // Since all collision tags are taken from the matrix, we do not need to do a deep copy here. + collisionTag = rhs.collisionTag; + + // Sphere Properties + + Center = rhs.Center; + Radius = rhs.Radius; + + // Local Properties + + relativeRadius = rhs.relativeRadius; + scale = rhs.scale; + + return *this; + } + + SHSphereCollisionShape& SHSphereCollisionShape::operator=(SHSphereCollisionShape&& rhs) noexcept + { + // Collision Shape Properties + + id = rhs.id; + material = rhs.material; + positionOffset = rhs.positionOffset; + rotationOffset = rhs.rotationOffset; + flags = rhs.flags; + // Since all collision tags are taken from the matrix, we do not need to do a deep copy here. + collisionTag = rhs.collisionTag; + + // Sphere Properties + + Center = rhs.Center; + Radius = rhs.Radius; + + // Local Properties + + relativeRadius = rhs.relativeRadius; + scale = rhs.scale; + + return *this; + } + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + const SHVec3& SHSphereCollisionShape::GetCenter() const noexcept + { + return Center; + } + + float SHSphereCollisionShape::GetWorldRadius() const noexcept + { + return Radius; + } + + float SHSphereCollisionShape::GetRelativeRadius() const noexcept + { + return relativeRadius; + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHSphereCollisionShape::SetCenter(const SHVec3& newCenter) noexcept + { + Center = newCenter; + } + + void SHSphereCollisionShape::SetWorldRadius(float newWorldRadius) noexcept + { + Radius = newWorldRadius; + + // Recompute Relative radius + relativeRadius = 2.0f * Radius / scale; + } + + void SHSphereCollisionShape::SetRelativeRadius(float newRelativeRadius) noexcept + { + relativeRadius = newRelativeRadius; + + // Recompute world radius + Radius = relativeRadius * scale * 0.5f; + } + + void SHSphereCollisionShape::SetScale(float maxScale) noexcept + { + scale = std::fabs(maxScale); + + // Recompute world radius + Radius = relativeRadius * scale * 0.5f; + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Member Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + bool SHSphereCollisionShape::TestPoint(const SHVec3& point) const noexcept + { + return SHSphere::TestPoint(point); + } + + SHRaycastResult SHSphereCollisionShape::Raycast(const SHRay& ray) const noexcept + { + return SHSphere::Raycast(ray); + } + + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h new file mode 100644 index 00000000..0a8c0321 --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h @@ -0,0 +1,123 @@ +/**************************************************************************************** + * \file SHSphereCollisionShape.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Sphere 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 "Math/Geometry/SHSphere.h" +#include "SHCollisionShape.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + /** + * @brief + * Encapsulates the information to create a sphere. + */ + struct SHSphereCreateInfo + { + public: + SHVec3 Center = SHVec3::Zero; + float Radius = 1.0f; + float RelativeRadius = 1.0f; + float Scale = 1.0f; + }; + + /** + * @brief + * Encapsulate a Sphere Collision Shape used for Physics Simulations. + */ + class SH_API SHSphereCollisionShape : public SHCollisionShape + , private SHSphere + { + private: + /*---------------------------------------------------------------------------------*/ + /* Friends */ + /*---------------------------------------------------------------------------------*/ + + friend class SHCollider; + friend class SHCompositeCollider; + friend class SHCollisionShapeFactory; + + public: + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHSphereCollisionShape (SHCollisionShapeID id) noexcept; + SHSphereCollisionShape (const SHSphereCollisionShape& rhs) noexcept; + SHSphereCollisionShape (SHSphereCollisionShape&& rhs) noexcept; + + ~SHSphereCollisionShape () override = default; + + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHSphereCollisionShape& operator= (const SHSphereCollisionShape& rhs) noexcept; + SHSphereCollisionShape& operator= (SHSphereCollisionShape&& rhs) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Getter Functions */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] const SHVec3& GetCenter () const noexcept; + [[nodiscard]] float GetWorldRadius () const noexcept; + [[nodiscard]] float GetRelativeRadius () const noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*---------------------------------------------------------------------------------*/ + + void SetCenter (const SHVec3& newCenter) noexcept; + void SetWorldRadius (float newWorldRadius) noexcept; + void SetRelativeRadius (float newRelativeRadius) noexcept; + void SetScale (float maxScale) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + /** + * @brief + * Tests if a point is inside the sphere. + * @param point + * The point to test. + * @return + * True if the point is inside the sphere. + */ + bool TestPoint (const SHVec3& point) const noexcept override; + + /** + * @brief + * Casts a ray against this sphere. + * @param ray + * The ray to cast. + * @return + * An object holding the results of the raycast.
+ * See the corresponding header for the contents of the object. + */ + SHRaycastResult Raycast (const SHRay& ray) const noexcept override; + + // TODO: Compute Moment of Inertia + + private: + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + float relativeRadius; + float scale; // Intended to be passed in by the base collider. + }; + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/SHCollider.cpp b/SHADE_Engine/src/Physics/Collision/SHCollider.cpp new file mode 100644 index 00000000..e950c4fb --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/SHCollider.cpp @@ -0,0 +1,327 @@ +/**************************************************************************************** + * \file SHCollider.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Base Collider Class. + * + * \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 "SHCollider.h" + +// Project Headers +#include "Math/SHMathHelpers.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHCollider::SHCollider(EntityID eid, const SHTransform& worldTransform) noexcept + : entityID { eid } + , shapeIDCounter { 0 } + , rigidBody { nullptr } + , shapeFactory { nullptr } + , transform { worldTransform } + {} + + SHCollider::SHCollider(const SHCollider& rhs) noexcept + : entityID { rhs.entityID } + , shapeIDCounter { rhs.shapeIDCounter } + , rigidBody { rhs.rigidBody } + , shapeFactory { rhs.shapeFactory } + , transform { rhs.transform } + { + if (!shapeFactory) + { + SHLOGV_ERROR("Shape factory is unlinked with Collider {}. Unable to add copy shapes!", entityID) + return; + } + + copyShapes(rhs); + } + + SHCollider::SHCollider(SHCollider&& rhs) noexcept + : entityID { rhs.entityID } + , shapeIDCounter { rhs.shapeIDCounter } + , rigidBody { rhs.rigidBody } + , shapeFactory { rhs.shapeFactory } + , transform { rhs.transform } + { + if (!shapeFactory) + { + SHLOGV_ERROR("Shape factory is unlinked with Collider {}. Unable to add copy shapes!", entityID) + return; + } + + copyShapes(rhs); + } + + SHCollider::~SHCollider() noexcept + { + if (!shapeFactory) + { + SHLOGV_ERROR("Shape factory is unlinked with Composite Collider {}. Unable to add destroy collider!", entityID) + return; + } + + for (auto* shape : shapes) + shapeFactory->DestroyShape(shape); + } + + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHCollider& SHCollider::operator=(const SHCollider& rhs) noexcept + { + if (this == &rhs) + return *this; + + if (!shapeFactory) + { + SHLOGV_ERROR("Shape factory is unlinked with Collider {}. Unable to add copy shapes!", entityID) + return *this; + } + + entityID = rhs.entityID; + rigidBody = rhs.rigidBody; + shapeFactory = rhs.shapeFactory; + transform = rhs.transform; + + copyShapes(rhs); + + return *this; + } + + SHCollider& SHCollider::operator=(SHCollider&& rhs) noexcept + { + if (!shapeFactory) + { + SHLOGV_ERROR("Shape factory is unlinked with Collider {}. Unable to add copy shapes!", entityID) + return *this; + } + + entityID = rhs.entityID; + rigidBody = rhs.rigidBody; + shapeFactory = rhs.shapeFactory; + transform = rhs.transform; + + copyShapes(rhs); + + return *this; + } + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + const SHTransform& SHCollider::GetTransform() const noexcept + { + return transform; + } + + const SHVec3& SHCollider::GetPosition() const noexcept + { + return transform.position; + } + + const SHQuaternion& SHCollider::GetOrientation() const noexcept + { + return transform.orientation; + } + + const SHVec3& SHCollider::GetScale() const noexcept + { + return transform.scale; + } + + const SHCollider::CollisionShapes& SHCollider::GetCollisionShapes() const noexcept + { + return shapes; + } + + SHCollisionShape* SHCollider::GetCollisionShape(int index) const + { + const int NUM_SHAPES = static_cast(shapes.size()); + + if (index < 0 || index >= NUM_SHAPES) + throw std::invalid_argument("Out-of-range index!"); + + return shapes[index]; + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHCollider::SetRigidBody(SHRigidBody* rb) noexcept + { + rigidBody = rb; + } + + void SHCollider::SetTransform(const SHTransform& newTransform) noexcept + { + transform = newTransform; + } + + void SHCollider::SetPosition(const SHVec3& newPosition) noexcept + { + transform.position = newPosition; + } + + void SHCollider::SetOrientation(const SHQuaternion& newOrientation) noexcept + { + transform.orientation = newOrientation; + } + + void SHCollider::SetScale(const SHVec3& newScale) noexcept + { + transform.scale = newScale; + } + + void SHCollider::SetFactory(SHCollisionShapeFactory* factory) noexcept + { + shapeFactory = factory; + } + + + /*-----------------------------------------------------------------------------------*/ + /* Public Member Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + const SHMatrix& SHCollider::ComputeTransformTRS() noexcept + { + return transform.ComputeTRS(); + } + + int SHCollider::AddSphereCollisionShape(float relativeRadius, const SHVec3& posOffset, const SHVec3& rotOffset) + { + if (!shapeFactory) + { + SHLOGV_ERROR("Shape factory is unlinked with Composite Collider {}. Unable to add new shape!", entityID) + return -1; + } + + // Compute world radius + const float SPHERE_SCALE = std::fabs(SHMath::Max({ transform.scale.x, transform.scale.y, transform.scale.z })); + + // Compute center + const SHQuaternion FINAL_ROT = transform.orientation * SHQuaternion::FromEuler(rotOffset); + const SHMatrix TRS = SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(transform.position); + + // Create Sphere + const SHSphereCreateInfo SPHERE_CREATE_INFO + { + .Center = SHVec3::Transform(posOffset, TRS) + , .Radius = relativeRadius * SPHERE_SCALE * 0.5f + , .RelativeRadius = relativeRadius + , .Scale = SPHERE_SCALE + }; + + const SHCollisionShapeID NEW_SHAPE_ID{ entityID, shapeIDCounter }; + + SHSphereCollisionShape* sphere = shapeFactory->CreateSphere(NEW_SHAPE_ID, SPHERE_CREATE_INFO); + ++shapeIDCounter; + + // Set offsets + sphere->positionOffset = posOffset; + sphere->rotationOffset = rotOffset; + + shapes.emplace_back(sphere); + return static_cast(shapes.size()); + } + + void SHCollider::RemoveCollisionShape(int index) + { + if (!shapeFactory) + { + SHLOGV_ERROR("Shape factory is unlinked with Composite Collider {}. Unable to add remove shape!", entityID) + return; + } + + const int NUM_SHAPES = static_cast(shapes.size()); + + if (index < 0 || index >= NUM_SHAPES) + throw std::invalid_argument("Out-of-range index!"); + + auto shapeIter = shapes.begin(); + for (int i = 0; i < NUM_SHAPES; ++i, ++shapeIter) + { + if (i == index) + break; + } + + shapeFactory->DestroyShape(*shapeIter); + *shapeIter = nullptr; + + // Remove the shape from the container to prevent accessing a nullptr + shapeIter = shapes.erase(shapeIter); + + SHLOG_INFO_D("Removing Collision Shape {} from Entity {}", index, entityID) + } + + void SHCollider::RecomputeShapes() const noexcept + { + + } + + /*-----------------------------------------------------------------------------------*/ + /* Private Member Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHCollider::copyShapes(const SHCollider& rhsCollider) + { + shapeIDCounter = 0; + for (const auto* shape : rhsCollider.shapes) + { + copyShape(shape); + ++shapeIDCounter; + } + } + + void SHCollider::copyShape(const SHCollisionShape* rhsShape) + { + switch (rhsShape->GetType()) + { + case SHCollisionShape::Type::BOX: + { + break; + } + case SHCollisionShape::Type::SPHERE: + { + const SHSphereCollisionShape* RHS_SPHERE = dynamic_cast(rhsShape); + + const SHSphereCreateInfo SPHERE_CREATE_INFO + { + .Center = RHS_SPHERE->Center + , .Radius = RHS_SPHERE->Radius + , .RelativeRadius = RHS_SPHERE->relativeRadius + , .Scale = RHS_SPHERE->scale + }; + + const SHCollisionShapeID NEW_SHAPE_ID{ entityID, shapeIDCounter }; + + SHSphereCollisionShape* sphere = shapeFactory->CreateSphere(NEW_SHAPE_ID, SPHERE_CREATE_INFO); + *sphere = *RHS_SPHERE; + + shapes.emplace_back(sphere); + + break; + } + case SHCollisionShape::Type::CAPSULE: + { + break; + } + default: break; + } + + ++shapeIDCounter; + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/SHCollider.h b/SHADE_Engine/src/Physics/Collision/SHCollider.h new file mode 100644 index 00000000..37d96caa --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/SHCollider.h @@ -0,0 +1,170 @@ +/**************************************************************************************** + * \file SHCollider.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Base Collider Class. + * + * \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 "ECS_Base/Entity/SHEntity.h" +#include "Math/Transform/SHTransform.h" +#include "Physics/Collision/CollisionShapes/SHCollisionShapeFactory.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-----------------------------------------------------------------------------------*/ + + class SHRigidBody; + + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + /** + * @brief + * Base class for a collider. + * There are only two collider types supported by SHADE Engine: Composite & Hull + */ + class SH_API SHCollider + { + private: + /*---------------------------------------------------------------------------------*/ + /* Friends */ + /*---------------------------------------------------------------------------------*/ + + friend class SHPhysicsWorld; + + public: + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + + using CollisionShapes = std::vector; + + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + /** + * @brief + * Constructor for a collider. + * @param eid + * The entity this collider belongs to. + * @param worldTransform + * The world transform for the collider. Defaults to the identity transform. + * This is particularly important for composite colliders for offsets & relative sizes. + * @return + */ + SHCollider (EntityID eid, const SHTransform& worldTransform = SHTransform::Identity) noexcept; + SHCollider (const SHCollider& rhs) noexcept; + SHCollider (SHCollider&& rhs) noexcept; + ~SHCollider () noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHCollider& operator=(const SHCollider& rhs) noexcept; + SHCollider& operator=(SHCollider&& rhs) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Getter Functions */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] const SHTransform& GetTransform () const noexcept; + [[nodiscard]] const SHVec3& GetPosition () const noexcept; + [[nodiscard]] const SHQuaternion& GetOrientation () const noexcept; + [[nodiscard]] const SHVec3& GetScale () const noexcept; + + [[nodiscard]] const CollisionShapes& GetCollisionShapes () const noexcept; + [[nodiscard]] SHCollisionShape* GetCollisionShape (int index) const; + + /*---------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*---------------------------------------------------------------------------------*/ + + void SetRigidBody (SHRigidBody* rb) noexcept; + + void SetTransform (const SHTransform& newTransform) noexcept; + void SetPosition (const SHVec3& newPosition) noexcept; + void SetOrientation (const SHQuaternion& newOrientation) noexcept; + void SetScale (const SHVec3& newScale) noexcept; + + void SetFactory (SHCollisionShapeFactory* factory) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Member Functions */ + /*---------------------------------------------------------------------------------*/ + + /** + * @brief + * Computes the TRS for the collider's transform + * @return + * The computed TRS. + */ + const SHMatrix& ComputeTransformTRS() noexcept; + + /** + * @brief + * Adds a sphere collision shape. + * @param posOffset + * The position offset of the sphere from the center of the collider. Defaults to a Zero Vector. + * @param rotOffset + * The rotation offset of the sphere from the rotation of the collider. Defaults to a Zero Vector. + * @param relativeRadius + * The relative radius is constructed with respect to the world scale.
+ * Radius = max(scale.x, scale.y, scale.z) * 0.5 * relativeRadius + * @return + * The index of the newly added shape. + */ + int AddSphereCollisionShape (float relativeRadius, const SHVec3& posOffset = SHVec3::Zero, const SHVec3& rotOffset = SHVec3::Zero); + // TODO: Add Box & Capsule + + /** + * @brief + * Removes a shape from the container. Removal reduces the size of the container. + * If removing all, perform removal from back to front. + * @param index + * The index of the shape to remove. + * @throws + * Invalid argument for out-of-range indices. + */ + void RemoveCollisionShape (int index); + + /** + * @brief + * Recomputes the transforms for all shapes in this composite collider. + */ + void RecomputeShapes () const noexcept; + + protected: + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + EntityID entityID; + uint32_t shapeIDCounter; // This increments everytime a shape is added to differentiate shapes. + + SHRigidBody* rigidBody; + SHCollisionShapeFactory* shapeFactory; + + SHTransform transform; + + CollisionShapes shapes; + + /*---------------------------------------------------------------------------------*/ + /* Member Functions */ + /*---------------------------------------------------------------------------------*/ + + void copyShapes (const SHCollider& rhsCollider); + void copyShape (const SHCollisionShape* rhsShape); + }; + +} // namespace SHADE diff --git a/SHADE_Engine/src/Physics/Collision/SHCollisionInfo.cpp b/SHADE_Engine/src/Physics/Collision/SHCollisionInfo.cpp index 43ad05ca..a28686e0 100644 --- a/SHADE_Engine/src/Physics/Collision/SHCollisionInfo.cpp +++ b/SHADE_Engine/src/Physics/Collision/SHCollisionInfo.cpp @@ -13,6 +13,11 @@ // Primary Header #include "SHCollisionInfo.h" +// Project Headers +#include "Physics/Collision/SHCollider.h" +#include "Physics/Interface/SHColliderComponent.h" + + namespace SHADE { /*-----------------------------------------------------------------------------------*/ @@ -77,12 +82,14 @@ namespace SHADE const SHCollisionShape* SHCollisionInfo::GetColliderA() const noexcept { - return &SHComponentManager::GetComponent(ids[ENTITY_A])->GetCollisionShape(ids[COLLIDER_A]); + const auto* COLLIDER_COMPONENT = SHComponentManager::GetComponent(ids[ENTITY_A]); + return COLLIDER_COMPONENT->GetCollider()->GetCollisionShape(ids[COLLIDER_A]); } const SHCollisionShape* SHCollisionInfo::GetColliderB() const noexcept { - return &SHComponentManager::GetComponent(ids[ENTITY_B])->GetCollisionShape(ids[COLLIDER_B]); + const auto* COLLIDER_COMPONENT = SHComponentManager::GetComponent(ids[ENTITY_B]); + return COLLIDER_COMPONENT->GetCollider()->GetCollisionShape(ids[COLLIDER_B]); } SHCollisionInfo::State SHCollisionInfo::GetCollisionState() const noexcept diff --git a/SHADE_Engine/src/Physics/Collision/SHCollisionInfo.h b/SHADE_Engine/src/Physics/Collision/SHCollisionInfo.h index dfcf4f22..d2dad647 100644 --- a/SHADE_Engine/src/Physics/Collision/SHCollisionInfo.h +++ b/SHADE_Engine/src/Physics/Collision/SHCollisionInfo.h @@ -12,7 +12,7 @@ // Project Headers #include "Physics/Interface/SHColliderComponent.h" -#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" namespace SHADE diff --git a/SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.cpp b/SHADE_Engine/src/Physics/Collision/SHPhysicsMaterial.cpp similarity index 100% rename from SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.cpp rename to SHADE_Engine/src/Physics/Collision/SHPhysicsMaterial.cpp diff --git a/SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.h b/SHADE_Engine/src/Physics/Collision/SHPhysicsMaterial.h similarity index 100% rename from SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.h rename to SHADE_Engine/src/Physics/Collision/SHPhysicsMaterial.h diff --git a/SHADE_Engine/src/Physics/Dynamics/SHMotionState.cpp b/SHADE_Engine/src/Physics/Dynamics/SHMotionState.cpp index 2cca1c45..91b5a688 100644 --- a/SHADE_Engine/src/Physics/Dynamics/SHMotionState.cpp +++ b/SHADE_Engine/src/Physics/Dynamics/SHMotionState.cpp @@ -74,7 +74,7 @@ namespace SHADE void SHMotionState::ForcePosition(const SHVec3& newPosition) noexcept { - hasMoved = false; + hasMoved = true; prevPosition = newPosition; position = newPosition; diff --git a/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.cpp b/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.cpp index 7d6c7c5c..0d7434f6 100644 --- a/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.cpp +++ b/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.cpp @@ -40,7 +40,7 @@ namespace SHADE void SHPhysicsWorld::AddRigidBody(SHRigidBody* rigidBody) noexcept { - const bool INSERTED = rigidBodies.emplace(rigidBody->entityID, rigidBody).second; + const bool INSERTED = rigidBodies.emplace(rigidBody).second; if (!INSERTED) { SHLOG_WARNING_D("Attempting to add duplicate rigid body {} to the Physics World!", rigidBody->entityID) @@ -49,15 +49,34 @@ namespace SHADE void SHPhysicsWorld::RemoveRigidBody(SHRigidBody* rigidBody) noexcept { - rigidBodies.erase(rigidBody->entityID); + rigidBodies.erase(rigidBody); + + // Run through the rigid body's contact graph and wake all of its non-static bodies that are asleep + } + + void SHPhysicsWorld::AddCollider(SHCollider* collider) noexcept + { + const bool INSERTED = colliders.emplace(collider).second; + if (!INSERTED) + { + SHLOG_WARNING_D("Attempting to add duplicate collider {} to the Physics World!", collider->entityID) + } + } + + void SHPhysicsWorld::RemoveCollider(SHCollider* collider) noexcept + { + colliders.erase(collider); + + // Get collider's rigid body + // Run through the rigid body's contact graph and wake all of its non-static bodies that are asleep } void SHPhysicsWorld::Step(float dt) { - for (auto* rigidBody : rigidBodies | std::views::values) + for (auto* rigidBody : rigidBodies) integrateForces(*rigidBody, dt); - for (auto* rigidBody : rigidBodies | std::views::values) + for (auto* rigidBody : rigidBodies) integrateVelocities(*rigidBody, dt); } diff --git a/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.h b/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.h index eb96a021..499230dd 100644 --- a/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.h +++ b/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.h @@ -10,12 +10,12 @@ #pragma once -#include +#include // Project Headers +#include "Physics/Collision/SHCollider.h" #include "SHRigidBody.h" -#include "Math/SHMath.h" -#include "SH_API.h" + namespace SHADE { @@ -66,8 +66,11 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - void AddRigidBody (SHRigidBody* rigidBody) noexcept; - void RemoveRigidBody (SHRigidBody* rigidBody) noexcept; + void AddRigidBody (SHRigidBody* rigidBody) noexcept; + void RemoveRigidBody (SHRigidBody* rigidBody) noexcept; + + void AddCollider (SHCollider* collider) noexcept; + void RemoveCollider (SHCollider* collider) noexcept; void Step (float dt); @@ -76,7 +79,11 @@ namespace SHADE /* Type Definitions */ /*---------------------------------------------------------------------------------*/ - using RigidBodies = std::unordered_map; + //! I realise using a set may be dangerous with pointers. An unordered_map may be better, but I don't need the entityIDs so... + + using Colliders = std::unordered_set; + using RigidBodies = std::unordered_set; + /*---------------------------------------------------------------------------------*/ /* Data Members */ @@ -84,6 +91,7 @@ namespace SHADE WorldSettings settings; + Colliders colliders; RigidBodies rigidBodies; /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Dynamics/SHRigidBody.cpp b/SHADE_Engine/src/Physics/Dynamics/SHRigidBody.cpp index 8f99a8f5..e79a8c91 100644 --- a/SHADE_Engine/src/Physics/Dynamics/SHRigidBody.cpp +++ b/SHADE_Engine/src/Physics/Dynamics/SHRigidBody.cpp @@ -14,6 +14,7 @@ #include "SHRigidBody.h" // Project Headers +#include "Physics/Collision/SHCollider.h" #include "Tools/Logger/SHLogger.h" namespace SHADE @@ -24,6 +25,7 @@ namespace SHADE SHRigidBody::SHRigidBody(EntityID eid, Type type) noexcept : entityID { eid } + , collider { nullptr } , bodyType { type } , invMass { type == Type::DYNAMIC ? 1.0f : 0.0f } , linearDrag { 0.01f } @@ -40,6 +42,7 @@ namespace SHADE SHRigidBody::SHRigidBody(const SHRigidBody& rhs) noexcept : entityID { rhs.entityID } + , collider { nullptr } , bodyType { rhs.bodyType } , invMass { rhs.invMass } , linearDrag { rhs.linearDrag } @@ -52,6 +55,7 @@ namespace SHADE SHRigidBody::SHRigidBody(SHRigidBody&& rhs) noexcept : entityID { rhs.entityID } + , collider { nullptr } , bodyType { rhs.bodyType } , invMass { rhs.invMass } , linearDrag { rhs.linearDrag } @@ -73,6 +77,8 @@ namespace SHADE return *this; entityID = rhs.entityID; + // Deep copy the collider + *collider = *rhs.collider; bodyType = rhs.bodyType; invMass = rhs.invMass; linearDrag = rhs.linearDrag; @@ -91,6 +97,8 @@ namespace SHADE SHRigidBody& SHRigidBody::operator=(SHRigidBody&& rhs) noexcept { entityID = rhs.entityID; + // Deep copy the collider + *collider = *rhs.collider; bodyType = rhs.bodyType; invMass = rhs.invMass; linearDrag = rhs.linearDrag; @@ -223,6 +231,11 @@ namespace SHADE /* Setter Functions Definitions */ /*-----------------------------------------------------------------------------------*/ + void SHRigidBody::SetCollider(SHCollider* c) noexcept + { + collider = c; + } + void SHRigidBody::SetType(Type newType) noexcept { if (newType == bodyType) diff --git a/SHADE_Engine/src/Physics/Dynamics/SHRigidBody.h b/SHADE_Engine/src/Physics/Dynamics/SHRigidBody.h index dbf2344f..1edf5cf6 100644 --- a/SHADE_Engine/src/Physics/Dynamics/SHRigidBody.h +++ b/SHADE_Engine/src/Physics/Dynamics/SHRigidBody.h @@ -11,12 +11,18 @@ #pragma once // Project Headers -#include "ECS_Base/SHECSMacros.h" +#include "ECS_Base/Entity/SHEntity.h" #include "Math/Vector/SHVec3.h" #include "SHMotionState.h" namespace SHADE { + /*-------------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-------------------------------------------------------------------------------------*/ + + class SHCollider; + /*-------------------------------------------------------------------------------------*/ /* Type Definitions */ /*-------------------------------------------------------------------------------------*/ @@ -96,6 +102,8 @@ namespace SHADE /* Setter Functions */ /*-----------------------------------------------------------------------------------*/ + void SetCollider (SHCollider* c) noexcept; + /** * @brief * Changing the type from non-Dynamic to Dynamic will set the default @@ -174,6 +182,7 @@ namespace SHADE // The entityID here is only meant for linking with the actual component in the engine. EntityID entityID; + SHCollider* collider; Type bodyType; @@ -187,7 +196,7 @@ namespace SHADE SHVec3 linearVelocity; SHVec3 angularVelocity; - // aZ aY aX pZ pY pX 0 0 0 0 0 autoMass enableGravity enableSleeping sleeping active + // aZ aY aX pZ pY pX 0 0 0 0 inIsland autoMass enableGravity enableSleeping sleeping active uint16_t flags; SHMotionState motionState; diff --git a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.cpp index b6e5ac40..ee33016a 100644 --- a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.cpp @@ -26,15 +26,13 @@ namespace SHADE SHPhysicsObject::SHPhysicsObject(const SHPhysicsObject& rhs) noexcept : entityID { rhs.entityID } { - // Perform a deep copy of the components - *rigidBody = *rhs.rigidBody; + deepCopyComponents(rhs.rigidBody, rhs.collider); } SHPhysicsObject::SHPhysicsObject(SHPhysicsObject&& rhs) noexcept : entityID { rhs.entityID } { - // Perform a deep copy of the components - *rigidBody = *rhs.rigidBody; + deepCopyComponents(rhs.rigidBody, rhs.collider); } SHPhysicsObject::~SHPhysicsObject() noexcept @@ -42,6 +40,10 @@ namespace SHADE entityID = MAX_EID; delete rigidBody; + rigidBody = nullptr; + + delete collider; + collider = nullptr; } /*-----------------------------------------------------------------------------------*/ @@ -53,20 +55,18 @@ namespace SHADE if (this == &rhs) return *this; - entityID = rhs.entityID; + entityID = rhs.entityID; - // Perform a deep copy of the components - *rigidBody = *rhs.rigidBody; + deepCopyComponents(rhs.rigidBody, rhs.collider); return *this; } SHPhysicsObject& SHPhysicsObject::operator=(SHPhysicsObject&& rhs) noexcept { - entityID = rhs.entityID; + entityID = rhs.entityID; - // Perform a deep copy of the components - *rigidBody = *rhs.rigidBody; + deepCopyComponents(rhs.rigidBody, rhs.collider); return *this; } @@ -77,7 +77,74 @@ namespace SHADE bool SHPhysicsObject::IsEmpty() const noexcept { - return rigidBody == nullptr; + return rigidBody == nullptr && collider == nullptr; + } + + SHRigidBody* SHPhysicsObject::CreateRigidBody(SHRigidBody::Type bodyType) + { + if (rigidBody) + { + SHLOG_INFO_D("Rigid body for Entity {} has already been created!", entityID) + return rigidBody; + } + + rigidBody = new SHRigidBody{ entityID, bodyType }; + + // Link with collider if it exists + if (collider) + collider->SetRigidBody(rigidBody); + + return rigidBody; + } + + void SHPhysicsObject::DestroyRigidBody() noexcept + { + delete rigidBody; + rigidBody = nullptr; + + // Unlink with collider + if (collider) + collider->SetRigidBody(nullptr); + } + + SHCollider* SHPhysicsObject::CreateCollider(const SHTransform& transform) + { + if (collider) + { + SHLOG_INFO_D("Collider for Entity {} has already been created!", entityID) + return collider; + } + + collider = new SHCollider{ entityID, transform }; + + // Link with rigidBody if it exists + if (rigidBody) + rigidBody->SetCollider(collider); + + return collider; + } + + void SHPhysicsObject::DestroyCollider() noexcept + { + delete collider; + collider = nullptr; + + // Unlink with rigid body + if (rigidBody) + rigidBody->SetCollider(nullptr); + } + + /*-----------------------------------------------------------------------------------*/ + /* Private Member Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsObject::deepCopyComponents(const SHRigidBody* rhsRigidBody, const SHCollider* rhsCollider) + { + if (rhsRigidBody) + rigidBody = new SHRigidBody{ *rhsRigidBody }; + + if (rhsCollider) + collider = new SHCollider { *rhsCollider }; } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.h b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.h index f297a6fb..2550543b 100644 --- a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.h +++ b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.h @@ -11,6 +11,7 @@ #pragma once // Project Headers +#include "Physics/Collision/SHCollider.h" #include "Physics/Dynamics/SHRigidBody.h" namespace SHADE @@ -32,6 +33,7 @@ namespace SHADE EntityID entityID = MAX_EID; SHRigidBody* rigidBody = nullptr; + SHCollider* collider = nullptr; /*-----------------------------------------------------------------------------------*/ /* Constructors & Destructor */ @@ -53,6 +55,55 @@ namespace SHADE /* Member Functions */ /*-----------------------------------------------------------------------------------*/ - bool IsEmpty() const noexcept; + /** + * @brief + * Checks if the physics object has a rigid body or a collider. + * @return + * True if the physics object has neither a rigid body nor a collider. + */ + [[nodiscard]] bool IsEmpty () const noexcept; + + /** + * @brief + * Creates a rigid body for this physics object. + * @param bodyType + * The rigid body's type. Can be modified after creation. + * @return + * Pointer to the rigid body that was created. The memory of this rigid body is managed + * by the physics object itself. + */ + SHRigidBody* CreateRigidBody (SHRigidBody::Type bodyType); + + /** + * @brief + * Destroys the rigid body of this physics object and frees the memory. + */ + void DestroyRigidBody () noexcept; + + /** + * @brief + * Creates a collider for this physics object. + * @param colliderType + * The collider's type. Should not be modified after creation. + * @param transform. + * The world transform of the collider. Defaults to the identity transform. + * @return + * Pointer to the collider that was created. The memory of this collider is managed + * by the physics object itself. + */ + SHCollider* CreateCollider (const SHTransform& transform = SHTransform::Identity); + + /** + * @brief + * Destroys the collider of this physics object and frees the memory. + */ + void DestroyCollider () noexcept; + + private: + /*-----------------------------------------------------------------------------------*/ + /* Member Functions */ + /*-----------------------------------------------------------------------------------*/ + + void deepCopyComponents(const SHRigidBody* rhsRigidBody, const SHCollider* rhsCollider); }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp index e6e92ba5..61a77f28 100644 --- a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp +++ b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp @@ -16,8 +16,7 @@ // Project Headers #include "Math/Transform/SHTransformComponent.h" #include "Physics/Interface/SHColliderComponent.h" -#include "Physics/Interface/SHCollisionShape.h" -#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" #include "Tools/Utilities/SHUtilities.h" namespace SHADE @@ -58,66 +57,68 @@ namespace SHADE void SHPhysicsObjectManager::AddRigidBody(EntityID entityID) noexcept { - SHPhysicsObject* physicsObject = nullptr; - - const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID); - if (PHYSICS_OBJECT_ITERATOR == physicsObjects.end()) - physicsObject = createPhysicsObject(entityID); - else - physicsObject = &PHYSICS_OBJECT_ITERATOR->second; + SHPhysicsObject* physicsObject = ensurePhysicsObject(entityID); // Get the component auto* rigidBodyComponent = SHComponentManager::GetComponent(entityID); // Create a new rigidbody in the physics object - // We assume none has already been made + const auto RIGID_BODY_TYPE = static_cast(rigidBodyComponent->GetType()); + auto* rigidBody = physicsObject->CreateRigidBody(RIGID_BODY_TYPE); - physicsObject->rigidBody = new SHRigidBody + SHVec3 worldPos = SHVec3::Zero; + // TODO: Force orientation + + if (const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent_s(entityID); TRANSFORM_COMPONENT) { - entityID - , static_cast(rigidBodyComponent->GetType()) - }; - - SHMotionState& motionState = physicsObject->rigidBody->GetMotionState(); - - if (const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent(entityID); TRANSFORM_COMPONENT) - { - motionState.ForcePosition(TRANSFORM_COMPONENT->GetWorldPosition()); - } - else - { - motionState.ForcePosition(SHVec3::Zero); + worldPos = TRANSFORM_COMPONENT->GetWorldPosition(); } + SHMotionState& motionState = rigidBody->GetMotionState(); + motionState.ForcePosition(worldPos); + // Link with the component - rigidBodyComponent->SetRigidBody(physicsObject->rigidBody); - - // TODO: Broadcast event + rigidBodyComponent->SetRigidBody(rigidBody); } void SHPhysicsObjectManager::RemoveRigidBody(EntityID entityID) noexcept { const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID); - if (PHYSICS_OBJECT_ITERATOR != physicsObjects.end()) - { - SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second; + if (PHYSICS_OBJECT_ITERATOR == physicsObjects.end()) + return; - delete physicsObject->rigidBody; - physicsObject->rigidBody = nullptr; + SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second; - // Destroy empty physics objects - if (physicsObject->IsEmpty()) - destroyPhysicsObject(entityID); - } + physicsObject->DestroyRigidBody(); - // TODO: Broadcast event + // Destroy empty physics objects + if (physicsObject->IsEmpty()) + destroyPhysicsObject(entityID); } void SHPhysicsObjectManager::AddCollider(EntityID entityID) noexcept { - // Link with the component + SHPhysicsObject* physicsObject = ensurePhysicsObject(entityID); - // TODO: Broadcast event + // Get the component + auto* colliderComponent = SHComponentManager::GetComponent(entityID); + + SHTransform worldTransform = SHTransform::Identity; + if (const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent_s(entityID); TRANSFORM_COMPONENT) + { + worldTransform.position = TRANSFORM_COMPONENT->GetWorldPosition(); + worldTransform.orientation = TRANSFORM_COMPONENT->GetWorldOrientation(); + worldTransform.scale = TRANSFORM_COMPONENT->GetWorldScale(); + + worldTransform.ComputeTRS(); + } + + // Create a new composite collider in the physics object + physicsObject->CreateCollider(worldTransform); + physicsObject->collider->SetFactory(&shapeFactory); + + // Link with the component + colliderComponent->SetCollider(physicsObject->collider); } void SHPhysicsObjectManager::RemoveCollider(EntityID entityID) noexcept @@ -127,30 +128,17 @@ namespace SHADE { SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second; + physicsObject->DestroyCollider(); + // Destroy empty physics objects if (physicsObject->IsEmpty()) destroyPhysicsObject(entityID); } - - // TODO: Broadcast event - } - - void SHPhysicsObjectManager::AddCollisionShape(EntityID entityID, uint8_t shapeID) noexcept - { - // Link with the component - - // TODO: Broadcast event - } - - void SHPhysicsObjectManager::RemoveCollisionShape(EntityID entityID, uint8_t shapeID) noexcept - { - // Unlink with the component - - // TODO: Broadcast event } void SHPhysicsObjectManager::RemoveAllObjects() noexcept { + // Physics objects itself will delete the object physicsObjects.clear(); } @@ -164,6 +152,18 @@ namespace SHADE return &NEW_OBJECT->second; } + SHPhysicsObject* SHPhysicsObjectManager::ensurePhysicsObject(EntityID entityID) + { + const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID); + + SHPhysicsObject* physicsObject = PHYSICS_OBJECT_ITERATOR == physicsObjects.end() + ? createPhysicsObject(entityID) + : &PHYSICS_OBJECT_ITERATOR->second; + + return physicsObject; + } + + void SHPhysicsObjectManager::destroyPhysicsObject(EntityID entityID) { physicsObjects.erase(entityID); diff --git a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h index 6449a2d8..ca260a02 100644 --- a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h +++ b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h @@ -14,6 +14,7 @@ // Project Headers #include "SHPhysicsObject.h" +#include "Physics/Collision/CollisionShapes/SHCollisionShapeFactory.h" namespace SHADE { @@ -26,7 +27,7 @@ namespace SHADE * Encapsulates a manager for physics objects that links raw physics components with the * engine's components. */ - class SHPhysicsObjectManager + class SH_API SHPhysicsObjectManager { private: /*-----------------------------------------------------------------------------------*/ @@ -60,7 +61,7 @@ namespace SHADE * @param entityID * The entity to link the new rigid body to. */ - void AddRigidBody (EntityID entityID) noexcept; + void AddRigidBody (EntityID entityID) noexcept; /** * @brief @@ -68,66 +69,48 @@ namespace SHADE * @param entityID * The entity to destroy the rigid body of. */ - void RemoveRigidBody (EntityID entityID) noexcept; + void RemoveRigidBody (EntityID entityID) noexcept; /** * @brief - * Creates a collider and links it with the collider component. + * Creates a composite collider and links it with the collider component. * @param entityID * The entity to link the new collider to. */ - void AddCollider (EntityID entityID) noexcept; + void AddCollider (EntityID entityID) noexcept; /** * @brief - * Destroys a collider and removes the link with the collider component. + * Destroys a composite collider and removes the link with the collider component. * @param entityID * The entity to destroy the collider of. */ - void RemoveCollider (EntityID entityID) noexcept; - - /** - * @brief - * Creates a collision shape for composite colliders and links it with the - * collider component. - * @param eientityIDd - * The entity to create a collision shape for. - * @param shapeID - * The id of the shape being created. - */ - void AddCollisionShape (EntityID entityID, uint8_t shapeID) noexcept; - - /** - * @brief - * Destroys a collision shape for composite colliders and removes the link with the - * collider component. - * @param entityID - * The entity to destroy the collision shape of. - * @param shapeID - * The id of the shape being destroyed. - */ - void RemoveCollisionShape (EntityID entityID, uint8_t shapeID) noexcept; + void RemoveCollider (EntityID entityID) noexcept; /** * @brief * Removes all physics object in the manager. This is only meant to be called when * the world is being destroyed or the scene is being changed. */ - void RemoveAllObjects () noexcept; + void RemoveAllObjects () noexcept; private: /*-----------------------------------------------------------------------------------*/ /* Data Members */ /*-----------------------------------------------------------------------------------*/ - EntityObjectMap physicsObjects; + EntityObjectMap physicsObjects; + SHCollisionShapeFactory shapeFactory; /*-----------------------------------------------------------------------------------*/ /* Member Functions */ /*-----------------------------------------------------------------------------------*/ SHPhysicsObject* createPhysicsObject (EntityID entityID); + SHPhysicsObject* ensurePhysicsObject (EntityID entityID); void destroyPhysicsObject (EntityID entityID); + + }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp index eef92493..d345290c 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp @@ -25,57 +25,43 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHColliderComponent::SHColliderComponent() noexcept + : collider { nullptr } {} /*-----------------------------------------------------------------------------------*/ /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - const SHColliderComponent::CollisionShapes& SHColliderComponent::GetCollisionShapes() const noexcept + SHCollider* const SHColliderComponent::GetCollider() const noexcept { - return collisionShapes; + return collider; } - SHCollisionShape& SHColliderComponent::GetCollisionShape(int index) + const SHCollider::CollisionShapes* const SHColliderComponent::GetCollisionShapes() const noexcept { - if (index < 0 || static_cast(index) >= collisionShapes.size()) - throw std::invalid_argument("Out-of-range access!"); + if (!collider) + return nullptr; - return collisionShapes[index]; + return &collider->GetCollisionShapes(); } + + SHCollisionShape* const SHColliderComponent::GetCollisionShape(int index) const + { + if (!collider) + return nullptr; + + return collider->GetCollisionShape(index); + } + + /*-----------------------------------------------------------------------------------*/ - /* Public Function Member Definitions */ + /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHColliderComponent::OnCreate() + void SHColliderComponent::SetCollider(SHCollider* c) noexcept { - - } - - void SHColliderComponent::OnDestroy() - { - - } - - void SHColliderComponent::RecomputeCollisionShapes() noexcept - { - - } - - int SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset, const SHVec3& rotOffset) noexcept - { - return 0; - } - - int SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept - { - return 0; - } - - void SHColliderComponent::RemoveCollider(int index) - { - + collider = c; } } // namespace SHADE diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h index 15a02173..83fb235c 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h @@ -14,14 +14,7 @@ // Project Headers #include "ECS_Base/Components/SHComponent.h" -#include "Math/Geometry/SHBox.h" -#include "Math/Geometry/SHSphere.h" -#include "SHCollisionShape.h" - -//namespace SHADE -//{ -// class SHPhysicsSystem; -//} +#include "Physics/Collision/SHCollider.h" namespace SHADE { @@ -39,12 +32,6 @@ namespace SHADE friend class SHPhysicsSystem; friend class SHPhysicsObject; - /*---------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*---------------------------------------------------------------------------------*/ - - using CollisionShapes = std::vector; - public: /*---------------------------------------------------------------------------------*/ @@ -67,33 +54,22 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] bool HasChanged () const noexcept; - - [[nodiscard]] const CollisionShapes& GetCollisionShapes() const noexcept; - [[nodiscard]] SHCollisionShape& GetCollisionShape (int index); + [[nodiscard]] SHCollider* const GetCollider () const noexcept; + [[nodiscard]] const SHCollider::CollisionShapes* const GetCollisionShapes() const noexcept; + [[nodiscard]] SHCollisionShape* const GetCollisionShape (int index) const; /*---------------------------------------------------------------------------------*/ - /* Function Members */ + /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void OnCreate () override; - void OnDestroy () override; - - void RecomputeCollisionShapes () noexcept; - - void RemoveCollider (int index); - - int AddBoundingBox (const SHVec3& halfExtents = SHVec3::One, const SHVec3& posOffset = SHVec3::Zero, const SHVec3& rotOffset = SHVec3::Zero) noexcept; - int AddBoundingSphere (float radius = 1.0f, const SHVec3& posOffset = SHVec3::Zero) noexcept; + void SetCollider(SHCollider* c) noexcept; private: - /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ - SHVec3 scale; - CollisionShapes collisionShapes; + SHCollider* collider; RTTR_ENABLE() }; diff --git a/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp b/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp deleted file mode 100644 index 4dd506f9..00000000 --- a/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/**************************************************************************************** - * \file SHCollider.cpp - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Implementation for a Collider. - * - * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or - * disclosure of this file or its contents without the prior written consent - * of DigiPen Institute of Technology is prohibited. -****************************************************************************************/ - -#include - -// Primary Header -#include "SHCollisionShape.h" -// Project Headers -#include "Math/Geometry/SHBox.h" -#include "Math/Geometry/SHSphere.h" -#include "Math/SHMathHelpers.h" -#include "Physics/Collision/SHCollisionTagMatrix.h" -#include "Reflection/SHReflectionMetadata.h" -#include "SHColliderComponent.h" - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Constructors & Destructor Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHCollisionShape::SHCollisionShape(EntityID eid, Type colliderType, const SHPhysicsMaterial& physicsMaterial) - : type { colliderType } - , entityID { eid } - , isTrigger { false } - , dirty { true } - , shape { nullptr } - , material { physicsMaterial } - , collisionTag { SHCollisionTagMatrix::GetTag(0) } - { - switch (type) - { - case Type::BOX: - { - shape = new SHBox{ SHVec3::Zero, SHVec3::One }; - break; - } - case Type::SPHERE: - { - shape = new SHSphere{ SHVec3::Zero, 0.5f }; - break; - } - default: break; - } - } - - SHCollisionShape::SHCollisionShape(const SHCollisionShape& rhs) noexcept - : type { rhs.type} - , entityID { rhs.entityID } - , isTrigger { rhs.isTrigger } - , dirty { true } - , shape { nullptr } - , material { rhs.material } - , positionOffset { rhs.positionOffset } - , rotationOffset { rhs.rotationOffset } - , collisionTag { rhs.collisionTag } - { - CopyShape(rhs.shape); - } - - SHCollisionShape::SHCollisionShape(SHCollisionShape&& rhs) noexcept - : type { rhs.type} - , entityID { rhs.entityID } - , isTrigger { rhs.isTrigger } - , dirty { true } - , shape { nullptr } - , material { rhs.material } - , positionOffset { rhs.positionOffset } - , rotationOffset { rhs.rotationOffset } - , collisionTag { rhs.collisionTag } - { - CopyShape(rhs.shape); - } - - SHCollisionShape::~SHCollisionShape() noexcept - { - shape = nullptr; - } - - /*-----------------------------------------------------------------------------------*/ - /* Operator Overload Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHCollisionShape& SHCollisionShape::operator=(const SHCollisionShape& rhs) noexcept - { - if (this == &rhs) - return *this; - - type = rhs.type; - entityID = rhs.entityID; - isTrigger = rhs.isTrigger; - dirty = true; - material = rhs.material; - positionOffset = rhs.positionOffset; - rotationOffset = rhs.rotationOffset; - collisionTag = rhs.collisionTag; - - delete shape; - CopyShape(rhs.shape); - - return *this; - } - - SHCollisionShape& SHCollisionShape::operator=(SHCollisionShape&& rhs) noexcept - { - type = rhs.type; - entityID = rhs.entityID; - isTrigger = rhs.isTrigger; - dirty = true; - material = rhs.material; - positionOffset = rhs.positionOffset; - rotationOffset = rhs.rotationOffset; - collisionTag = rhs.collisionTag; - - delete shape; - CopyShape(rhs.shape); - - return *this; - } - - /*-----------------------------------------------------------------------------------*/ - /* Getter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - bool SHCollisionShape::HasChanged() const noexcept - { - return dirty; - } - - bool SHCollisionShape::IsTrigger() const noexcept - { - return isTrigger; - } - - SHCollisionShape::Type SHCollisionShape::GetType() const noexcept - { - return type; - } - - const SHCollisionTag& SHCollisionShape::GetCollisionTag() const noexcept - { - return *collisionTag; - } - - float SHCollisionShape::GetFriction() const noexcept - { - return material.GetFriction(); - } - - float SHCollisionShape::GetBounciness() const noexcept - { - return material.GetBounciness(); - } - - float SHCollisionShape::GetDensity() const noexcept - { - return material.GetDensity(); - } - - const SHPhysicsMaterial& SHCollisionShape::GetMaterial() const noexcept - { - return material; - } - - const SHVec3& SHCollisionShape::GetPositionOffset() const noexcept - { - return positionOffset; - } - - const SHVec3& SHCollisionShape::GetRotationOffset() const noexcept - { - return rotationOffset; - } - - const SHShape* SHCollisionShape::GetShape() const noexcept - { - return shape; - } - - /*-----------------------------------------------------------------------------------*/ - /* Setter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHCollisionShape::SetBoundingBox(const SHVec3& halfExtents) - { - //dirty = true; - - //const auto* COLLIDER = SHComponentManager::GetComponent(entityID); - //auto* box = reinterpret_cast(shape); - - //SHVec3 correctedHalfExtents = halfExtents; - - //// Get current relative halfExtents for error checking. 0 is ignored - //const SHVec3& CURRENT_RELATIVE_EXTENTS = box->GetRelativeExtents(); - //for (size_t i = 0; i < SHVec3::SIZE; ++i) - //{ - // if (SHMath::CompareFloat(halfExtents[i], 0.0f)) - // correctedHalfExtents[i] = CURRENT_RELATIVE_EXTENTS[i]; - //} - // - //// Set the half extents relative to world scale - //const SHVec3 WORLD_EXTENTS = correctedHalfExtents * COLLIDER->GetScale() * 0.5f; - - //if (type != Type::BOX) - //{ - // type = Type::BOX; - - // delete shape; - // shape = new SHBox{ positionOffset, WORLD_EXTENTS }; - //} - - //box->SetWorldExtents(WORLD_EXTENTS); - //box->SetRelativeExtents(correctedHalfExtents); - } - - void SHCollisionShape::SetBoundingSphere(float radius) - { - //dirty = true; - - //auto* sphere = reinterpret_cast(shape); - //const auto* COLLIDER = SHComponentManager::GetComponent(entityID); - - //// Get current relative halfExtents for error checking. 0 is ignored - //const float CURRENT_RELATIVE_RADIUS = sphere->GetRelativeRadius(); - //if (SHMath::CompareFloat(radius, 0.0f)) - // radius = CURRENT_RELATIVE_RADIUS; - - //// Set the radius relative to world scale - //const SHVec3 WORLD_SCALE = COLLIDER->GetScale(); - //const float MAX_SCALE = SHMath::Max({ WORLD_SCALE.x, WORLD_SCALE.y, WORLD_SCALE.z }); - //const float WORLD_RADIUS = radius * MAX_SCALE * 0.5f; - - //if (type != Type::SPHERE) - //{ - // type = Type::SPHERE; - - // delete shape; - // shape = new SHSphere{ positionOffset, WORLD_RADIUS }; - //} - - //sphere->SetWorldRadius(WORLD_RADIUS); - //sphere->SetRelativeRadius(radius); - } - - void SHCollisionShape::SetIsTrigger(bool trigger) noexcept - { - dirty = true; - isTrigger = trigger; - } - - void SHCollisionShape::SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept - { - dirty = true; - collisionTag = newCollisionTag; - } - - void SHCollisionShape::SetFriction(float friction) noexcept - { - dirty = true; - material.SetFriction(friction); - } - - void SHCollisionShape::SetBounciness(float bounciness) noexcept - { - dirty = true; - material.SetBounciness(bounciness); - } - - void SHCollisionShape::SetDensity(float density) noexcept - { - dirty = true; - material.SetDensity(density); - } - - void SHCollisionShape::SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept - { - dirty = true; - material = newMaterial; - } - - void SHCollisionShape::SetPositionOffset(const SHVec3& posOffset) noexcept - { - dirty = true; - positionOffset = posOffset; - - switch (type) - { - case Type::BOX: - { - reinterpret_cast(shape)->SetCenter(positionOffset); - break; - } - case Type::SPHERE: - { - reinterpret_cast(shape)->SetCenter(positionOffset); - break; - } - default: break; - } - } - - void SHCollisionShape::SetRotationOffset(const SHVec3& rotOffset) noexcept - { - dirty = true; - rotationOffset = rotOffset; - } - - /*-----------------------------------------------------------------------------------*/ - /* Private Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHCollisionShape::CopyShape(const SHShape* rhs) - { - switch (type) - { - case Type::BOX: - { - const auto* RHS_BOX = reinterpret_cast(rhs); - - shape = new SHBox{ positionOffset, RHS_BOX->GetWorldExtents() }; - auto* lhsBox = reinterpret_cast(shape); - lhsBox->SetRelativeExtents(RHS_BOX->GetRelativeExtents()); - - break; - } - case Type::SPHERE: - { - const auto* RHS_SPHERE = reinterpret_cast(rhs); - - shape = new SHSphere{ positionOffset, RHS_SPHERE->GetWorldRadius() }; - auto* lhsSphere = reinterpret_cast(shape); - lhsSphere->SetRelativeRadius(RHS_SPHERE->GetRelativeRadius()); - - break; - } - default: break; - } - } - -} // namespace SHADE - -RTTR_REGISTRATION -{ - using namespace SHADE; - using namespace rttr; - - registration::enumeration("Collider Type") - ( - value("Box", SHCollisionShape::Type::BOX), - value("Sphere", SHCollisionShape::Type::SPHERE) - // TODO(Diren): Add More Shapes - ); - - registration::class_("Collider") - .property("IsTrigger" , &SHCollisionShape::IsTrigger , &SHCollisionShape::SetIsTrigger ) - .property("Friction" , &SHCollisionShape::GetFriction , &SHCollisionShape::SetFriction ) - .property("Bounciness" , &SHCollisionShape::GetBounciness , &SHCollisionShape::SetBounciness ) - .property("Density" , &SHCollisionShape::GetDensity , &SHCollisionShape::SetDensity ) - .property("Position Offset" , &SHCollisionShape::GetPositionOffset, &SHCollisionShape::SetPositionOffset) - .property("Rotation Offset" , &SHCollisionShape::GetRotationOffset, &SHCollisionShape::SetRotationOffset) (metadata(META::angleInRad, true)); -} \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp similarity index 98% rename from SHADE_Engine/src/Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.cpp rename to SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp index ddc51fbc..da848f09 100644 --- a/SHADE_Engine/src/Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp @@ -10,17 +10,9 @@ #include -// External Dependencies -#include - // Primary Header #include "SHRigidBodyComponent.h" -// Project Headers -#include "ECS_Base/Managers/SHSystemManager.h" -#include "Physics/Dynamics/SHRigidBody.h" -#include "Physics/System/SHPhysicsSystem.h" - namespace SHADE { /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h similarity index 96% rename from SHADE_Engine/src/Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h rename to SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h index bfb1717b..7d377184 100644 --- a/SHADE_Engine/src/Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h @@ -15,15 +15,10 @@ // Project Headers #include "ECS_Base/Components/SHComponent.h" #include "Math/Vector/SHVec3.h" +#include "Physics/Dynamics/SHRigidBody.h" namespace SHADE { - /*-------------------------------------------------------------------------------------*/ - /* Forward Declarations */ - /*-------------------------------------------------------------------------------------*/ - - class SHRigidBody; - /*-----------------------------------------------------------------------------------*/ /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/SHPhysicsEvents.h b/SHADE_Engine/src/Physics/SHPhysicsEvents.h index ae48a75b..35217347 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsEvents.h +++ b/SHADE_Engine/src/Physics/SHPhysicsEvents.h @@ -11,7 +11,7 @@ #pragma once // Project Headers -#include "Interface/SHCollisionShape.h" +#include "Collision/CollisionShapes/SHCollisionShape.h" namespace SHADE diff --git a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPostUpdateRoutine.cpp b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPostUpdateRoutine.cpp index 5f18c450..cd4b1cff 100644 --- a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPostUpdateRoutine.cpp +++ b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPostUpdateRoutine.cpp @@ -57,19 +57,20 @@ namespace SHADE if (!rigidBodyComponent.rigidBody) continue; - if (const SHMotionState& MOTION_STATE = rigidBodyComponent.rigidBody->GetMotionState(); MOTION_STATE) - { - SHVec3 renderPosition = rigidBodyComponent.IsInterpolating() - ? MOTION_STATE.InterpolatePositions(FACTOR) - : MOTION_STATE.position; + const SHMotionState& MOTION_STATE = rigidBodyComponent.rigidBody->GetMotionState(); - /* - * TODO: Test if the scene graph transforms abides by setting world position. Collisions will ignore the scene graph hierarchy. - */ + if (!MOTION_STATE) + continue; - transformComponent->SetWorldPosition(renderPosition); - // TODO: SetOrientation - } + SHVec3 renderPosition = rigidBodyComponent.IsInterpolating() ? MOTION_STATE.InterpolatePositions(FACTOR) : MOTION_STATE.position; + + /* + * TODO: Test if the scene graph transforms abides by setting world position. Collisions will ignore the scene graph hierarchy. + */ + + + transformComponent->SetWorldPosition(renderPosition); + // TODO: SetOrientation } // Collision & Trigger messages diff --git a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp index eda69161..c03571db 100644 --- a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp +++ b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp @@ -40,23 +40,32 @@ namespace SHADE { const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent_s(entityID); + if (!TRANSFORM_COMPONENT || !TRANSFORM_COMPONENT->HasChanged()) + return; + + const SHVec3& WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition(); + const SHQuaternion& WORLD_ROT = TRANSFORM_COMPONENT->GetWorldOrientation(); + const SHVec3& WORLD_SCL = TRANSFORM_COMPONENT->GetWorldScale(); + // We assume that all engine components and physics object components have been successfully linked - if (TRANSFORM_COMPONENT && TRANSFORM_COMPONENT->HasChanged()) + if (physicsObject.rigidBody) { - // Sync the objects transforms - const SHVec3 WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition(); + SHMotionState& motionState = physicsObject.rigidBody->GetMotionState(); - if (physicsObject.rigidBody) - { - SHMotionState& motionState = physicsObject.rigidBody->GetMotionState(); - - motionState.ForcePosition(TRANSFORM_COMPONENT->GetWorldPosition()); - // TODO: Force Orientation - } + motionState.ForcePosition(TRANSFORM_COMPONENT->GetWorldPosition()); + // TODO: Force Orientation } - // TODO: Sync Collider Transform with World Transform + if (physicsObject.collider) + { + physicsObject.collider->SetPosition(WORLD_POS); + physicsObject.collider->SetOrientation(WORLD_ROT); + physicsObject.collider->SetScale(WORLD_SCL); + + physicsObject.collider->RecomputeShapes(); + } } } -} + +} // namespace SHADE diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index b4ff6961..d7bece3b 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -162,6 +162,9 @@ namespace SHADE { if (PHYSICS_OBJECT.rigidBody) physicsWorld->RemoveRigidBody(PHYSICS_OBJECT.rigidBody); + + if (PHYSICS_OBJECT.collider) + physicsWorld->RemoveCollider(PHYSICS_OBJECT.collider); } delete physicsWorld; @@ -177,13 +180,16 @@ namespace SHADE // This is for handling scene changes while the editor is active. const auto* EDITOR = SHSystemManager::GetSystem(); - if (EDITOR && EDITOR->editorState == SHEditor::State::PLAY) + if (!EDITOR || EDITOR->editorState != SHEditor::State::PLAY) + return onSceneInitEvent.get()->handle; + + for (const auto& PHYSICS_OBJECT : physicsObjectManager.GetPhysicsObjects() | std::views::values) { - for (const auto& PHYSICS_OBJECT : physicsObjectManager.GetPhysicsObjects() | std::views::values) - { - if (PHYSICS_OBJECT.rigidBody) - physicsWorld->AddRigidBody(PHYSICS_OBJECT.rigidBody); - } + if (PHYSICS_OBJECT.rigidBody) + physicsWorld->AddRigidBody(PHYSICS_OBJECT.rigidBody); + + if (PHYSICS_OBJECT.collider) + physicsWorld->AddCollider(PHYSICS_OBJECT.collider); } #endif @@ -202,6 +208,9 @@ namespace SHADE { if (PHYSICS_OBJECT.rigidBody) physicsWorld->RemoveRigidBody(PHYSICS_OBJECT.rigidBody); + + if (PHYSICS_OBJECT.collider) + physicsWorld->RemoveCollider(PHYSICS_OBJECT.collider); } delete physicsWorld; @@ -223,25 +232,34 @@ namespace SHADE const bool IS_COLLIDER = ADDED_ID == COLLIDER_COMPONENT_ID; // Check if its a physics component - if (IS_RIGID_BODY || IS_COLLIDER) + const bool IS_PHYSICS_COMPONENT = IS_RIGID_BODY || IS_COLLIDER; + if (!IS_PHYSICS_COMPONENT) + return onComponentAddedEvent.get()->handle; + + const EntityID EID = EVENT_DATA->eid; + + // Link engine components with physics object component + if (IS_RIGID_BODY) { - const EntityID EID = EVENT_DATA->eid; + physicsObjectManager.AddRigidBody(EID); - // Link engine components with physics object component - if (IS_RIGID_BODY) + if (physicsWorld) { - physicsObjectManager.AddRigidBody(EID); - - if (physicsWorld) - { - auto* rigidBody = physicsObjectManager.GetPhysicsObject(EID)->rigidBody; - physicsWorld->AddRigidBody(rigidBody); - } + auto* rigidBody = physicsObjectManager.GetPhysicsObject(EID)->rigidBody; + physicsWorld->AddRigidBody(rigidBody); } + } - if (IS_COLLIDER) - physicsObjectManager.AddCollider(EID); + if (IS_COLLIDER) + { + physicsObjectManager.AddCollider(EID); + + if (physicsWorld) + { + auto* collider = physicsObjectManager.GetPhysicsObject(EID)->collider; + physicsWorld->AddCollider(collider); + } } return onComponentAddedEvent.get()->handle; @@ -260,27 +278,35 @@ namespace SHADE const bool IS_COLLIDER = REMOVED_DATA == COLLIDER_COMPONENT_ID; // Check if its a physics component - if (IS_RIGID_BODY || IS_COLLIDER) + const bool IS_PHYSICS_COMPONENT = IS_RIGID_BODY || IS_COLLIDER; + if (!IS_PHYSICS_COMPONENT) + return onComponentRemovedEvent.get()->handle; + + const EntityID EID = EVENT_DATA->eid; + + if (IS_RIGID_BODY) { - const EntityID EID = EVENT_DATA->eid; - - // Link engine components with physics object component - if (IS_RIGID_BODY) + if (physicsWorld) { - if (physicsWorld) - { - auto* rigidBody = physicsObjectManager.GetPhysicsObject(EID)->rigidBody; - physicsWorld->RemoveRigidBody(rigidBody); - } - - physicsObjectManager.RemoveRigidBody(EID); + auto* rigidBody = physicsObjectManager.GetPhysicsObject(EID)->rigidBody; + physicsWorld->RemoveRigidBody(rigidBody); } - - if (IS_COLLIDER) - physicsObjectManager.RemoveCollider(EID); + physicsObjectManager.RemoveRigidBody(EID); } + if (IS_COLLIDER) + { + if (physicsWorld) + { + auto* collider = physicsObjectManager.GetPhysicsObject(EID)->collider; + physicsWorld->RemoveCollider(collider); + } + + physicsObjectManager.RemoveCollider(EID); + } + + return onComponentRemovedEvent.get()->handle; } @@ -295,7 +321,8 @@ namespace SHADE if (PHYSICS_OBJECT.rigidBody) physicsWorld->AddRigidBody(PHYSICS_OBJECT.rigidBody); - // TODO: Add Collider if it exists + if (PHYSICS_OBJECT.collider) + physicsWorld->AddCollider(PHYSICS_OBJECT.collider); } return onEditorPlayEvent.get()->handle; diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index 7d7dece5..2a351e86 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -18,7 +18,7 @@ #include "Physics/Dynamics/SHPhysicsWorld.h" #include "Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h" -#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" #include "Physics/Interface/SHColliderComponent.h" diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index 9d648185..99e4fa41 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -15,7 +15,7 @@ #include "Camera/SHCameraArmComponent.h" #include "Math/Transform/SHTransformComponent.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h" -#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" #include "UI/SHCanvasComponent.h" #include "UI/SHButtonComponent.h" #include "ECS_Base/Managers/SHSystemManager.h" diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index e1cb8181..cbbe8505 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -1,9 +1,7 @@ #pragma once #include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" -#include "Math/Geometry/SHBox.h" -#include "Math/Geometry/SHSphere.h" -#include "Physics/Interface/SHCollisionShape.h" +#include "Physics/Collision/CollisionShapes/SHSphereCollisionShape.h" #include "Resource/SHResourceManager.h" #include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec3.h" @@ -134,14 +132,14 @@ namespace YAML { case SHCollisionShape::Type::BOX: { - const auto* BOX = reinterpret_cast(rhs.GetShape()); - node[HalfExtents] = BOX->GetRelativeExtents(); + //const auto* BOX = reinterpret_cast(rhs.GetShape()); + //node[HalfExtents] = BOX->GetRelativeExtents(); } break; case SHCollisionShape::Type::SPHERE: { - const auto* SPHERE = reinterpret_cast(rhs.GetShape()); - node[Radius] = SPHERE->GetRelativeRadius(); + const auto& SPHERE = dynamic_cast(rhs); + node[Radius] = SPHERE.GetRelativeRadius(); } break; case SHCollisionShape::Type::CAPSULE: break; @@ -172,14 +170,17 @@ namespace YAML { case SHCollisionShape::Type::BOX: { - if (node[HalfExtents].IsDefined()) - rhs.SetBoundingBox(node[HalfExtents].as()); + //if (node[HalfExtents].IsDefined()) + // rhs.SetBoundingBox(node[HalfExtents].as()); } break; case SHCollisionShape::Type::SPHERE: { if (node[Radius].IsDefined()) - rhs.SetBoundingSphere(node[Radius].as()); + { + auto* sphere = dynamic_cast(&rhs); + sphere->SetRelativeRadius(node[Radius].as()); + } } break; case SHCollisionShape::Type::CAPSULE: break; @@ -207,11 +208,10 @@ namespace YAML static Node encode(SHColliderComponent& rhs) { Node node, collidersNode; - auto const& colliders = rhs.GetCollisionShapes(); - int const numColliders = static_cast(colliders.size()); + int const numColliders = static_cast(rhs.GetCollisionShapes()->size()); for (int i = 0; i < numColliders; ++i) { - auto& collider = rhs.GetCollisionShape(i); + auto& collider = *rhs.GetCollisionShape(i); Node colliderNode = convert::encode(collider); if (colliderNode.IsDefined()) collidersNode[i] = colliderNode; @@ -233,14 +233,16 @@ namespace YAML if (!ok) return false; + auto* collider = rhs.GetCollider(); + switch (colliderType) { - case SHCollisionShape::Type::BOX: rhs.AddBoundingBox(); break; - case SHCollisionShape::Type::SPHERE: rhs.AddBoundingSphere(); break; + case SHCollisionShape::Type::BOX: break; + case SHCollisionShape::Type::SPHERE: collider->AddSphereCollisionShape(1.0f); break; case SHCollisionShape::Type::CAPSULE: break; default:; } - YAML::convert::decode(colliderNode, rhs.GetCollisionShape(numColliders++)); + YAML::convert::decode(colliderNode, *collider->GetCollisionShape(numColliders++)); } } return true; diff --git a/SHADE_Managed/src/Components/Collider.cxx b/SHADE_Managed/src/Components/Collider.cxx index 414e79b7..1c84637a 100644 --- a/SHADE_Managed/src/Components/Collider.cxx +++ b/SHADE_Managed/src/Components/Collider.cxx @@ -107,7 +107,7 @@ namespace SHADE try { - auto& shape = collider->GetCollisionShape(arrayIndex); + auto& shape = *collider->GetCollisionShape(arrayIndex); return shape; } catch (std::invalid_argument&) @@ -128,35 +128,39 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ Vector3 BoxCollider::Center::get() { - return Convert::ToCLI(getNativeCollisionShape().GetCenter()); + //return Convert::ToCLI(getNativeCollisionShape().GetCenter()); + return Vector3::Zero; } void BoxCollider::Center::set(Vector3 value) { - getNativeCollisionShape().SetCenter(Convert::ToNative(value)); + //getNativeCollisionShape().SetCenter(Convert::ToNative(value)); } Vector3 BoxCollider::HalfExtents::get() { - return Convert::ToCLI(getNativeCollisionShape().GetWorldExtents()); + //return Convert::ToCLI(getNativeCollisionShape().GetWorldExtents()); + return Vector3::Zero; } void BoxCollider::HalfExtents::set(Vector3 value) { - getNativeCollisionShape().SetWorldExtents(Convert::ToNative(value)); + //getNativeCollisionShape().SetWorldExtents(Convert::ToNative(value)); } Vector3 BoxCollider::Min::get() { - return Convert::ToCLI(getNativeCollisionShape().GetMin()); + //return Convert::ToCLI(getNativeCollisionShape().GetMin()); + return Vector3::Zero; } void BoxCollider::Min::set(Vector3 value) { - getNativeCollisionShape().SetMin(Convert::ToNative(value)); + //getNativeCollisionShape().SetMin(Convert::ToNative(value)); } Vector3 BoxCollider::Max::get() { - return Convert::ToCLI(getNativeCollisionShape().GetMax()); + //return Convert::ToCLI(getNativeCollisionShape().GetMax()); + return Vector3::Zero; } void BoxCollider::Max::set(Vector3 value) { - getNativeCollisionShape().SetMax(Convert::ToNative(value)); + //getNativeCollisionShape().SetMax(Convert::ToNative(value)); } /*---------------------------------------------------------------------------------*/ @@ -164,11 +168,13 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ bool BoxCollider::TestPoint(Vector3 point) { - return getNativeCollisionShape().TestPoint(Convert::ToNative(point)); + //return getNativeCollisionShape().TestPoint(Convert::ToNative(point)); + return false; } bool BoxCollider::Raycast(Ray ray, float maxDistance) { - return getNativeCollisionShape().Raycast(Convert::ToNative(ray)); + //return getNativeCollisionShape().Raycast(Convert::ToNative(ray)); + return false; } /*---------------------------------------------------------------------------------*/ @@ -176,19 +182,19 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ Vector3 SphereCollider::Center::get() { - return Convert::ToCLI(getNativeCollisionShape().GetCenter()); + return Convert::ToCLI(getNativeCollisionShape().GetCenter()); } void SphereCollider::Center::set(Vector3 value) { - getNativeCollisionShape().SetCenter(Convert::ToNative(value)); + getNativeCollisionShape().SetCenter(Convert::ToNative(value)); } float SphereCollider::Radius::get() { - return getNativeCollisionShape().GetWorldRadius(); + return getNativeCollisionShape().GetWorldRadius(); } void SphereCollider::Radius::set(float value) { - getNativeCollisionShape().SetWorldRadius(value); + getNativeCollisionShape().SetWorldRadius(value); } /*---------------------------------------------------------------------------------*/ @@ -196,11 +202,11 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ bool SphereCollider::TestPoint(Vector3 point) { - return getNativeCollisionShape().TestPoint(Convert::ToNative(point)); + return getNativeCollisionShape().TestPoint(Convert::ToNative(point)); } bool SphereCollider::Raycast(Ray ray, float maxDistance) { - return getNativeCollisionShape().Raycast(Convert::ToNative(ray)); + return getNativeCollisionShape().Raycast(Convert::ToNative(ray)); } /*---------------------------------------------------------------------------------*/ @@ -231,7 +237,10 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ int Collider::CollisionShapeCount::get() { - return static_cast(GetNativeComponent()->GetCollisionShapes().size()); + if (const auto* shapes = GetNativeComponent()->GetCollisionShapes()) + return static_cast(shapes->size()); + + return -1; } /*---------------------------------------------------------------------------------*/ @@ -311,10 +320,10 @@ namespace SHADE // Populate the list int i = 0; - for (const auto& collider : GetNativeComponent()->GetCollisionShapes()) + for (const auto* collider : *GetNativeComponent()->GetCollisionShapes()) { CollisionShape^ bound = nullptr; - switch (collider.GetType()) + switch (collider->GetType()) { case SHCollisionShape::Type::BOX: bound = gcnew BoxCollider(i, Owner.GetEntity()); diff --git a/SHADE_Managed/src/Components/Collider.h++ b/SHADE_Managed/src/Components/Collider.h++ index 8ea648aa..c2e732f4 100644 --- a/SHADE_Managed/src/Components/Collider.h++ +++ b/SHADE_Managed/src/Components/Collider.h++ @@ -27,11 +27,11 @@ namespace SHADE try { - auto& shape = collider->GetCollisionShape(arrayIndex); - if (shape.GetType() != SHCollisionShape::Type::BOX) + auto* shape = collider->GetCollisionShape(arrayIndex); + if (!shape || shape->GetType() == SHCollisionShape::Type::INVALID) throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape."); - return reinterpret_cast(shape); + return dynamic_cast(*shape); } catch (std::invalid_argument&) { diff --git a/SHADE_Managed/src/Components/RigidBody.hxx b/SHADE_Managed/src/Components/RigidBody.hxx index 6ca39316..8bfe34aa 100644 --- a/SHADE_Managed/src/Components/RigidBody.hxx +++ b/SHADE_Managed/src/Components/RigidBody.hxx @@ -15,7 +15,7 @@ of DigiPen Institute of Technology is prohibited. #pragma once // External Dependencies -#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" // Project Includes #include "Components/Component.hxx" diff --git a/SHADE_Managed/src/Engine/ECS.cxx b/SHADE_Managed/src/Engine/ECS.cxx index 3ace79ab..c388f0cd 100644 --- a/SHADE_Managed/src/Engine/ECS.cxx +++ b/SHADE_Managed/src/Engine/ECS.cxx @@ -23,7 +23,7 @@ of DigiPen Institute of Technology is prohibited. #include "ECS_Base/Managers/SHEntityManager.h" #include "Math/Transform/SHTransformComponent.h" #include "Physics/Interface/SHColliderComponent.h" -#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" #include "Scene/SHSceneManager.h" #include "Scene/SHSceneGraph.h" #include "Tools/Logger/SHLog.h"