Implemented a custom physics engine #316

Merged
direnbharwani merged 95 commits from SHPhysics into main 2023-01-23 15:55:45 +08:00
45 changed files with 1934 additions and 816 deletions
Showing only changes of commit 74e50e10bd - Show all commits

View File

@ -11,7 +11,7 @@
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h" #include "Physics/Interface/SHRigidBodyComponent.h"
#include "Physics/Interface/SHColliderComponent.h" #include "Physics/Interface/SHColliderComponent.h"
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h" #include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h"

View File

@ -10,7 +10,7 @@
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h" #include "Physics/Interface/SHRigidBodyComponent.h"
#include "Physics/Interface/SHColliderComponent.h" #include "Physics/Interface/SHColliderComponent.h"
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
@ -92,7 +92,7 @@ namespace Sandbox
floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC); floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC);
floorCollider.AddBoundingBox(); //floorCollider.AddBoundingBox();
// Create blank entity with a script // Create blank entity with a script
//testObj = SHADE::SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>(); //testObj = SHADE::SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
@ -113,9 +113,9 @@ namespace Sandbox
racoonTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f }); racoonTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
racoonTransform.SetWorldPosition({ -3.0f, -2.0f, -5.0f }); racoonTransform.SetWorldPosition({ -3.0f, -2.0f, -5.0f });
racoonCollider.AddBoundingBox(); //racoonCollider.AddBoundingBox();
racoonCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f,0.5f,0.0f)); //racoonCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f,0.5f,0.0f));
racoonCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); //racoonCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
auto racoonItemLocation = SHEntityManager::CreateEntity<SHTransformComponent>(); auto racoonItemLocation = SHEntityManager::CreateEntity<SHTransformComponent>();
auto& racoonItemLocationTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(racoonItemLocation); auto& racoonItemLocationTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(racoonItemLocation);
@ -138,15 +138,15 @@ namespace Sandbox
itemTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f }); itemTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
itemTransform.SetWorldPosition({ 0.0f, -2.0f, -5.0f }); itemTransform.SetWorldPosition({ 0.0f, -2.0f, -5.0f });
itemCollider.AddBoundingBox(); //itemCollider.AddBoundingBox();
itemCollider.AddBoundingBox(SHVec3(2.0f,2.0f,2.0f)); //itemCollider.AddBoundingBox(SHVec3(2.0f,2.0f,2.0f));
itemCollider.GetCollisionShape(1).SetIsTrigger(true); //itemCollider.GetCollisionShape(1).SetIsTrigger(true);
itemCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); //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).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
itemCollider.GetCollisionShape(1).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); //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).SetBoundingBox(SHVec3(1.0f, 1.0f, 1.0f));
itemRigidBody.SetInterpolate(false); itemRigidBody.SetInterpolate(false);
itemRigidBody.SetFreezeRotationX(true); itemRigidBody.SetFreezeRotationX(true);
@ -167,9 +167,9 @@ namespace Sandbox
AITransform.SetWorldScale({ 2.0f, 2.0f, 2.0f }); AITransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
AITransform.SetWorldPosition({ -8.0f, -2.0f, 2.5f }); AITransform.SetWorldPosition({ -8.0f, -2.0f, 2.5f });
AICollider.AddBoundingBox(); //AICollider.AddBoundingBox();
AICollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); //AICollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
AICollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); //AICollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
AIRigidBody.SetInterpolate(false); AIRigidBody.SetInterpolate(false);
AIRigidBody.SetFreezeRotationX(true); AIRigidBody.SetFreezeRotationX(true);

View File

