Refactored the colliders?

This took me 4 days omg
This commit is contained in:
Diren D Bharwani 2022-12-09 01:15:43 +08:00
parent 38b1c46d1f
commit 74e50e10bd
45 changed files with 1934 additions and 816 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -25,13 +25,11 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
SHSphere::SHSphere() noexcept
: RelativeRadius { 1.0f }
{
type = Type::SPHERE;
}
SHSphere::SHSphere(const SHVec3& center, float radius) noexcept
: RelativeRadius { 1.0f }
{
type = Type::SPHERE;
@ -48,7 +46,6 @@ namespace SHADE
Center = rhs.Center;
Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
}
SHSphere::SHSphere(SHSphere&& rhs) noexcept
@ -57,7 +54,6 @@ namespace SHADE
Center = rhs.Center;
Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
}
/*-----------------------------------------------------------------------------------*/
@ -74,7 +70,6 @@ namespace SHADE
{
Center = rhs.Center;
Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
}
return *this;
@ -90,50 +85,11 @@ namespace SHADE
{
Center = rhs.Center;
Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
}
return *this;
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
SHVec3 SHSphere::GetCenter() const noexcept
{
return Center;
}
float SHSphere::GetWorldRadius() const noexcept
{
return Radius;
}
float SHSphere::GetRelativeRadius() const noexcept
{
return RelativeRadius;
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHSphere::SetCenter(const SHVec3& center) noexcept
{
Center = center;
}
void SHSphere::SetWorldRadius(float newWorldRadius) noexcept
{
Radius = newWorldRadius;
}
void SHSphere::SetRelativeRadius(float newRelativeRadius) noexcept
{
RelativeRadius = newRelativeRadius;
}
/*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/

View File

@ -23,7 +23,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
class SH_API SHSphere : public SHShape,
private DirectX::BoundingSphere
public DirectX::BoundingSphere
{
public:
/*---------------------------------------------------------------------------------*/
@ -32,8 +32,8 @@ namespace SHADE
SHSphere () noexcept;
SHSphere (const SHVec3& center, float radius) noexcept;
SHSphere (const SHSphere& rhs) noexcept;
SHSphere (SHSphere&& rhs) noexcept;
SHSphere (const SHSphere& rhs) noexcept;
SHSphere (SHSphere&& rhs) noexcept;
~SHSphere () override = default;
@ -44,49 +44,100 @@ namespace SHADE
SHSphere& operator= (const SHSphere& rhs) noexcept;
SHSphere& operator= (SHSphere&& rhs) noexcept;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] SHVec3 GetCenter () const noexcept;
[[nodiscard]] float GetWorldRadius () const noexcept;
[[nodiscard]] float GetRelativeRadius () const noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetCenter (const SHVec3& center) noexcept;
void SetWorldRadius (float newWorldRadius) noexcept;
void SetRelativeRadius (float newRelativeRadius) noexcept;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
/**
* @brief
* Checks if a point is inside the sphere.
* @param point
* The point to check.
* @return
* True if the point is inside the sphere.
*/
[[nodiscard]] bool TestPoint (const SHVec3& point) const noexcept override;
[[nodiscard]] SHRaycastResult Raycast(const SHRay& ray) const noexcept override;
[[nodiscard]] bool Contains (const SHSphere& rhs) const noexcept;
[[nodiscard]] float Volume () const noexcept;
[[nodiscard]] float SurfaceArea () const noexcept;
/**
* @brief
* Casts a ray against the sphere.
* @param ray
* The ray to cast.
* @return
* The result of the raycast. <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 */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] static SHSphere Combine (const SHSphere& lhs, const SHSphere& rhs) noexcept;
[[nodiscard]] static bool Intersect (const SHSphere& lhs, const SHSphere& rhs) noexcept;
[[nodiscard]] static SHSphere BuildFromSpheres (const SHSphere* spheres, size_t numSpheres) noexcept;
/**
* @brief
* Combines two spheres to form a larger sphere.
* If one sphere is completely contained by the other, the result is the larger sphere.
* @return
* The combined sphere.
*/
[[nodiscard]] static SHSphere Combine (const SHSphere& lhs, const SHSphere& rhs) noexcept;
/**
* @brief
* Checks if two spheres are intersecting.
* @return
* True if they are intersecting.
*/
[[nodiscard]] static bool Intersect (const SHSphere& lhs, const SHSphere& rhs) noexcept;
/**
* @brief
* Builds a single sphere from multiple spheres.
* @param spheres
* The set of spheres to build from.
* @param numSpheres
* The number of spheres in the set to build from.
* @return
* A sphere that contains all the spheres in the set.
*/
[[nodiscard]] static SHSphere BuildFromSpheres (const SHSphere* spheres, size_t numSpheres) noexcept;
/**
* @brief
* Builds a sphere from a set of vertices.
* @param vertices
* The vertices to build a sphere from.
* @param numVertices
* The number of vertices in the set to build from.
* @param stride
* The stride between each vertex, in the instance there is data in between each
* vertex that does not define the geometry of the object.
* @return
* A sphere that contains all the vertices in the set.
*/
[[nodiscard]] static SHSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept;
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
float RelativeRadius;
};
} // namespace SHADE

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

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
#include "SHCollisionInfo.h"
// Project Headers
#include "Physics/Collision/SHCollider.h"
#include "Physics/Interface/SHColliderComponent.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
@ -77,12 +82,14 @@ namespace SHADE
const SHCollisionShape* SHCollisionInfo::GetColliderA() const noexcept
{
return &SHComponentManager::GetComponent<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
{
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

View File

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

View File

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

View File

@ -40,7 +40,7 @@ namespace SHADE
void SHPhysicsWorld::AddRigidBody(SHRigidBody* rigidBody) noexcept
{
const bool INSERTED = rigidBodies.emplace(rigidBody->entityID, rigidBody).second;
const bool INSERTED = rigidBodies.emplace(rigidBody).second;
if (!INSERTED)
{
SHLOG_WARNING_D("Attempting to add duplicate rigid body {} to the Physics World!", rigidBody->entityID)
@ -49,15 +49,34 @@ namespace SHADE
void SHPhysicsWorld::RemoveRigidBody(SHRigidBody* rigidBody) noexcept
{
rigidBodies.erase(rigidBody->entityID);
rigidBodies.erase(rigidBody);
// Run through the rigid body's contact graph and wake all of its non-static bodies that are asleep
}
void SHPhysicsWorld::AddCollider(SHCollider* collider) noexcept
{
const bool INSERTED = colliders.emplace(collider).second;
if (!INSERTED)
{
SHLOG_WARNING_D("Attempting to add duplicate collider {} to the Physics World!", collider->entityID)
}
}
void SHPhysicsWorld::RemoveCollider(SHCollider* collider) noexcept
{
colliders.erase(collider);
// Get collider's rigid body
// Run through the rigid body's contact graph and wake all of its non-static bodies that are asleep
}
void SHPhysicsWorld::Step(float dt)
{
for (auto* rigidBody : rigidBodies | std::views::values)
for (auto* rigidBody : rigidBodies)
integrateForces(*rigidBody, dt);
for (auto* rigidBody : rigidBodies | std::views::values)
for (auto* rigidBody : rigidBodies)
integrateVelocities(*rigidBody, dt);
}

View File

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

View File

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

View File

@ -11,12 +11,18 @@
#pragma once
// Project Headers
#include "ECS_Base/SHECSMacros.h"
#include "ECS_Base/Entity/SHEntity.h"
#include "Math/Vector/SHVec3.h"
#include "SHMotionState.h"
namespace SHADE
{
/*-------------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-------------------------------------------------------------------------------------*/
class SHCollider;
/*-------------------------------------------------------------------------------------*/
/* Type Definitions */
/*-------------------------------------------------------------------------------------*/
@ -96,6 +102,8 @@ namespace SHADE
/* Setter Functions */
/*-----------------------------------------------------------------------------------*/
void SetCollider (SHCollider* c) noexcept;
/**
* @brief
* Changing the type from non-Dynamic to Dynamic will set the default
@ -174,6 +182,7 @@ namespace SHADE
// The entityID here is only meant for linking with the actual component in the engine.
EntityID entityID;
SHCollider* collider;
Type bodyType;
@ -187,7 +196,7 @@ namespace SHADE
SHVec3 linearVelocity;
SHVec3 angularVelocity;
// aZ aY aX pZ pY pX 0 0 0 0 0 autoMass enableGravity enableSleeping sleeping active
// aZ aY aX pZ pY pX 0 0 0 0 inIsland autoMass enableGravity enableSleeping sleeping active
uint16_t flags;
SHMotionState motionState;

View File

@ -26,15 +26,13 @@ namespace SHADE
SHPhysicsObject::SHPhysicsObject(const SHPhysicsObject& rhs) noexcept
: entityID { rhs.entityID }
{
// Perform a deep copy of the components
*rigidBody = *rhs.rigidBody;
deepCopyComponents(rhs.rigidBody, rhs.collider);
}
SHPhysicsObject::SHPhysicsObject(SHPhysicsObject&& rhs) noexcept
: entityID { rhs.entityID }
{
// Perform a deep copy of the components
*rigidBody = *rhs.rigidBody;
deepCopyComponents(rhs.rigidBody, rhs.collider);
}
SHPhysicsObject::~SHPhysicsObject() noexcept
@ -42,6 +40,10 @@ namespace SHADE
entityID = MAX_EID;
delete rigidBody;
rigidBody = nullptr;
delete collider;
collider = nullptr;
}
/*-----------------------------------------------------------------------------------*/
@ -53,20 +55,18 @@ namespace SHADE
if (this == &rhs)
return *this;
entityID = rhs.entityID;
entityID = rhs.entityID;
// Perform a deep copy of the components
*rigidBody = *rhs.rigidBody;
deepCopyComponents(rhs.rigidBody, rhs.collider);
return *this;
}
SHPhysicsObject& SHPhysicsObject::operator=(SHPhysicsObject&& rhs) noexcept
{
entityID = rhs.entityID;
entityID = rhs.entityID;
// Perform a deep copy of the components
*rigidBody = *rhs.rigidBody;
deepCopyComponents(rhs.rigidBody, rhs.collider);
return *this;
}
@ -77,7 +77,74 @@ namespace SHADE
bool SHPhysicsObject::IsEmpty() const noexcept
{
return rigidBody == nullptr;
return rigidBody == nullptr && collider == nullptr;
}
SHRigidBody* SHPhysicsObject::CreateRigidBody(SHRigidBody::Type bodyType)
{
if (rigidBody)
{
SHLOG_INFO_D("Rigid body for Entity {} has already been created!", entityID)
return rigidBody;
}
rigidBody = new SHRigidBody{ entityID, bodyType };
// Link with collider if it exists
if (collider)
collider->SetRigidBody(rigidBody);
return rigidBody;
}
void SHPhysicsObject::DestroyRigidBody() noexcept
{
delete rigidBody;
rigidBody = nullptr;
// Unlink with collider
if (collider)
collider->SetRigidBody(nullptr);
}
SHCollider* SHPhysicsObject::CreateCollider(const SHTransform& transform)
{
if (collider)
{
SHLOG_INFO_D("Collider for Entity {} has already been created!", entityID)
return collider;
}
collider = new SHCollider{ entityID, transform };
// Link with rigidBody if it exists
if (rigidBody)
rigidBody->SetCollider(collider);
return collider;
}
void SHPhysicsObject::DestroyCollider() noexcept
{
delete collider;
collider = nullptr;
// Unlink with rigid body
if (rigidBody)
rigidBody->SetCollider(nullptr);
}
/*-----------------------------------------------------------------------------------*/
/* Private Member Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsObject::deepCopyComponents(const SHRigidBody* rhsRigidBody, const SHCollider* rhsCollider)
{
if (rhsRigidBody)
rigidBody = new SHRigidBody{ *rhsRigidBody };
if (rhsCollider)
collider = new SHCollider { *rhsCollider };
}
} // namespace SHADE

View File

@ -11,6 +11,7 @@
#pragma once
// Project Headers
#include "Physics/Collision/SHCollider.h"
#include "Physics/Dynamics/SHRigidBody.h"
namespace SHADE
@ -32,6 +33,7 @@ namespace SHADE
EntityID entityID = MAX_EID;
SHRigidBody* rigidBody = nullptr;
SHCollider* collider = nullptr;
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor */
@ -53,6 +55,55 @@ namespace SHADE
/* Member Functions */
/*-----------------------------------------------------------------------------------*/
bool IsEmpty() const noexcept;
/**
* @brief
* Checks if the physics object has a rigid body or a collider.
* @return
* True if the physics object has neither a rigid body nor a collider.
*/
[[nodiscard]] bool IsEmpty () const noexcept;
/**
* @brief
* Creates a rigid body for this physics object.
* @param bodyType
* The rigid body's type. Can be modified after creation.
* @return
* Pointer to the rigid body that was created. The memory of this rigid body is managed
* by the physics object itself.
*/
SHRigidBody* CreateRigidBody (SHRigidBody::Type bodyType);
/**
* @brief
* Destroys the rigid body of this physics object and frees the memory.
*/
void DestroyRigidBody () noexcept;
/**
* @brief
* Creates a collider for this physics object.
* @param colliderType
* The collider's type. Should not be modified after creation.
* @param transform.
* The world transform of the collider. Defaults to the identity transform.
* @return
* Pointer to the collider that was created. The memory of this collider is managed
* by the physics object itself.
*/
SHCollider* CreateCollider (const SHTransform& transform = SHTransform::Identity);
/**
* @brief
* Destroys the collider of this physics object and frees the memory.
*/
void DestroyCollider () noexcept;
private:
/*-----------------------------------------------------------------------------------*/
/* Member Functions */
/*-----------------------------------------------------------------------------------*/
void deepCopyComponents(const SHRigidBody* rhsRigidBody, const SHCollider* rhsCollider);
};
} // namespace SHADE

View File

@ -16,8 +16,7 @@
// Project Headers
#include "Math/Transform/SHTransformComponent.h"
#include "Physics/Interface/SHColliderComponent.h"
#include "Physics/Interface/SHCollisionShape.h"
#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
#include "Physics/Interface/SHRigidBodyComponent.h"
#include "Tools/Utilities/SHUtilities.h"
namespace SHADE
@ -58,66 +57,68 @@ namespace SHADE
void SHPhysicsObjectManager::AddRigidBody(EntityID entityID) noexcept
{
SHPhysicsObject* physicsObject = nullptr;
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
if (PHYSICS_OBJECT_ITERATOR == physicsObjects.end())
physicsObject = createPhysicsObject(entityID);
else
physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
SHPhysicsObject* physicsObject = ensurePhysicsObject(entityID);
// Get the component
auto* rigidBodyComponent = SHComponentManager::GetComponent<SHRigidBodyComponent>(entityID);
// 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
, 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);
worldPos = TRANSFORM_COMPONENT->GetWorldPosition();
}
SHMotionState& motionState = rigidBody->GetMotionState();
motionState.ForcePosition(worldPos);
// Link with the component
rigidBodyComponent->SetRigidBody(physicsObject->rigidBody);
// TODO: Broadcast event
rigidBodyComponent->SetRigidBody(rigidBody);
}
void SHPhysicsObjectManager::RemoveRigidBody(EntityID entityID) noexcept
{
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
if (PHYSICS_OBJECT_ITERATOR != physicsObjects.end())
{
SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
if (PHYSICS_OBJECT_ITERATOR == physicsObjects.end())
return;
delete physicsObject->rigidBody;
physicsObject->rigidBody = nullptr;
SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
// Destroy empty physics objects
if (physicsObject->IsEmpty())
destroyPhysicsObject(entityID);
}
physicsObject->DestroyRigidBody();
// TODO: Broadcast event
// Destroy empty physics objects
if (physicsObject->IsEmpty())
destroyPhysicsObject(entityID);
}
void SHPhysicsObjectManager::AddCollider(EntityID entityID) noexcept
{
// Link with the component
SHPhysicsObject* physicsObject = ensurePhysicsObject(entityID);
// TODO: Broadcast event
// Get the component
auto* colliderComponent = SHComponentManager::GetComponent<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
@ -127,30 +128,17 @@ namespace SHADE
{
SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
physicsObject->DestroyCollider();
// Destroy empty physics objects
if (physicsObject->IsEmpty())
destroyPhysicsObject(entityID);
}
// TODO: Broadcast event
}
void SHPhysicsObjectManager::AddCollisionShape(EntityID entityID, uint8_t shapeID) noexcept
{
// Link with the component
// TODO: Broadcast event
}
void SHPhysicsObjectManager::RemoveCollisionShape(EntityID entityID, uint8_t shapeID) noexcept
{
// Unlink with the component
// TODO: Broadcast event
}
void SHPhysicsObjectManager::RemoveAllObjects() noexcept
{
// Physics objects itself will delete the object
physicsObjects.clear();
}
@ -164,6 +152,18 @@ namespace SHADE
return &NEW_OBJECT->second;
}
SHPhysicsObject* SHPhysicsObjectManager::ensurePhysicsObject(EntityID entityID)
{
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
SHPhysicsObject* physicsObject = PHYSICS_OBJECT_ITERATOR == physicsObjects.end()
? createPhysicsObject(entityID)
: &PHYSICS_OBJECT_ITERATOR->second;
return physicsObject;
}
void SHPhysicsObjectManager::destroyPhysicsObject(EntityID entityID)
{
physicsObjects.erase(entityID);

View File

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

View File

@ -25,57 +25,43 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
SHColliderComponent::SHColliderComponent() noexcept
: collider { nullptr }
{}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
const SHColliderComponent::CollisionShapes& SHColliderComponent::GetCollisionShapes() const noexcept
SHCollider* const SHColliderComponent::GetCollider() const noexcept
{
return collisionShapes;
return collider;
}
SHCollisionShape& SHColliderComponent::GetCollisionShape(int index)
const SHCollider::CollisionShapes* const SHColliderComponent::GetCollisionShapes() const noexcept
{
if (index < 0 || static_cast<size_t>(index) >= collisionShapes.size())
throw std::invalid_argument("Out-of-range access!");
if (!collider)
return nullptr;
return collisionShapes[index];
return &collider->GetCollisionShapes();
}
SHCollisionShape* const SHColliderComponent::GetCollisionShape(int index) const
{
if (!collider)
return nullptr;
return collider->GetCollisionShape(index);
}
/*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHColliderComponent::OnCreate()
void SHColliderComponent::SetCollider(SHCollider* c) noexcept
{
}
void SHColliderComponent::OnDestroy()
{
}
void SHColliderComponent::RecomputeCollisionShapes() noexcept
{
}
int SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset, const SHVec3& rotOffset) noexcept
{
return 0;
}
int SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept
{
return 0;
}
void SHColliderComponent::RemoveCollider(int index)
{
collider = c;
}
} // namespace SHADE

View File

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

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>
// External Dependencies
#include <reactphysics3d/reactphysics3d.h>
// Primary Header
#include "SHRigidBodyComponent.h"
// Project Headers
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Physics/Dynamics/SHRigidBody.h"
#include "Physics/System/SHPhysicsSystem.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/

View File

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

View File

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

View File

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

View File

@ -40,23 +40,32 @@ namespace SHADE
{
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
if (TRANSFORM_COMPONENT && TRANSFORM_COMPONENT->HasChanged())
if (physicsObject.rigidBody)
{
// Sync the objects transforms
const SHVec3 WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition();
SHMotionState& motionState = physicsObject.rigidBody->GetMotionState();
if (physicsObject.rigidBody)
{
SHMotionState& motionState = physicsObject.rigidBody->GetMotionState();
motionState.ForcePosition(TRANSFORM_COMPONENT->GetWorldPosition());
// TODO: Force Orientation
}
motionState.ForcePosition(TRANSFORM_COMPONENT->GetWorldPosition());
// TODO: Force Orientation
}
// TODO: Sync Collider Transform with World Transform
if (physicsObject.collider)
{
physicsObject.collider->SetPosition(WORLD_POS);
physicsObject.collider->SetOrientation(WORLD_ROT);
physicsObject.collider->SetScale(WORLD_SCL);
physicsObject.collider->RecomputeShapes();
}
}
}
}
} // namespace SHADE

View File

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

View File

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

View File

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

View File

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

View File

@ -107,7 +107,7 @@ namespace SHADE
try
{
auto& shape = collider->GetCollisionShape(arrayIndex);
auto& shape = *collider->GetCollisionShape(arrayIndex);
return shape;
}
catch (std::invalid_argument&)
@ -128,35 +128,39 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
Vector3 BoxCollider::Center::get()
{
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetCenter());
//return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetCenter());
return Vector3::Zero;
}
void BoxCollider::Center::set(Vector3 value)
{
getNativeCollisionShape<SHBox>().SetCenter(Convert::ToNative(value));
//getNativeCollisionShape<SHBox>().SetCenter(Convert::ToNative(value));
}
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)
{
getNativeCollisionShape<SHBox>().SetWorldExtents(Convert::ToNative(value));
//getNativeCollisionShape<SHBox>().SetWorldExtents(Convert::ToNative(value));
}
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)
{
getNativeCollisionShape<SHBox>().SetMin(Convert::ToNative(value));
//getNativeCollisionShape<SHBox>().SetMin(Convert::ToNative(value));
}
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)
{
getNativeCollisionShape<SHBox>().SetMax(Convert::ToNative(value));
//getNativeCollisionShape<SHBox>().SetMax(Convert::ToNative(value));
}
/*---------------------------------------------------------------------------------*/
@ -164,11 +168,13 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
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)
{
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()
{
return Convert::ToCLI(getNativeCollisionShape<SHSphere>().GetCenter());
return Convert::ToCLI(getNativeCollisionShape<SHSphereCollisionShape>().GetCenter());
}
void SphereCollider::Center::set(Vector3 value)
{
getNativeCollisionShape<SHSphere>().SetCenter(Convert::ToNative(value));
getNativeCollisionShape<SHSphereCollisionShape>().SetCenter(Convert::ToNative(value));
}
float SphereCollider::Radius::get()
{
return getNativeCollisionShape<SHSphere>().GetWorldRadius();
return getNativeCollisionShape<SHSphereCollisionShape>().GetWorldRadius();
}
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)
{
return getNativeCollisionShape<SHBox>().TestPoint(Convert::ToNative(point));
return getNativeCollisionShape<SHSphereCollisionShape>().TestPoint(Convert::ToNative(point));
}
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()
{
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
int i = 0;
for (const auto& collider : GetNativeComponent()->GetCollisionShapes())
for (const auto* collider : *GetNativeComponent()->GetCollisionShapes())
{
CollisionShape^ bound = nullptr;
switch (collider.GetType())
switch (collider->GetType())
{
case SHCollisionShape::Type::BOX:
bound = gcnew BoxCollider(i, Owner.GetEntity());

View File

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

View File

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

View File

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