@ -322,37 +322,37 @@ namespace SHADE
{ {
DrawContextMenu(component); DrawContextMenu(component);
auto& colliders = component->GetCollisionShapes(); auto* colliders = component->GetCollisionShapes();
int const size = static_cast<int>(colliders.size()); int const size = colliders ? static_cast<int>(colliders->size()) : 0;
ImGui::BeginChild("Collision Shapes", { 0.0f, colliders.empty() ? 1.0f : 250.0f }, true); ImGui::BeginChild("Collision Shapes", { 0.0f, colliders->empty() ? 1.0f : 250.0f }, true);
std::optional<int> colliderToDelete{ std::nullopt }; std::optional<int> colliderToDelete{ std::nullopt };
for (int i{}; i < size; ++i) for (int i{}; i < size; ++i)
{ {
ImGui::PushID(i); ImGui::PushID(i);
SHCollisionShape* collider = &component->GetCollisionShape(i); SHCollisionShape* collider = component->GetCollisionShape(i);
auto cursorPos = ImGui::GetCursorPos(); auto cursorPos = ImGui::GetCursorPos();
//collider->IsTrigger //collider->IsTrigger
if (collider->GetType() == SHCollisionShape::Type::BOX) if (collider->GetType() == SHCollisionShape::Type::BOX)
{ {
SHEditorWidgets::BeginPanel(std::format("{} Box #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); //SHEditorWidgets::BeginPanel(std::format("{} Box #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
//
const auto* BOX = reinterpret_cast<const SHBox*>(collider->GetShape()); //const auto* BOX = reinterpret_cast<const SHBox*>(collider->GetShape());
SHEditorWidgets::DragVec3 //SHEditorWidgets::DragVec3
( //(
"Half Extents", { "X", "Y", "Z" }, // "Half Extents", { "X", "Y", "Z" },
[BOX] { return BOX->GetRelativeExtents(); }, // [BOX] { return BOX->GetRelativeExtents(); },
[collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); }); // [collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); });
} }
else if (collider->GetType() == SHCollisionShape::Type::SPHERE) else if (collider->GetType() == SHCollisionShape::Type::SPHERE)
{ {
SHEditorWidgets::BeginPanel(std::format("{} Sphere #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); SHEditorWidgets::BeginPanel(std::format("{} Sphere #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
const auto* SPHERE = reinterpret_cast<const SHSphere*>(collider->GetShape()); auto* SPHERE = reinterpret_cast<SHSphereCollisionShape*>(collider);
SHEditorWidgets::DragFloat SHEditorWidgets::DragFloat
( (
"Radius", "Radius",
[SPHERE] { return SPHERE->GetRelativeRadius(); }, [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) else if (collider->GetType() == SHCollisionShape::Type::CAPSULE)
{ {
@ -393,7 +393,7 @@ namespace SHADE
} }
if (colliderToDelete.has_value()) if (colliderToDelete.has_value())
{ {
component->RemoveCollider(colliderToDelete.value()); component->GetCollider()->RemoveCollisionShape(colliderToDelete.value());
} }
ImGui::EndChild(); ImGui::EndChild();
@ -401,11 +401,11 @@ namespace SHADE
{ {
if (ImGui::Selectable("Box Collider")) if (ImGui::Selectable("Box Collider"))
{ {
component->AddBoundingBox(); //component->AddBoundingBox();
} }
if (ImGui::Selectable("Sphere Collider")) if (ImGui::Selectable("Sphere Collider"))
{ {
component->AddBoundingSphere(); component->GetCollider()->AddSphereCollisionShape(1.0f);
} }
ImGui::EndMenu(); ImGui::EndMenu();
} }

View File

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

View File

@ -25,13 +25,11 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHSphere::SHSphere() noexcept SHSphere::SHSphere() noexcept
: RelativeRadius { 1.0f }
{ {
type = Type::SPHERE; type = Type::SPHERE;
} }
SHSphere::SHSphere(const SHVec3& center, float radius) noexcept SHSphere::SHSphere(const SHVec3& center, float radius) noexcept
: RelativeRadius { 1.0f }
{ {
type = Type::SPHERE; type = Type::SPHERE;
@ -48,7 +46,6 @@ namespace SHADE
Center = rhs.Center; Center = rhs.Center;
Radius = rhs.Radius; Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
} }
SHSphere::SHSphere(SHSphere&& rhs) noexcept SHSphere::SHSphere(SHSphere&& rhs) noexcept
@ -57,7 +54,6 @@ namespace SHADE
Center = rhs.Center; Center = rhs.Center;
Radius = rhs.Radius; Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -74,7 +70,6 @@ namespace SHADE
{ {
Center = rhs.Center; Center = rhs.Center;
Radius = rhs.Radius; Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
} }
return *this; return *this;
@ -90,50 +85,11 @@ namespace SHADE
{ {
Center = rhs.Center; Center = rhs.Center;
Radius = rhs.Radius; Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
} }
return *this; 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 */ /* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -23,7 +23,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
class SH_API SHSphere : public SHShape, class SH_API SHSphere : public SHShape,
private DirectX::BoundingSphere public DirectX::BoundingSphere
{ {
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -32,8 +32,8 @@ namespace SHADE
SHSphere () noexcept; SHSphere () noexcept;
SHSphere (const SHVec3& center, float radius) noexcept; SHSphere (const SHVec3& center, float radius) noexcept;
SHSphere (const SHSphere& rhs) noexcept; SHSphere (const SHSphere& rhs) noexcept;
SHSphere (SHSphere&& rhs) noexcept; SHSphere (SHSphere&& rhs) noexcept;
~SHSphere () override = default; ~SHSphere () override = default;
@ -44,49 +44,100 @@ namespace SHADE
SHSphere& operator= (const SHSphere& rhs) noexcept; SHSphere& operator= (const SHSphere& rhs) noexcept;
SHSphere& operator= (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 */ /* 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]] 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; * @brief
[[nodiscard]] float SurfaceArea () const noexcept; * Casts a ray against the sphere.
* @param ray
* The ray to cast.
* @return
* The result of the raycast. <br/>
* 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 */ /* 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; * @brief
[[nodiscard]] static SHSphere BuildFromSpheres (const SHSphere* spheres, size_t numSpheres) noexcept; * 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; [[nodiscard]] static SHSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept;
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
float RelativeRadius;
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -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 <SHpch.h>
// 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<Type>(i));
if (flags & FLAG_VALUE)
return static_cast<Type>(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<SHCollisionShape::Type>("Collider Type")
(
value("Box", SHCollisionShape::Type::BOX),
value("Sphere", SHCollisionShape::Type::SPHERE)
// TODO(Diren): Add More Shapes
);
registration::class_<SHCollisionShape>("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));
}

View File

@ -1,7 +1,7 @@
/**************************************************************************************** /****************************************************************************************
* \file SHCollider.h * \file SHCollisionShape.h
* \author Diren D Bharwani, diren.dbharwani, 390002520 * \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 * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent * disclosure of this file or its contents without the prior written consent
@ -16,8 +16,9 @@
#include "ECS_Base/Entity/SHEntity.h" #include "ECS_Base/Entity/SHEntity.h"
#include "Math/Geometry/SHShape.h" #include "Math/Geometry/SHShape.h"
#include "Math/SHQuaternion.h" #include "Math/SHQuaternion.h"
#include "SHPhysicsMaterial.h"
#include "Physics/Collision/SHCollisionTags.h" #include "Physics/Collision/SHCollisionTags.h"
#include "Physics/Collision/SHPhysicsMaterial.h"
#include "SHCollisionShapeID.h"
namespace SHADE namespace SHADE
{ {
@ -34,7 +35,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
friend class SHColliderComponent; friend class SHColliderComponent;
friend class SHPhysicsObject; friend class SHCollisionShapeFactory;
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -46,87 +47,87 @@ namespace SHADE
BOX BOX
, SPHERE , SPHERE
, CAPSULE , CAPSULE
, COUNT
, INVALID = -1
}; };
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */ /* 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 (const SHCollisionShape& rhs) noexcept = default;
SHCollisionShape (SHCollisionShape&& rhs) noexcept; SHCollisionShape (SHCollisionShape&& rhs) noexcept = default;
~SHCollisionShape () noexcept; virtual ~SHCollisionShape () noexcept = default;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Operator Overloads */ /* Operator Overloads */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHCollisionShape& operator=(const SHCollisionShape& rhs) noexcept; SHCollisionShape& operator=(const SHCollisionShape& rhs) noexcept = default;
SHCollisionShape& operator=(SHCollisionShape&& rhs) noexcept; SHCollisionShape& operator=(SHCollisionShape&& rhs) noexcept = default;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] bool HasChanged () const noexcept; // Material Properties
// TODO: Remove individual setters once instanced materials are supported
[[nodiscard]] bool IsTrigger () const noexcept;
[[nodiscard]] Type GetType () const noexcept;
[[nodiscard]] const SHCollisionTag& GetCollisionTag () const noexcept;
[[nodiscard]] float GetFriction () const noexcept; [[nodiscard]] float GetFriction () const noexcept;
[[nodiscard]] float GetBounciness () const noexcept; [[nodiscard]] float GetBounciness () const noexcept;
[[nodiscard]] float GetDensity () const noexcept; [[nodiscard]] float GetDensity () const noexcept;
[[nodiscard]] const SHPhysicsMaterial& GetMaterial () const noexcept; [[nodiscard]] const SHPhysicsMaterial& GetMaterial () const noexcept;
// Offsets
[[nodiscard]] const SHVec3& GetPositionOffset () const noexcept; [[nodiscard]] const SHVec3& GetPositionOffset () const noexcept;
[[nodiscard]] const SHVec3& GetRotationOffset () 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 */ /* 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 SetFriction (float friction) noexcept;
void SetBounciness (float bounciness) noexcept; void SetBounciness (float bounciness) noexcept;
void SetDensity (float density) noexcept; void SetDensity (float density) noexcept;
void SetMaterial (const SHPhysicsMaterial& newMaterial) noexcept; void SetMaterial (const SHPhysicsMaterial& newMaterial) noexcept;
void SetPositionOffset (const SHVec3& posOffset) noexcept; void SetPositionOffset (const SHVec3& posOffset) noexcept;
void SetRotationOffset (const SHVec3& rotOffset) 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 */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
Type type; SHCollisionShapeID id;
EntityID entityID; // The entity this collider belongs to
bool isTrigger;
bool dirty;
SHShape* shape; SHPhysicsMaterial material;
SHPhysicsMaterial material;
SHVec3 positionOffset; SHVec3 positionOffset;
SHVec3 rotationOffset; SHVec3 rotationOffset;
SHCollisionTag* collisionTag; uint8_t flags; // 0 debugDraw wasColliding isColliding trigger capsule sphere box
SHCollisionTag* collisionTag;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
void CopyShape(const SHShape* rhs);
RTTR_ENABLE() RTTR_ENABLE()
}; };

View File

@ -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 <SHpch.h>
// 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

View File

@ -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 <unordered_map>
// Project Header
#include "SHSphereCollisionShape.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/**
* @brief
* Encapsulates a class for Creating and Destroying Collision Shapes. <br/>
* All memory for collision shapes are handled in this factory class. <br/>
* 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<SHCollisionShapeID, SHSphereCollisionShape*, SHCollisionShapeIDHash>;
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
Spheres spheres;
// TODO: Add boxes, capsules and hulls
};
} // namespace SHADE

View File

@ -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<uint32_t>::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"

View File

@ -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<uint64_t>()(id.value);
}
}

View File

@ -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 <SHpch.h>
// 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

View File

@ -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. <br/>
* 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

View File

@ -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 <SHpch.h>
// 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<int>(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<int>(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<int>(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<const SHSphereCollisionShape*>(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

View File

@ -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<SHCollisionShape*>;
/*---------------------------------------------------------------------------------*/
/* 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. <br/>
* 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

View File

@ -13,6 +13,11 @@
// Primary Header // Primary Header
#include "SHCollisionInfo.h" #include "SHCollisionInfo.h"
// Project Headers
#include "Physics/Collision/SHCollider.h"
#include "Physics/Interface/SHColliderComponent.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -77,12 +82,14 @@ namespace SHADE
const SHCollisionShape* SHCollisionInfo::GetColliderA() const noexcept const SHCollisionShape* SHCollisionInfo::GetColliderA() const noexcept
{ {
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_A])->GetCollisionShape(ids[COLLIDER_A]); const auto* COLLIDER_COMPONENT = SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_A]);
return COLLIDER_COMPONENT->GetCollider()->GetCollisionShape(ids[COLLIDER_A]);
} }
const SHCollisionShape* SHCollisionInfo::GetColliderB() const noexcept const SHCollisionShape* SHCollisionInfo::GetColliderB() const noexcept
{ {
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_B])->GetCollisionShape(ids[COLLIDER_B]); const auto* COLLIDER_COMPONENT = SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_B]);
return COLLIDER_COMPONENT->GetCollider()->GetCollisionShape(ids[COLLIDER_B]);
} }
SHCollisionInfo::State SHCollisionInfo::GetCollisionState() const noexcept SHCollisionInfo::State SHCollisionInfo::GetCollisionState() const noexcept

View File

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

View File

@ -74,7 +74,7 @@ namespace SHADE
void SHMotionState::ForcePosition(const SHVec3& newPosition) noexcept void SHMotionState::ForcePosition(const SHVec3& newPosition) noexcept
{ {
hasMoved = false; hasMoved = true;
prevPosition = newPosition; prevPosition = newPosition;
position = newPosition; position = newPosition;

View File

@ -40,7 +40,7 @@ namespace SHADE
void SHPhysicsWorld::AddRigidBody(SHRigidBody* rigidBody) noexcept void SHPhysicsWorld::AddRigidBody(SHRigidBody* rigidBody) noexcept
{ {
const bool INSERTED = rigidBodies.emplace(rigidBody->entityID, rigidBody).second; const bool INSERTED = rigidBodies.emplace(rigidBody).second;
if (!INSERTED) if (!INSERTED)
{ {
SHLOG_WARNING_D("Attempting to add duplicate rigid body {} to the Physics World!", rigidBody->entityID) 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 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) void SHPhysicsWorld::Step(float dt)
{ {
for (auto* rigidBody : rigidBodies | std::views::values) for (auto* rigidBody : rigidBodies)
integrateForces(*rigidBody, dt); integrateForces(*rigidBody, dt);
for (auto* rigidBody : rigidBodies | std::views::values) for (auto* rigidBody : rigidBodies)
integrateVelocities(*rigidBody, dt); integrateVelocities(*rigidBody, dt);
} }

View File

@ -10,12 +10,12 @@
#pragma once #pragma once
#include <unordered_map> #include <unordered_set>
// Project Headers // Project Headers
#include "Physics/Collision/SHCollider.h"
#include "SHRigidBody.h" #include "SHRigidBody.h"
#include "Math/SHMath.h"
#include "SH_API.h"
namespace SHADE namespace SHADE
{ {
@ -66,8 +66,11 @@ namespace SHADE
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void AddRigidBody (SHRigidBody* rigidBody) noexcept; void AddRigidBody (SHRigidBody* rigidBody) noexcept;
void RemoveRigidBody (SHRigidBody* rigidBody) noexcept; void RemoveRigidBody (SHRigidBody* rigidBody) noexcept;
void AddCollider (SHCollider* collider) noexcept;
void RemoveCollider (SHCollider* collider) noexcept;
void Step (float dt); void Step (float dt);
@ -76,7 +79,11 @@ namespace SHADE
/* Type Definitions */ /* Type Definitions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
using RigidBodies = std::unordered_map<EntityID, SHRigidBody*>; //! 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<SHCollider*>;
using RigidBodies = std::unordered_set<SHRigidBody*>;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
@ -84,6 +91,7 @@ namespace SHADE
WorldSettings settings; WorldSettings settings;
Colliders colliders;
RigidBodies rigidBodies; RigidBodies rigidBodies;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -14,6 +14,7 @@
#include "SHRigidBody.h" #include "SHRigidBody.h"
// Project Headers // Project Headers
#include "Physics/Collision/SHCollider.h"
#include "Tools/Logger/SHLogger.h" #include "Tools/Logger/SHLogger.h"
namespace SHADE namespace SHADE
@ -24,6 +25,7 @@ namespace SHADE
SHRigidBody::SHRigidBody(EntityID eid, Type type) noexcept SHRigidBody::SHRigidBody(EntityID eid, Type type) noexcept
: entityID { eid } : entityID { eid }
, collider { nullptr }
, bodyType { type } , bodyType { type }
, invMass { type == Type::DYNAMIC ? 1.0f : 0.0f } , invMass { type == Type::DYNAMIC ? 1.0f : 0.0f }
, linearDrag { 0.01f } , linearDrag { 0.01f }
@ -40,6 +42,7 @@ namespace SHADE
SHRigidBody::SHRigidBody(const SHRigidBody& rhs) noexcept SHRigidBody::SHRigidBody(const SHRigidBody& rhs) noexcept
: entityID { rhs.entityID } : entityID { rhs.entityID }
, collider { nullptr }
, bodyType { rhs.bodyType } , bodyType { rhs.bodyType }
, invMass { rhs.invMass } , invMass { rhs.invMass }
, linearDrag { rhs.linearDrag } , linearDrag { rhs.linearDrag }
@ -52,6 +55,7 @@ namespace SHADE
SHRigidBody::SHRigidBody(SHRigidBody&& rhs) noexcept SHRigidBody::SHRigidBody(SHRigidBody&& rhs) noexcept
: entityID { rhs.entityID } : entityID { rhs.entityID }
, collider { nullptr }
, bodyType { rhs.bodyType } , bodyType { rhs.bodyType }
, invMass { rhs.invMass } , invMass { rhs.invMass }
, linearDrag { rhs.linearDrag } , linearDrag { rhs.linearDrag }
@ -73,6 +77,8 @@ namespace SHADE
return *this; return *this;
entityID = rhs.entityID; entityID = rhs.entityID;
// Deep copy the collider
*collider = *rhs.collider;
bodyType = rhs.bodyType; bodyType = rhs.bodyType;
invMass = rhs.invMass; invMass = rhs.invMass;
linearDrag = rhs.linearDrag; linearDrag = rhs.linearDrag;
@ -91,6 +97,8 @@ namespace SHADE
SHRigidBody& SHRigidBody::operator=(SHRigidBody&& rhs) noexcept SHRigidBody& SHRigidBody::operator=(SHRigidBody&& rhs) noexcept
{ {
entityID = rhs.entityID; entityID = rhs.entityID;
// Deep copy the collider
*collider = *rhs.collider;
bodyType = rhs.bodyType; bodyType = rhs.bodyType;
invMass = rhs.invMass; invMass = rhs.invMass;
linearDrag = rhs.linearDrag; linearDrag = rhs.linearDrag;
@ -223,6 +231,11 @@ namespace SHADE
/* Setter Functions Definitions */ /* Setter Functions Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHRigidBody::SetCollider(SHCollider* c) noexcept
{
collider = c;
}
void SHRigidBody::SetType(Type newType) noexcept void SHRigidBody::SetType(Type newType) noexcept
{ {
if (newType == bodyType) if (newType == bodyType)

View File

@ -11,12 +11,18 @@
#pragma once #pragma once
// Project Headers // Project Headers
#include "ECS_Base/SHECSMacros.h" #include "ECS_Base/Entity/SHEntity.h"
#include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec3.h"
#include "SHMotionState.h" #include "SHMotionState.h"
namespace SHADE namespace SHADE
{ {
/*-------------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-------------------------------------------------------------------------------------*/
class SHCollider;
/*-------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------*/
@ -96,6 +102,8 @@ namespace SHADE
/* Setter Functions */ /* Setter Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SetCollider (SHCollider* c) noexcept;
/** /**
* @brief * @brief
* Changing the type from non-Dynamic to Dynamic will set the default * 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. // The entityID here is only meant for linking with the actual component in the engine.
EntityID entityID; EntityID entityID;
SHCollider* collider;
Type bodyType; Type bodyType;
@ -187,7 +196,7 @@ namespace SHADE
SHVec3 linearVelocity; SHVec3 linearVelocity;
SHVec3 angularVelocity; 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; uint16_t flags;
SHMotionState motionState; SHMotionState motionState;

View File

@ -26,15 +26,13 @@ namespace SHADE
SHPhysicsObject::SHPhysicsObject(const SHPhysicsObject& rhs) noexcept SHPhysicsObject::SHPhysicsObject(const SHPhysicsObject& rhs) noexcept
: entityID { rhs.entityID } : entityID { rhs.entityID }
{ {
// Perform a deep copy of the components deepCopyComponents(rhs.rigidBody, rhs.collider);
*rigidBody = *rhs.rigidBody;
} }
SHPhysicsObject::SHPhysicsObject(SHPhysicsObject&& rhs) noexcept SHPhysicsObject::SHPhysicsObject(SHPhysicsObject&& rhs) noexcept
: entityID { rhs.entityID } : entityID { rhs.entityID }
{ {
// Perform a deep copy of the components deepCopyComponents(rhs.rigidBody, rhs.collider);
*rigidBody = *rhs.rigidBody;
} }
SHPhysicsObject::~SHPhysicsObject() noexcept SHPhysicsObject::~SHPhysicsObject() noexcept
@ -42,6 +40,10 @@ namespace SHADE
entityID = MAX_EID; entityID = MAX_EID;
delete rigidBody; delete rigidBody;
rigidBody = nullptr;
delete collider;
collider = nullptr;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -53,20 +55,18 @@ namespace SHADE
if (this == &rhs) if (this == &rhs)
return *this; return *this;
entityID = rhs.entityID; entityID = rhs.entityID;
// Perform a deep copy of the components deepCopyComponents(rhs.rigidBody, rhs.collider);
*rigidBody = *rhs.rigidBody;
return *this; return *this;
} }
SHPhysicsObject& SHPhysicsObject::operator=(SHPhysicsObject&& rhs) noexcept SHPhysicsObject& SHPhysicsObject::operator=(SHPhysicsObject&& rhs) noexcept
{ {
entityID = rhs.entityID; entityID = rhs.entityID;
// Perform a deep copy of the components deepCopyComponents(rhs.rigidBody, rhs.collider);
*rigidBody = *rhs.rigidBody;
return *this; return *this;
} }
@ -77,7 +77,74 @@ namespace SHADE
bool SHPhysicsObject::IsEmpty() const noexcept 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 } // namespace SHADE

View File

@ -11,6 +11,7 @@
#pragma once #pragma once
// Project Headers // Project Headers
#include "Physics/Collision/SHCollider.h"
#include "Physics/Dynamics/SHRigidBody.h" #include "Physics/Dynamics/SHRigidBody.h"
namespace SHADE namespace SHADE
@ -32,6 +33,7 @@ namespace SHADE
EntityID entityID = MAX_EID; EntityID entityID = MAX_EID;
SHRigidBody* rigidBody = nullptr; SHRigidBody* rigidBody = nullptr;
SHCollider* collider = nullptr;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor */ /* Constructors & Destructor */
@ -53,6 +55,55 @@ namespace SHADE
/* Member Functions */ /* 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 } // namespace SHADE

View File

@ -16,8 +16,7 @@
// Project Headers // Project Headers
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Physics/Interface/SHColliderComponent.h" #include "Physics/Interface/SHColliderComponent.h"
#include "Physics/Interface/SHCollisionShape.h" #include "Physics/Interface/SHRigidBodyComponent.h"
#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
#include "Tools/Utilities/SHUtilities.h" #include "Tools/Utilities/SHUtilities.h"
namespace SHADE namespace SHADE
@ -58,66 +57,68 @@ namespace SHADE
void SHPhysicsObjectManager::AddRigidBody(EntityID entityID) noexcept void SHPhysicsObjectManager::AddRigidBody(EntityID entityID) noexcept
{ {
SHPhysicsObject* physicsObject = nullptr; SHPhysicsObject* physicsObject = ensurePhysicsObject(entityID);
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
if (PHYSICS_OBJECT_ITERATOR == physicsObjects.end())
physicsObject = createPhysicsObject(entityID);
else
physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
// Get the component // Get the component
auto* rigidBodyComponent = SHComponentManager::GetComponent<SHRigidBodyComponent>(entityID); auto* rigidBodyComponent = SHComponentManager::GetComponent<SHRigidBodyComponent>(entityID);
// Create a new rigidbody in the physics object // Create a new rigidbody in the physics object
// We assume none has already been made const auto RIGID_BODY_TYPE = static_cast<SHRigidBody::Type>(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<SHTransformComponent>(entityID); TRANSFORM_COMPONENT)
{ {
entityID worldPos = TRANSFORM_COMPONENT->GetWorldPosition();
, static_cast<SHRigidBody::Type>(rigidBodyComponent->GetType())
};
SHMotionState& motionState = physicsObject->rigidBody->GetMotionState();
if (const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent<SHTransformComponent>(entityID); TRANSFORM_COMPONENT)
{
motionState.ForcePosition(TRANSFORM_COMPONENT->GetWorldPosition());
}
else
{
motionState.ForcePosition(SHVec3::Zero);
} }
SHMotionState& motionState = rigidBody->GetMotionState();
motionState.ForcePosition(worldPos);
// Link with the component // Link with the component
rigidBodyComponent->SetRigidBody(physicsObject->rigidBody); rigidBodyComponent->SetRigidBody(rigidBody);
// TODO: Broadcast event
} }
void SHPhysicsObjectManager::RemoveRigidBody(EntityID entityID) noexcept void SHPhysicsObjectManager::RemoveRigidBody(EntityID entityID) noexcept
{ {
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID); const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
if (PHYSICS_OBJECT_ITERATOR != physicsObjects.end()) if (PHYSICS_OBJECT_ITERATOR == physicsObjects.end())
{ return;
SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
delete physicsObject->rigidBody; SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
physicsObject->rigidBody = nullptr;
// Destroy empty physics objects physicsObject->DestroyRigidBody();
if (physicsObject->IsEmpty())
destroyPhysicsObject(entityID);
}
// TODO: Broadcast event // Destroy empty physics objects
if (physicsObject->IsEmpty())
destroyPhysicsObject(entityID);
} }
void SHPhysicsObjectManager::AddCollider(EntityID entityID) noexcept void SHPhysicsObjectManager::AddCollider(EntityID entityID) noexcept
{ {
// Link with the component SHPhysicsObject* physicsObject = ensurePhysicsObject(entityID);
// TODO: Broadcast event // Get the component
auto* colliderComponent = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
SHTransform worldTransform = SHTransform::Identity;
if (const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent_s<SHTransformComponent>(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 void SHPhysicsObjectManager::RemoveCollider(EntityID entityID) noexcept
@ -127,30 +128,17 @@ namespace SHADE
{ {
SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second; SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
physicsObject->DestroyCollider();
// Destroy empty physics objects // Destroy empty physics objects
if (physicsObject->IsEmpty()) if (physicsObject->IsEmpty())
destroyPhysicsObject(entityID); 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 void SHPhysicsObjectManager::RemoveAllObjects() noexcept
{ {
// Physics objects itself will delete the object
physicsObjects.clear(); physicsObjects.clear();
} }
@ -164,6 +152,18 @@ namespace SHADE
return &NEW_OBJECT->second; 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) void SHPhysicsObjectManager::destroyPhysicsObject(EntityID entityID)
{ {
physicsObjects.erase(entityID); physicsObjects.erase(entityID);

View File

@ -14,6 +14,7 @@
// Project Headers // Project Headers
#include "SHPhysicsObject.h" #include "SHPhysicsObject.h"
#include "Physics/Collision/CollisionShapes/SHCollisionShapeFactory.h"
namespace SHADE namespace SHADE
{ {
@ -26,7 +27,7 @@ namespace SHADE
* Encapsulates a manager for physics objects that links raw physics components with the * Encapsulates a manager for physics objects that links raw physics components with the
* engine's components. * engine's components.
*/ */
class SHPhysicsObjectManager class SH_API SHPhysicsObjectManager
{ {
private: private:
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -60,7 +61,7 @@ namespace SHADE
* @param entityID * @param entityID
* The entity to link the new rigid body to. * The entity to link the new rigid body to.
*/ */
void AddRigidBody (EntityID entityID) noexcept; void AddRigidBody (EntityID entityID) noexcept;
/** /**
* @brief * @brief
@ -68,66 +69,48 @@ namespace SHADE
* @param entityID * @param entityID
* The entity to destroy the rigid body of. * The entity to destroy the rigid body of.
*/ */
void RemoveRigidBody (EntityID entityID) noexcept; void RemoveRigidBody (EntityID entityID) noexcept;
/** /**
* @brief * @brief
* Creates a collider and links it with the collider component. * Creates a composite collider and links it with the collider component.
* @param entityID * @param entityID
* The entity to link the new collider to. * The entity to link the new collider to.
*/ */
void AddCollider (EntityID entityID) noexcept; void AddCollider (EntityID entityID) noexcept;
/** /**
* @brief * @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 * @param entityID
* The entity to destroy the collider of. * The entity to destroy the collider of.
*/ */
void RemoveCollider (EntityID entityID) noexcept; 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;
/** /**
* @brief * @brief
* Removes all physics object in the manager. This is only meant to be called when * 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. * the world is being destroyed or the scene is being changed.
*/ */
void RemoveAllObjects () noexcept; void RemoveAllObjects () noexcept;
private: private:
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
EntityObjectMap physicsObjects; EntityObjectMap physicsObjects;
SHCollisionShapeFactory shapeFactory;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Member Functions */ /* Member Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHPhysicsObject* createPhysicsObject (EntityID entityID); SHPhysicsObject* createPhysicsObject (EntityID entityID);
SHPhysicsObject* ensurePhysicsObject (EntityID entityID);
void destroyPhysicsObject (EntityID entityID); void destroyPhysicsObject (EntityID entityID);
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -25,57 +25,43 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHColliderComponent::SHColliderComponent() noexcept SHColliderComponent::SHColliderComponent() noexcept
: collider { nullptr }
{} {}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */ /* 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<size_t>(index) >= collisionShapes.size()) if (!collider)
throw std::invalid_argument("Out-of-range access!"); 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
{ {
collider = c;
}
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)
{
} }
} // namespace SHADE } // namespace SHADE

View File

@ -14,14 +14,7 @@
// Project Headers // Project Headers
#include "ECS_Base/Components/SHComponent.h" #include "ECS_Base/Components/SHComponent.h"
#include "Math/Geometry/SHBox.h" #include "Physics/Collision/SHCollider.h"
#include "Math/Geometry/SHSphere.h"
#include "SHCollisionShape.h"
//namespace SHADE
//{
// class SHPhysicsSystem;
//}
namespace SHADE namespace SHADE
{ {
@ -39,12 +32,6 @@ namespace SHADE
friend class SHPhysicsSystem; friend class SHPhysicsSystem;
friend class SHPhysicsObject; friend class SHPhysicsObject;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
using CollisionShapes = std::vector<SHCollisionShape>;
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -67,33 +54,22 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] bool HasChanged () const noexcept; [[nodiscard]] SHCollider* const GetCollider () const noexcept;
[[nodiscard]] const SHCollider::CollisionShapes* const GetCollisionShapes() const noexcept;
[[nodiscard]] const CollisionShapes& GetCollisionShapes() const noexcept; [[nodiscard]] SHCollisionShape* const GetCollisionShape (int index) const;
[[nodiscard]] SHCollisionShape& GetCollisionShape (int index);
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void OnCreate () override; void SetCollider(SHCollider* c) noexcept;
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;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHVec3 scale; SHCollider* collider;
CollisionShapes collisionShapes;
RTTR_ENABLE() RTTR_ENABLE()
}; };

View File

@ -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 <SHpch.h>
// 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<SHColliderComponent>(entityID);
//auto* box = reinterpret_cast<SHBox*>(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<SHSphere*>(shape);
//const auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(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<SHBox*>(shape)->SetCenter(positionOffset);
break;
}
case Type::SPHERE:
{
reinterpret_cast<SHSphere*>(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<const SHBox*>(rhs);
shape = new SHBox{ positionOffset, RHS_BOX->GetWorldExtents() };
auto* lhsBox = reinterpret_cast<SHBox*>(shape);
lhsBox->SetRelativeExtents(RHS_BOX->GetRelativeExtents());
break;
}
case Type::SPHERE:
{
const auto* RHS_SPHERE = reinterpret_cast<const SHSphere*>(rhs);
shape = new SHSphere{ positionOffset, RHS_SPHERE->GetWorldRadius() };
auto* lhsSphere = reinterpret_cast<SHSphere*>(shape);
lhsSphere->SetRelativeRadius(RHS_SPHERE->GetRelativeRadius());
break;
}
default: break;
}
}
} // namespace SHADE
RTTR_REGISTRATION
{
using namespace SHADE;
using namespace rttr;
registration::enumeration<SHCollisionShape::Type>("Collider Type")
(
value("Box", SHCollisionShape::Type::BOX),
value("Sphere", SHCollisionShape::Type::SPHERE)
// TODO(Diren): Add More Shapes
);
registration::class_<SHCollisionShape>("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));
}

View File

@ -10,17 +10,9 @@
#include <SHpch.h> #include <SHpch.h>
// External Dependencies
#include <reactphysics3d/reactphysics3d.h>
// Primary Header // Primary Header
#include "SHRigidBodyComponent.h" #include "SHRigidBodyComponent.h"
// Project Headers
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Physics/Dynamics/SHRigidBody.h"
#include "Physics/System/SHPhysicsSystem.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -15,15 +15,10 @@
// Project Headers // Project Headers
#include "ECS_Base/Components/SHComponent.h" #include "ECS_Base/Components/SHComponent.h"
#include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec3.h"
#include "Physics/Dynamics/SHRigidBody.h"
namespace SHADE namespace SHADE
{ {
/*-------------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-------------------------------------------------------------------------------------*/
class SHRigidBody;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -11,7 +11,7 @@
#pragma once #pragma once
// Project Headers // Project Headers
#include "Interface/SHCollisionShape.h" #include "Collision/CollisionShapes/SHCollisionShape.h"
namespace SHADE namespace SHADE

View File

@ -57,19 +57,20 @@ namespace SHADE
if (!rigidBodyComponent.rigidBody) if (!rigidBodyComponent.rigidBody)
continue; continue;
if (const SHMotionState& MOTION_STATE = rigidBodyComponent.rigidBody->GetMotionState(); MOTION_STATE) const SHMotionState& MOTION_STATE = rigidBodyComponent.rigidBody->GetMotionState();
{
SHVec3 renderPosition = rigidBodyComponent.IsInterpolating()
? MOTION_STATE.InterpolatePositions(FACTOR)
: MOTION_STATE.position;
/* if (!MOTION_STATE)
* TODO: Test if the scene graph transforms abides by setting world position. Collisions will ignore the scene graph hierarchy. continue;
*/
transformComponent->SetWorldPosition(renderPosition); SHVec3 renderPosition = rigidBodyComponent.IsInterpolating() ? MOTION_STATE.InterpolatePositions(FACTOR) : MOTION_STATE.position;
// TODO: SetOrientation
} /*
* 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 // Collision & Trigger messages

View File

@ -40,23 +40,32 @@ namespace SHADE
{ {
const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID); const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent_s<SHTransformComponent>(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 // 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 SHMotionState& motionState = physicsObject.rigidBody->GetMotionState();
const SHVec3 WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition();
if (physicsObject.rigidBody) motionState.ForcePosition(TRANSFORM_COMPONENT->GetWorldPosition());
{ // TODO: Force Orientation
SHMotionState& motionState = physicsObject.rigidBody->GetMotionState();
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

View File

@ -162,6 +162,9 @@ namespace SHADE
{ {
if (PHYSICS_OBJECT.rigidBody) if (PHYSICS_OBJECT.rigidBody)
physicsWorld->RemoveRigidBody(PHYSICS_OBJECT.rigidBody); physicsWorld->RemoveRigidBody(PHYSICS_OBJECT.rigidBody);
if (PHYSICS_OBJECT.collider)
physicsWorld->RemoveCollider(PHYSICS_OBJECT.collider);
} }
delete physicsWorld; delete physicsWorld;
@ -177,13 +180,16 @@ namespace SHADE
// This is for handling scene changes while the editor is active. // This is for handling scene changes while the editor is active.
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>(); const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
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 #endif
@ -202,6 +208,9 @@ namespace SHADE
{ {
if (PHYSICS_OBJECT.rigidBody) if (PHYSICS_OBJECT.rigidBody)
physicsWorld->RemoveRigidBody(PHYSICS_OBJECT.rigidBody); physicsWorld->RemoveRigidBody(PHYSICS_OBJECT.rigidBody);
if (PHYSICS_OBJECT.collider)
physicsWorld->RemoveCollider(PHYSICS_OBJECT.collider);
} }
delete physicsWorld; delete physicsWorld;
@ -223,25 +232,34 @@ namespace SHADE
const bool IS_COLLIDER = ADDED_ID == COLLIDER_COMPONENT_ID; const bool IS_COLLIDER = ADDED_ID == COLLIDER_COMPONENT_ID;
// Check if its a physics component // 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 (physicsWorld)
if (IS_RIGID_BODY)
{ {
physicsObjectManager.AddRigidBody(EID); auto* rigidBody = physicsObjectManager.GetPhysicsObject(EID)->rigidBody;
physicsWorld->AddRigidBody(rigidBody);
if (physicsWorld)
{
auto* rigidBody = physicsObjectManager.GetPhysicsObject(EID)->rigidBody;
physicsWorld->AddRigidBody(rigidBody);
}
} }
}
if (IS_COLLIDER) if (IS_COLLIDER)
physicsObjectManager.AddCollider(EID); {
physicsObjectManager.AddCollider(EID);
if (physicsWorld)
{
auto* collider = physicsObjectManager.GetPhysicsObject(EID)->collider;
physicsWorld->AddCollider(collider);
}
} }
return onComponentAddedEvent.get()->handle; return onComponentAddedEvent.get()->handle;
@ -260,27 +278,35 @@ namespace SHADE
const bool IS_COLLIDER = REMOVED_DATA == COLLIDER_COMPONENT_ID; const bool IS_COLLIDER = REMOVED_DATA == COLLIDER_COMPONENT_ID;
// Check if its a physics component // 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; if (physicsWorld)
// Link engine components with physics object component
if (IS_RIGID_BODY)
{ {
if (physicsWorld) auto* rigidBody = physicsObjectManager.GetPhysicsObject(EID)->rigidBody;
{ physicsWorld->RemoveRigidBody(rigidBody);
auto* rigidBody = physicsObjectManager.GetPhysicsObject(EID)->rigidBody;
physicsWorld->RemoveRigidBody(rigidBody);
}
physicsObjectManager.RemoveRigidBody(EID);
} }
if (IS_COLLIDER) physicsObjectManager.RemoveRigidBody(EID);
physicsObjectManager.RemoveCollider(EID);
} }
if (IS_COLLIDER)
{
if (physicsWorld)
{
auto* collider = physicsObjectManager.GetPhysicsObject(EID)->collider;
physicsWorld->RemoveCollider(collider);
}
physicsObjectManager.RemoveCollider(EID);
}
return onComponentRemovedEvent.get()->handle; return onComponentRemovedEvent.get()->handle;
} }
@ -295,7 +321,8 @@ namespace SHADE
if (PHYSICS_OBJECT.rigidBody) if (PHYSICS_OBJECT.rigidBody)
physicsWorld->AddRigidBody(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; return onEditorPlayEvent.get()->handle;

View File

@ -18,7 +18,7 @@
#include "Physics/Dynamics/SHPhysicsWorld.h" #include "Physics/Dynamics/SHPhysicsWorld.h"
#include "Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h" #include "Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h"
#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h" #include "Physics/Interface/SHRigidBodyComponent.h"
#include "Physics/Interface/SHColliderComponent.h" #include "Physics/Interface/SHColliderComponent.h"

View File

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

View File

@ -1,9 +1,7 @@
#pragma once #pragma once
#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
#include "Math/Geometry/SHBox.h" #include "Physics/Collision/CollisionShapes/SHSphereCollisionShape.h"
#include "Math/Geometry/SHSphere.h"
#include "Physics/Interface/SHCollisionShape.h"
#include "Resource/SHResourceManager.h" #include "Resource/SHResourceManager.h"
#include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec2.h"
#include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec3.h"
@ -134,14 +132,14 @@ namespace YAML
{ {
case SHCollisionShape::Type::BOX: case SHCollisionShape::Type::BOX:
{ {
const auto* BOX = reinterpret_cast<const SHBox*>(rhs.GetShape()); //const auto* BOX = reinterpret_cast<const SHBox*>(rhs.GetShape());
node[HalfExtents] = BOX->GetRelativeExtents(); //node[HalfExtents] = BOX->GetRelativeExtents();
} }
break; break;
case SHCollisionShape::Type::SPHERE: case SHCollisionShape::Type::SPHERE:
{ {
const auto* SPHERE = reinterpret_cast<const SHSphere*>(rhs.GetShape()); const auto& SPHERE = dynamic_cast<const SHSphereCollisionShape&>(rhs);
node[Radius] = SPHERE->GetRelativeRadius(); node[Radius] = SPHERE.GetRelativeRadius();
} }
break; break;
case SHCollisionShape::Type::CAPSULE: break; case SHCollisionShape::Type::CAPSULE: break;
@ -172,14 +170,17 @@ namespace YAML
{ {
case SHCollisionShape::Type::BOX: case SHCollisionShape::Type::BOX:
{ {
if (node[HalfExtents].IsDefined()) //if (node[HalfExtents].IsDefined())
rhs.SetBoundingBox(node[HalfExtents].as<SHVec3>()); // rhs.SetBoundingBox(node[HalfExtents].as<SHVec3>());
} }
break; break;
case SHCollisionShape::Type::SPHERE: case SHCollisionShape::Type::SPHERE:
{ {
if (node[Radius].IsDefined()) if (node[Radius].IsDefined())
rhs.SetBoundingSphere(node[Radius].as<float>()); {
auto* sphere = dynamic_cast<SHSphereCollisionShape*>(&rhs);
sphere->SetRelativeRadius(node[Radius].as<float>());
}
} }
break; break;
case SHCollisionShape::Type::CAPSULE: break; case SHCollisionShape::Type::CAPSULE: break;
@ -207,11 +208,10 @@ namespace YAML
static Node encode(SHColliderComponent& rhs) static Node encode(SHColliderComponent& rhs)
{ {
Node node, collidersNode; Node node, collidersNode;
auto const& colliders = rhs.GetCollisionShapes(); int const numColliders = static_cast<int>(rhs.GetCollisionShapes()->size());
int const numColliders = static_cast<int>(colliders.size());
for (int i = 0; i < numColliders; ++i) for (int i = 0; i < numColliders; ++i)
{ {
auto& collider = rhs.GetCollisionShape(i); auto& collider = *rhs.GetCollisionShape(i);
Node colliderNode = convert<SHCollisionShape>::encode(collider); Node colliderNode = convert<SHCollisionShape>::encode(collider);
if (colliderNode.IsDefined()) if (colliderNode.IsDefined())
collidersNode[i] = colliderNode; collidersNode[i] = colliderNode;
@ -233,14 +233,16 @@ namespace YAML
if (!ok) if (!ok)
return false; return false;
auto* collider = rhs.GetCollider();
switch (colliderType) switch (colliderType)
{ {
case SHCollisionShape::Type::BOX: rhs.AddBoundingBox(); break; case SHCollisionShape::Type::BOX: break;
case SHCollisionShape::Type::SPHERE: rhs.AddBoundingSphere(); break; case SHCollisionShape::Type::SPHERE: collider->AddSphereCollisionShape(1.0f); break;
case SHCollisionShape::Type::CAPSULE: break; case SHCollisionShape::Type::CAPSULE: break;
default:; default:;
} }
YAML::convert<SHCollisionShape>::decode(colliderNode, rhs.GetCollisionShape(numColliders++)); YAML::convert<SHCollisionShape>::decode(colliderNode, *collider->GetCollisionShape(numColliders++));
} }
} }
return true; return true;

View File

@ -107,7 +107,7 @@ namespace SHADE
try try
{ {
auto& shape = collider->GetCollisionShape(arrayIndex); auto& shape = *collider->GetCollisionShape(arrayIndex);
return shape; return shape;
} }
catch (std::invalid_argument&) catch (std::invalid_argument&)
@ -128,35 +128,39 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
Vector3 BoxCollider::Center::get() Vector3 BoxCollider::Center::get()
{ {
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetCenter()); //return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetCenter());
return Vector3::Zero;
} }
void BoxCollider::Center::set(Vector3 value) void BoxCollider::Center::set(Vector3 value)
{ {
getNativeCollisionShape<SHBox>().SetCenter(Convert::ToNative(value)); //getNativeCollisionShape<SHBox>().SetCenter(Convert::ToNative(value));
} }
Vector3 BoxCollider::HalfExtents::get() Vector3 BoxCollider::HalfExtents::get()
{ {
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetWorldExtents()); //return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetWorldExtents());
return Vector3::Zero;
} }
void BoxCollider::HalfExtents::set(Vector3 value) void BoxCollider::HalfExtents::set(Vector3 value)
{ {
getNativeCollisionShape<SHBox>().SetWorldExtents(Convert::ToNative(value)); //getNativeCollisionShape<SHBox>().SetWorldExtents(Convert::ToNative(value));
} }
Vector3 BoxCollider::Min::get() Vector3 BoxCollider::Min::get()
{ {
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetMin()); //return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetMin());
return Vector3::Zero;
} }
void BoxCollider::Min::set(Vector3 value) void BoxCollider::Min::set(Vector3 value)
{ {
getNativeCollisionShape<SHBox>().SetMin(Convert::ToNative(value)); //getNativeCollisionShape<SHBox>().SetMin(Convert::ToNative(value));
} }
Vector3 BoxCollider::Max::get() Vector3 BoxCollider::Max::get()
{ {
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetMax()); //return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetMax());
return Vector3::Zero;
} }
void BoxCollider::Max::set(Vector3 value) void BoxCollider::Max::set(Vector3 value)
{ {
getNativeCollisionShape<SHBox>().SetMax(Convert::ToNative(value)); //getNativeCollisionShape<SHBox>().SetMax(Convert::ToNative(value));
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -164,11 +168,13 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
bool BoxCollider::TestPoint(Vector3 point) bool BoxCollider::TestPoint(Vector3 point)
{ {
return getNativeCollisionShape<SHBox>().TestPoint(Convert::ToNative(point)); //return getNativeCollisionShape<SHBox>().TestPoint(Convert::ToNative(point));
return false;
} }
bool BoxCollider::Raycast(Ray ray, float maxDistance) bool BoxCollider::Raycast(Ray ray, float maxDistance)
{ {
return getNativeCollisionShape<SHBox>().Raycast(Convert::ToNative(ray)); //return getNativeCollisionShape<SHBox>().Raycast(Convert::ToNative(ray));
return false;
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -176,19 +182,19 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
Vector3 SphereCollider::Center::get() Vector3 SphereCollider::Center::get()
{ {
return Convert::ToCLI(getNativeCollisionShape<SHSphere>().GetCenter()); return Convert::ToCLI(getNativeCollisionShape<SHSphereCollisionShape>().GetCenter());
} }
void SphereCollider::Center::set(Vector3 value) void SphereCollider::Center::set(Vector3 value)
{ {
getNativeCollisionShape<SHSphere>().SetCenter(Convert::ToNative(value)); getNativeCollisionShape<SHSphereCollisionShape>().SetCenter(Convert::ToNative(value));
} }
float SphereCollider::Radius::get() float SphereCollider::Radius::get()
{ {
return getNativeCollisionShape<SHSphere>().GetWorldRadius(); return getNativeCollisionShape<SHSphereCollisionShape>().GetWorldRadius();
} }
void SphereCollider::Radius::set(float value) void SphereCollider::Radius::set(float value)
{ {
getNativeCollisionShape<SHSphere>().SetWorldRadius(value); getNativeCollisionShape<SHSphereCollisionShape>().SetWorldRadius(value);
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -196,11 +202,11 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
bool SphereCollider::TestPoint(Vector3 point) bool SphereCollider::TestPoint(Vector3 point)
{ {
return getNativeCollisionShape<SHBox>().TestPoint(Convert::ToNative(point)); return getNativeCollisionShape<SHSphereCollisionShape>().TestPoint(Convert::ToNative(point));
} }
bool SphereCollider::Raycast(Ray ray, float maxDistance) bool SphereCollider::Raycast(Ray ray, float maxDistance)
{ {
return getNativeCollisionShape<SHBox>().Raycast(Convert::ToNative(ray)); return getNativeCollisionShape<SHSphereCollisionShape>().Raycast(Convert::ToNative(ray));
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -231,7 +237,10 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
int Collider::CollisionShapeCount::get() int Collider::CollisionShapeCount::get()
{ {
return static_cast<int>(GetNativeComponent()->GetCollisionShapes().size()); if (const auto* shapes = GetNativeComponent()->GetCollisionShapes())
return static_cast<int>(shapes->size());
return -1;
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -311,10 +320,10 @@ namespace SHADE
// Populate the list // Populate the list
int i = 0; int i = 0;
for (const auto& collider : GetNativeComponent()->GetCollisionShapes()) for (const auto* collider : *GetNativeComponent()->GetCollisionShapes())
{ {
CollisionShape^ bound = nullptr; CollisionShape^ bound = nullptr;
switch (collider.GetType()) switch (collider->GetType())
{ {
case SHCollisionShape::Type::BOX: case SHCollisionShape::Type::BOX:
bound = gcnew BoxCollider(i, Owner.GetEntity()); bound = gcnew BoxCollider(i, Owner.GetEntity());

View File

@ -27,11 +27,11 @@ namespace SHADE
try try
{ {
auto& shape = collider->GetCollisionShape(arrayIndex); auto* shape = collider->GetCollisionShape(arrayIndex);
if (shape.GetType() != SHCollisionShape::Type::BOX) if (!shape || shape->GetType() == SHCollisionShape::Type::INVALID)
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape."); throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape.");
return reinterpret_cast<CollisionShapeType&>(shape); return dynamic_cast<CollisionShapeType&>(*shape);
} }
catch (std::invalid_argument&) catch (std::invalid_argument&)
{ {

View File

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

View File

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