diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index 3b277e6c..c3f95aec 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -104,8 +104,10 @@ namespace Sandbox transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber()); transform.SetWorldScale(TEST_OBJ_SCALE); - auto* box = collider.AddBoundingBox(); - box->SetHalfExtents(transform.GetWorldScale() * 0.5f); + if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN) + collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero); + else + collider.AddBoundingSphere(0.5f, SHVec3::Zero); stressTestObjects.emplace_back(entity); } diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp b/SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp index 3abcc315..d0ba2f14 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp +++ b/SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp @@ -14,6 +14,9 @@ #include "SHBoundingBox.h" // Project Headers #include "Math/SHMathHelpers.h" +#include "Math/SHRay.h" + +using namespace DirectX; namespace SHADE { @@ -21,89 +24,53 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ + SHBoundingBox::SHBoundingBox() noexcept + { + type = Type::BOX; + } + SHBoundingBox::SHBoundingBox(const SHVec3& c, const SHVec3& hE) noexcept - : SHShape {} - , center { c } - , halfExtents { hE } { - type = Type::BOUNDING_BOX; + type = Type::BOX; + + Center = c; + Extents = hE; } - SHBoundingBox::SHBoundingBox(const SHVec3* vertices, size_t numVertices) noexcept - : SHShape {} - { - type = Type::BOUNDING_BOX; - - if (vertices == nullptr || numVertices < 2) - { - SHLOG_ERROR("Insufficient number of vertices passed into bounding box constructor!") - return; - } - - SHVec3 min { std::numeric_limits::max() }; - SHVec3 max { std::numeric_limits::min() }; - - for (size_t i = 0; i < numVertices; ++i) - { - const SHVec3& v = vertices[i]; - - min.x = SHMath::Min(min.x, v.x); - min.y = SHMath::Min(min.y, v.y); - min.z = SHMath::Min(min.z, v.z); - - max.x = SHMath::Max(max.x, v.x); - max.y = SHMath::Max(max.y, v.y); - max.z = SHMath::Max(max.z, v.z); - } - - center = SHVec3::Lerp(min, max, 0.5f); - halfExtents = SHVec3::Abs((max - min) * 0.5f); - } - - SHBoundingBox::SHBoundingBox(const SHBoundingBox* boxes, size_t numBoxes) noexcept - : SHShape {} - { - type = Type::BOUNDING_BOX; - - if (boxes == nullptr || numBoxes == 0) - { - SHLOG_ERROR("Insufficient number of boxes passed into bounding box constructor!") - return; - } - - center = boxes->center; - halfExtents = boxes->halfExtents; - - for (size_t i = 1; i < numBoxes; ++i) - *this = Combine(*this, boxes[i]); - } SHBoundingBox::SHBoundingBox(const SHBoundingBox& rhs) noexcept - : SHShape {} - , center { rhs.center } - , halfExtents { rhs.halfExtents } { - type = Type::BOUNDING_BOX; + if (this == &rhs) + return; + + type = Type::BOX; + + Center = rhs.Center; + Extents = rhs.Extents; } SHBoundingBox::SHBoundingBox(SHBoundingBox&& rhs) noexcept - : SHShape {} - , center { rhs.center } - , halfExtents { rhs.halfExtents } { - type = Type::BOUNDING_BOX; + type = Type::BOX; + + Center = rhs.Center; + Extents = rhs.Extents; } + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + SHBoundingBox& SHBoundingBox::operator=(const SHBoundingBox& rhs) noexcept { - if (rhs.type != Type::BOUNDING_BOX) + if (rhs.type != Type::BOX) { SHLOG_WARNING("Cannot assign a non-bounding box to a bounding box!") } - else + else if (this != &rhs) { - center = rhs.center; - halfExtents = rhs.halfExtents; + Center = rhs.Center; + Extents = rhs.Extents; } return *this; @@ -111,14 +78,14 @@ namespace SHADE SHBoundingBox& SHBoundingBox::operator=(SHBoundingBox&& rhs) noexcept { - if (rhs.type != Type::BOUNDING_BOX) + if (rhs.type != Type::BOX) { SHLOG_WARNING("Cannot assign a non-bounding box to a bounding box!") } else { - center = rhs.center; - halfExtents = rhs.halfExtents; + Center = rhs.Center; + Extents = rhs.Extents; } return *this; @@ -128,24 +95,24 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - const SHVec3& SHBoundingBox::GetCenter() const noexcept + SHVec3 SHBoundingBox::GetCenter() const noexcept { - return center; + return Center; } - const SHVec3& SHBoundingBox::GetHalfExtents() const noexcept + SHVec3 SHBoundingBox::GetHalfExtents() const noexcept { - return halfExtents; + return Extents; } SHVec3 SHBoundingBox::GetMin() const noexcept { - return center - halfExtents; + return SHVec3{ Center.x - Extents.x, Center.y - Extents.y, Center.z - Extents.z }; } SHVec3 SHBoundingBox::GetMax() const noexcept { - return center + halfExtents; + return SHVec3{ Center.x + Extents.x, Center.y + Extents.y, Center.z + Extents.z }; } /*-----------------------------------------------------------------------------------*/ @@ -154,36 +121,42 @@ namespace SHADE void SHBoundingBox::SetCenter(const SHVec3& newCenter) noexcept { - center = newCenter; + Center = newCenter; } void SHBoundingBox::SetHalfExtents(const SHVec3& newHalfExtents) noexcept { - halfExtents = newHalfExtents; + Extents = newHalfExtents; } void SHBoundingBox::SetMin(const SHVec3& min) noexcept { - const SHVec3 MAX = center + halfExtents; + const SHVec3 MAX = GetMax(); - center = SHVec3::Lerp(min, MAX, 0.5f); - halfExtents = SHVec3::Abs((MAX - min) * 0.5f); + Center = SHVec3::Lerp(min, MAX, 0.5f); + Extents = SHVec3::Abs((MAX - min) * 0.5f); } void SHBoundingBox::SetMax(const SHVec3& max) noexcept { - const SHVec3 MIN = center - halfExtents; + const SHVec3 MIN = GetMin(); - center = SHVec3::Lerp(MIN, max, 0.5f); - halfExtents = SHVec3::Abs((max - MIN) * 0.5f); + Center = SHVec3::Lerp(MIN, max, 0.5f); + Extents = SHVec3::Abs((max - MIN) * 0.5f); } void SHBoundingBox::SetMinMax(const SHVec3& min, const SHVec3& max) noexcept { - center = SHVec3::Lerp(min, max, 0.5f); - halfExtents = SHVec3::Abs((max - min) * 0.5f); + Center = SHVec3::Lerp(min, max, 0.5f); + Extents = SHVec3::Abs((max - min) * 0.5f); } + std::vector SHBoundingBox::GetVertices() const noexcept + { + std::vector vertices{ 8 }; + GetCorners(vertices.data()); + return vertices; + } /*-----------------------------------------------------------------------------------*/ /* Public Function Member Definitions */ @@ -191,38 +164,29 @@ namespace SHADE bool SHBoundingBox::TestPoint(const SHVec3& point) noexcept { - const SHVec3 V = SHVec3::Abs(point - center); - for (size_t i = 0; i < SHVec3::SIZE; ++i) - { - if (V[i] > halfExtents[i]) - return false; - } + return BoundingBox::Contains(point); + } - return true; + bool SHBoundingBox::Raycast(const SHRay& ray, float& distance) noexcept + { + return BoundingBox::Intersects(ray.position, ray.direction, distance); } bool SHBoundingBox::Contains(const SHBoundingBox& rhs) const noexcept { - const SHVec3 V = SHVec3::Abs(rhs.center - center); - for (size_t i = 0; i < SHVec3::SIZE; ++i) - { - if (V[i] > rhs.halfExtents[i]) - return false; - } - - return true; + return BoundingBox::Contains(rhs); } float SHBoundingBox::Volume() const noexcept { - return 8.0f * (halfExtents.x * halfExtents.y * halfExtents.z); + return 8.0f * (Extents.x * Extents.y * Extents.z); } float SHBoundingBox::SurfaceArea() const noexcept { - return 8.0f * ((halfExtents.x * halfExtents.y) - + (halfExtents.x * halfExtents.z) - + (halfExtents.y * halfExtents.z)); + return 8.0f * ((Extents.x * Extents.y) + + (Extents.x * Extents.z) + + (Extents.y * Extents.z)); } /*-----------------------------------------------------------------------------------*/ @@ -231,37 +195,31 @@ namespace SHADE SHBoundingBox SHBoundingBox::Combine(const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept { - if (lhs.Contains(rhs)) - return lhs; - - if (rhs.Contains(lhs)) - return rhs; - - const SHVec3 LHS_MIN = lhs.GetMin(); - const SHVec3 LHS_MAX = lhs.GetMax(); - const SHVec3 RHS_MIN = rhs.GetMin(); - const SHVec3 RHS_MAX = rhs.GetMax(); - - SHVec3 min = SHVec3::Min({ LHS_MIN, RHS_MIN }); - SHVec3 max = SHVec3::Max({ LHS_MAX, RHS_MAX }); - - SHBoundingBox result{ lhs }; - result.SetMinMax(min, max); + SHBoundingBox result; + CreateMerged(result, lhs, rhs); return result; } bool SHBoundingBox::Intersect(const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept { - const SHVec3 V = SHVec3::Abs(lhs.center - rhs.center); - const SHVec3 D = lhs.halfExtents + rhs.halfExtents; + return lhs.Intersects(rhs); + } - for (size_t i = 0; i < SHVec3::SIZE; ++i) - { - if (V[i] > D[i]) - return false; - } + SHBoundingBox SHBoundingBox::BuildFromBoxes(const SHBoundingBox* boxes, size_t numBoxes) noexcept + { + SHBoundingBox result; - return true; + for (size_t i = 1; i < numBoxes; ++i) + CreateMerged(result, boxes[i - 1], boxes[i]); + + return result; + } + + SHBoundingBox SHBoundingBox::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept + { + SHBoundingBox result; + CreateFromPoints(result, numVertices, vertices, stride); + return result; } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.h b/SHADE_Engine/src/Math/Geometry/SHBoundingBox.h index a89c5965..5b3d26d5 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.h +++ b/SHADE_Engine/src/Math/Geometry/SHBoundingBox.h @@ -22,32 +22,43 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - // TODO(Diren): Use DirectX BoundingBox instead of custom - class SH_API SHBoundingBox : public SHShape + class SH_API SHBoundingBox : public SHShape, + private DirectX::BoundingBox { public: + /*---------------------------------------------------------------------------------*/ + /* Static Data Members */ + /*---------------------------------------------------------------------------------*/ + + static constexpr size_t NUM_VERTICES = 8; + /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHBoundingBox (const SHVec3& center, const SHVec3& halfExtents) noexcept; - SHBoundingBox (const SHVec3* vertices, size_t numVertices) noexcept; - SHBoundingBox (const SHBoundingBox* boxes, size_t numBoxes) noexcept; + ~SHBoundingBox () override = default; - SHBoundingBox (const SHBoundingBox& rhs) noexcept; - SHBoundingBox (SHBoundingBox&& rhs) noexcept; + SHBoundingBox () noexcept; + SHBoundingBox (const SHVec3& center, const SHVec3& halfExtents) noexcept; + SHBoundingBox (const SHBoundingBox& rhs) noexcept; + SHBoundingBox (SHBoundingBox&& rhs) noexcept; - SHBoundingBox& operator= (const SHBoundingBox& rhs) noexcept; - SHBoundingBox& operator= (SHBoundingBox&& rhs) noexcept; + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHBoundingBox& operator= (const SHBoundingBox& rhs) noexcept; + SHBoundingBox& operator= (SHBoundingBox&& rhs) noexcept; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] const SHVec3& GetCenter () const noexcept; - [[nodiscard]] const SHVec3& GetHalfExtents () const noexcept; - [[nodiscard]] SHVec3 GetMin () const noexcept; - [[nodiscard]] SHVec3 GetMax () const noexcept; + [[nodiscard]] SHVec3 GetCenter () const noexcept; + [[nodiscard]] SHVec3 GetHalfExtents() const noexcept; + [[nodiscard]] SHVec3 GetMin () const noexcept; + [[nodiscard]] SHVec3 GetMax () const noexcept; + [[nodiscard]] std::vector GetVertices () const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ @@ -59,31 +70,25 @@ namespace SHADE void SetMax (const SHVec3& max) noexcept; void SetMinMax (const SHVec3& min, const SHVec3& max) noexcept; - /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] bool TestPoint (const SHVec3& point) noexcept override; + [[nodiscard]] bool TestPoint (const SHVec3& point) noexcept override; + [[nodiscard]] bool Raycast (const SHRay& ray, float& distance) noexcept override; - [[nodiscard]] bool Contains (const SHBoundingBox& rhs) const noexcept; - [[nodiscard]] float Volume () const noexcept; - [[nodiscard]] float SurfaceArea () const noexcept; + [[nodiscard]] bool Contains (const SHBoundingBox& rhs) const noexcept; + [[nodiscard]] float Volume () const noexcept; + [[nodiscard]] float SurfaceArea () const noexcept; /*---------------------------------------------------------------------------------*/ /* Static Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] static SHBoundingBox Combine (const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept; - [[nodiscard]] static bool Intersect (const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept; - - private: - /*---------------------------------------------------------------------------------*/ - /* Data Members */ - /*---------------------------------------------------------------------------------*/ - - SHVec3 center; - SHVec3 halfExtents; + [[nodiscard]] static SHBoundingBox Combine (const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept; + [[nodiscard]] static bool Intersect (const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept; + [[nodiscard]] static SHBoundingBox BuildFromBoxes (const SHBoundingBox* boxes, size_t numBoxes) noexcept; + [[nodiscard]] static SHBoundingBox BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; }; diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp b/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp new file mode 100644 index 00000000..62bf12b2 --- /dev/null +++ b/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp @@ -0,0 +1,183 @@ +/**************************************************************************************** + * \file SHBoundingSphere.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Bounding Sphere + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#include + +// Primary Header +#include "SHBoundingSphere.h" +// Project Headers +#include "Math/SHMathHelpers.h" +#include "Math/SHRay.h" + +using namespace DirectX; + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHBoundingSphere::SHBoundingSphere() noexcept + { + type = Type::SPHERE; + } + + SHBoundingSphere::SHBoundingSphere(const SHVec3& center, float radius) noexcept + { + type = Type::SPHERE; + + Center = center; + Radius = radius; + } + + SHBoundingSphere::SHBoundingSphere(const SHBoundingSphere& rhs) noexcept + { + if (this == &rhs) + return; + + type = Type::SPHERE; + + Center = rhs.Center; + Radius = rhs.Radius; + } + + SHBoundingSphere::SHBoundingSphere(SHBoundingSphere&& rhs) noexcept + { + type = Type::SPHERE; + + Center = rhs.Center; + Radius = rhs.Radius; + } + + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHBoundingSphere& SHBoundingSphere::operator=(const SHBoundingSphere& rhs) noexcept + { + if (rhs.type != Type::SPHERE) + { + SHLOG_WARNING("Cannot assign a non-sphere to a sphere!") + } + else if (this != &rhs) + { + Center = rhs.Center; + Radius = rhs.Radius; + } + + return *this; + } + + SHBoundingSphere& SHBoundingSphere::operator=(SHBoundingSphere&& rhs) noexcept + { + if (rhs.type != Type::SPHERE) + { + SHLOG_WARNING("Cannot assign a non-sphere to a sphere!") + } + else + { + Center = rhs.Center; + Radius = rhs.Radius; + } + + return *this; + } + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHVec3 SHBoundingSphere::GetCenter() const noexcept + { + return Center; + } + + float SHBoundingSphere::GetRadius() const noexcept + { + return Radius; + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHBoundingSphere::SetCenter(const SHVec3& center) noexcept + { + Center = center; + } + + void SHBoundingSphere::SetRadius(float radius) noexcept + { + Radius = radius; + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + bool SHBoundingSphere::TestPoint(const SHVec3& point) noexcept + { + return BoundingSphere::Contains(point); + } + + bool SHBoundingSphere::Raycast(const SHRay& ray, float& distance) noexcept + { + return Intersects(ray.position, ray.direction, distance); + } + + bool SHBoundingSphere::Contains(const SHBoundingSphere& rhs) const noexcept + { + return BoundingSphere::Contains(rhs); + } + + float SHBoundingSphere::Volume() const noexcept + { + return (4.0f / 3.0f) * SHMath::PI * (Radius * Radius * Radius); + } + + float SHBoundingSphere::SurfaceArea() const noexcept + { + return 4.0f * SHMath::PI * (Radius * Radius); + } + + /*-----------------------------------------------------------------------------------*/ + /* Static Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHBoundingSphere SHBoundingSphere::Combine(const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept + { + SHBoundingSphere result; + CreateMerged(result, lhs, rhs); + return result; + } + + bool SHBoundingSphere::Intersect(const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept + { + return lhs.Intersects(rhs); + } + + SHBoundingSphere SHBoundingSphere::BuildFromSpheres(const SHBoundingSphere* spheres, size_t numSpheres) noexcept + { + SHBoundingSphere result; + + for (size_t i = 1; i < numSpheres; ++i) + CreateMerged(result, spheres[i - 1], spheres[i]); + + return result; + } + + SHBoundingSphere SHBoundingSphere::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept + { + SHBoundingSphere result; + CreateFromPoints(result, numVertices, vertices, stride); + return result; + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h b/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h new file mode 100644 index 00000000..001e889b --- /dev/null +++ b/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h @@ -0,0 +1,83 @@ +/**************************************************************************************** + * \file SHBoundingSphere.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Bounding Sphere. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#pragma once + +#include + +// Project Headers +#include "SHShape.h" +#include "SH_API.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + class SH_API SHBoundingSphere : public SHShape, + private DirectX::BoundingSphere + { + public: + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHBoundingSphere () noexcept; + SHBoundingSphere (const SHVec3& center, float radius) noexcept; + SHBoundingSphere (const SHBoundingSphere& rhs) noexcept; + SHBoundingSphere (SHBoundingSphere&& rhs) noexcept; + + ~SHBoundingSphere () override = default; + + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHBoundingSphere& operator= (const SHBoundingSphere& rhs) noexcept; + SHBoundingSphere& operator= (SHBoundingSphere&& rhs) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Getter Functions */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] SHVec3 GetCenter () const noexcept; + [[nodiscard]] float GetRadius () const noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*---------------------------------------------------------------------------------*/ + + void SetCenter (const SHVec3& center) noexcept; + void SetRadius (float radius) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] bool TestPoint (const SHVec3& point) noexcept override; + [[nodiscard]] bool Raycast (const SHRay& ray, float& distance) noexcept override; + + [[nodiscard]] bool Contains (const SHBoundingSphere& rhs) const noexcept; + [[nodiscard]] float Volume () const noexcept; + [[nodiscard]] float SurfaceArea () const noexcept; + + + /*---------------------------------------------------------------------------------*/ + /* Static Function Members */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] static SHBoundingSphere Combine (const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept; + [[nodiscard]] static bool Intersect (const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept; + [[nodiscard]] static SHBoundingSphere BuildFromSpheres (const SHBoundingSphere* spheres, size_t numSpheres) noexcept; + [[nodiscard]] static SHBoundingSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; + + }; +} // namespace SHADE diff --git a/SHADE_Engine/src/Math/Geometry/SHShape.h b/SHADE_Engine/src/Math/Geometry/SHShape.h index e33ca583..18f54fe6 100644 --- a/SHADE_Engine/src/Math/Geometry/SHShape.h +++ b/SHADE_Engine/src/Math/Geometry/SHShape.h @@ -11,8 +11,9 @@ #pragma once // Project Headers -#include "Math/Transform/SHTransform.h" #include "SH_API.h" +#include "Math/SHRay.h" + namespace SHADE { @@ -29,11 +30,10 @@ namespace SHADE enum class Type { - BOUNDING_BOX + BOX , SPHERE , CAPSULE , CONVEX_HULL - , TRIANGLE , COUNT , NONE = -1 @@ -69,7 +69,8 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] virtual bool TestPoint (const SHVec3& point) noexcept = 0; + [[nodiscard]] virtual bool TestPoint (const SHVec3& point) noexcept = 0; + [[nodiscard]] virtual bool Raycast (const SHRay& ray, float& distance) noexcept = 0; protected: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/SHColour.cpp b/SHADE_Engine/src/Math/SHColour.cpp new file mode 100644 index 00000000..8aae2cb3 --- /dev/null +++ b/SHADE_Engine/src/Math/SHColour.cpp @@ -0,0 +1,297 @@ +/**************************************************************************************** + * \file SHColour.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Colour. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#include + + +#include + +// Primary Header +#include "SHColour.h" +// Project Headers +#include "SHMathHelpers.h" + +using namespace DirectX; + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Static Data Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + const SHColour SHColour::BEIGE = DirectX::Colors::Beige; + const SHColour SHColour::BLACK = DirectX::Colors::Black; + const SHColour SHColour::BLUE = DirectX::Colors::Blue; + const SHColour SHColour::BROWN = DirectX::Colors::Brown; + const SHColour SHColour::CHOCOLATE = DirectX::Colors::Chocolate; + const SHColour SHColour::CORAL = DirectX::Colors::Coral; + const SHColour SHColour::CRIMSON = DirectX::Colors::Crimson; + const SHColour SHColour::CYAN = DirectX::Colors::Cyan; + const SHColour SHColour::DARKBLUE = DirectX::Colors::DarkBlue; + const SHColour SHColour::DARKGRAY = DirectX::Colors::DarkGray; + const SHColour SHColour::DARKGREEN = DirectX::Colors::DarkGreen; + const SHColour SHColour::DARKMAGENTA = DirectX::Colors::DarkMagenta; + const SHColour SHColour::DARKORANGE = DirectX::Colors::DarkOrange; + const SHColour SHColour::DARKRED = DirectX::Colors::DarkRed; + const SHColour SHColour::DEEPPINK = DirectX::Colors::DeepPink; + const SHColour SHColour::FORESTGREEN = DirectX::Colors::ForestGreen; + const SHColour SHColour::FUCHSIA = DirectX::Colors::Fuchsia; + const SHColour SHColour::GOLD = DirectX::Colors::Gold; + const SHColour SHColour::GRAY = DirectX::Colors::Gray; + const SHColour SHColour::GREEN = DirectX::Colors::Green; + const SHColour SHColour::HOTPINK = DirectX::Colors::HotPink; + const SHColour SHColour::INDIGO = DirectX::Colors::Indigo; + const SHColour SHColour::LAVENDER = DirectX::Colors::Lavender; + const SHColour SHColour::LIGHTBLUE = DirectX::Colors::LightBlue; + const SHColour SHColour::LIGHTGRAY = DirectX::Colors::LightGray; + const SHColour SHColour::LIGHTGREEN = DirectX::Colors::LightGreen; + const SHColour SHColour::LIGHTPINK = DirectX::Colors::LightPink; + const SHColour SHColour::LIGHTYELLOW = DirectX::Colors::LightYellow; + const SHColour SHColour::LIME = DirectX::Colors::Lime; + const SHColour SHColour::LIMEGREEN = DirectX::Colors::LimeGreen; + const SHColour SHColour::MAGENTA = DirectX::Colors::Magenta; + const SHColour SHColour::MAROON = DirectX::Colors::Maroon; + const SHColour SHColour::MEDIUMBLUE = DirectX::Colors::MediumBlue; + const SHColour SHColour::MEDIUMPURPLE = DirectX::Colors::MediumPurple; + const SHColour SHColour::NAVY = DirectX::Colors::Navy; + const SHColour SHColour::OLIVE = DirectX::Colors::Olive; + const SHColour SHColour::ORANGE = DirectX::Colors::Orange; + const SHColour SHColour::ORCHID = DirectX::Colors::Orchid; + const SHColour SHColour::PINK = DirectX::Colors::Pink; + const SHColour SHColour::PURPLE = DirectX::Colors::Purple; + const SHColour SHColour::RED = DirectX::Colors::Red; + const SHColour SHColour::ROYALBLUE = DirectX::Colors::RoyalBlue; + const SHColour SHColour::SALMON = DirectX::Colors::Salmon; + const SHColour SHColour::SANDYBROWN = DirectX::Colors::SandyBrown; + const SHColour SHColour::SILVER = DirectX::Colors::Silver; + const SHColour SHColour::SKYBLUE = DirectX::Colors::SkyBlue; + const SHColour SHColour::SLATEGRAY = DirectX::Colors::SlateGray; + const SHColour SHColour::SNOW = DirectX::Colors::Snow; + const SHColour SHColour::STEELBLUE = DirectX::Colors::SteelBlue; + const SHColour SHColour::TAN = DirectX::Colors::Tan; + const SHColour SHColour::TEAL = DirectX::Colors::Teal; + const SHColour SHColour::TURQUOISE = DirectX::Colors::Turquoise; + const SHColour SHColour::VIOLET = DirectX::Colors::Violet; + const SHColour SHColour::WHITE = DirectX::Colors::White; + const SHColour SHColour::YELLOW = DirectX::Colors::Yellow; + + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHColour::SHColour() noexcept + : SHVec4 { 0.0f, 0.0f, 0.0f, 1.0f } + {} + + SHColour::SHColour(float r, float g, float b) noexcept + : SHVec4 { r, g, b, 1.0f } + {} + + SHColour::SHColour(float r, float g, float b, float a) noexcept + : SHVec4 { r, g, b, a } + {} + + SHColour::SHColour(uint8_t r, uint8_t g, uint8_t b) noexcept + : SHVec4 + { + static_cast(r) / 255.0f, + static_cast(g) / 255.0f, + static_cast(b) / 255.0f, + 1.0f + } + {} + + SHColour::SHColour(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept + : SHVec4 + { + static_cast(r) / 255.0f, + static_cast(g) / 255.0f, + static_cast(b) / 255.0f, + static_cast(a) / 255.0f + } + {} + + SHColour::SHColour(const DirectX::XMFLOAT3& colour) noexcept + : SHVec4 { colour.x, colour.y, colour.z, 1.0f } + {} + + SHColour::SHColour(const DirectX::XMVECTORF32& colour) noexcept + : SHVec4 + { + XMVectorGetX(colour), + XMVectorGetY(colour), + XMVectorGetZ(colour), + XMVectorGetW(colour) + } + {} + + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + + bool SHColour::operator==(const SHColour& rhs) const noexcept + { + return XMColorEqual(*this, rhs); + } + + bool SHColour::operator!=(const SHColour& rhs) const noexcept + { + return XMColorNotEqual(*this, rhs); + } + + /*-----------------------------------------------------------------------------------*/ + /* Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHColourHSV SHColour::ToHSV() noexcept + { + SHColourHSV hsv; + + const float MIN = SHMath::Min({ x, y, z }); + const float MAX = SHMath::Max({ x, y, z }); + + hsv.v = MAX; + + const float DELTA = MAX - MIN; + hsv.s = (MAX != 0.0f) ? DELTA / MAX : 0.0f; + + static const float SIN_60 = sin(SHMath::DegreesToRadians(60.0f)); + + if (DELTA == 0.0f) + hsv.h = 0.0f; + else if (x == MAX) + hsv.h = (y - z) / DELTA; + else if (y == MAX) + hsv.h = 2.0f + (z - x) / DELTA; + else + hsv.h = 4.0f + (x - y) / DELTA; + + hsv.h *= 60; + if (hsv.h < 0.0f) + hsv.h += 360.f; + + return hsv; + } + + void SHColour::Negate() noexcept + { + XMStoreFloat4(this, XMColorNegative(*this)); + } + + void SHColour::Saturate() noexcept + { + XMStoreFloat4(this, XMVectorSaturate(*this)); + } + + void SHColour::AdjustSaturation(float saturation) noexcept + { + XMStoreFloat4(this, XMColorAdjustSaturation(*this, saturation)); + } + + void SHColour::AdjustContrast(float contrast) noexcept + { + XMStoreFloat4(this, XMColorAdjustContrast(*this, contrast)); + } + + /*-----------------------------------------------------------------------------------*/ + /* Static Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHColour SHColour::Modulate(const SHColour& lhs, const SHColour& rhs) noexcept + { + SHColour result; + XMStoreFloat4(&result, XMColorModulate(lhs, rhs)); + return result; + } + + SHColour SHColour::FromHSV(float hue, float saturation, float value) + { + if (hue < 0.0f || saturation < 0.0f || value < 0.0f) + throw std::invalid_argument("One or more of the hsv values are invalid!"); + + SHColour colour; + + if (saturation == 0.0f) + { + colour.x = colour.y = colour.z = value; + } + else + { + hue /= 60.0f; + + const int SECTOR = static_cast(hue); + + const float F = hue - static_cast(SECTOR); + const float P = value * (1.0f - saturation); + const float Q = value * (1.0f - saturation * F); + const float T = value * (1.0f - saturation * (1.0f - F)); + + switch (SECTOR) + { + case 0: + { + colour.x = value; + colour.y = T; + colour.z = P; + + break; + } + case 1: + { + colour.x = Q; + colour.y = value; + colour.z = P; + + break; + } + case 2: + { + colour.x = P; + colour.y = value; + colour.z = T; + + break; + } + case 3: + { + colour.x = P; + colour.y = Q; + colour.z = value; + + break; + } + case 4: + { + colour.x = T; + colour.y = P; + colour.z = value; + + break; + } + default: + { + colour.x = value; + colour.y = P; + colour.z = Q; + + break; + } + } + } + + return colour; + } + + SHColour SHColour::FromHSV(const SHColourHSV& hsv) + { + return FromHSV(hsv.h, hsv.s, hsv.v); + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/SHColour.h b/SHADE_Engine/src/Math/SHColour.h new file mode 100644 index 00000000..bd2bc9e7 --- /dev/null +++ b/SHADE_Engine/src/Math/SHColour.h @@ -0,0 +1,166 @@ +/**************************************************************************************** + * \file SHColour.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Colour. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#pragma once + +#include + +// Project Headers +#include "SH_API.h" +#include "Vector/SHVec3.h" +#include "Vector/SHVec4.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-----------------------------------------------------------------------------------*/ + + class SHColour; + + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + struct SH_API SHColourHSV + { + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + float h = 0.0f; + float s = 0.0f; + float v = 0.0f; + }; + + class SH_API SHColour : private SHVec4 + { + public: + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHColour () noexcept; + SHColour (float r, float g, float b) noexcept; + SHColour (float r, float g, float b, float a) noexcept; + SHColour (uint8_t r, uint8_t g, uint8_t b) noexcept; + SHColour (uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept; + + SHColour (const SHVec3& colour) noexcept; + SHColour (const DirectX::XMFLOAT3& colour) noexcept; + SHColour (const DirectX::XMVECTORF32& colour) noexcept; + + SHColour (const SHColour&) = default; + SHColour (SHColour&&) = default; + + ~SHColour () = default; + + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHColour& operator= (const SHColour&) = default; + SHColour& operator= (SHColour&&) = default; + + bool operator== (const SHColour& rhs) const noexcept; + bool operator!= (const SHColour& rhs) const noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Properties */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] inline float& r() noexcept { return x; } + [[nodiscard]] inline float& g() noexcept { return y; } + [[nodiscard]] inline float& b() noexcept { return z; } + [[nodiscard]] inline float& a() noexcept { return w; } + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + SHColourHSV ToHSV () noexcept; + + void Negate () noexcept; + void Saturate () noexcept; + + void AdjustSaturation (float saturation) noexcept; + void AdjustContrast (float contrast) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Static Function Members */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] static SHColour Modulate (const SHColour& lhs, const SHColour& rhs) noexcept; + [[nodiscard]] static SHColour FromHSV (float hue, float saturation, float value); + [[nodiscard]] static SHColour FromHSV (const SHColourHSV& hsv); + + /*---------------------------------------------------------------------------------*/ + /* Static Data Members */ + /*---------------------------------------------------------------------------------*/ + + static const SHColour BEIGE ; + static const SHColour BLACK ; + static const SHColour BLUE ; + static const SHColour BROWN ; + static const SHColour CHOCOLATE ; + static const SHColour CORAL ; + static const SHColour CRIMSON ; + static const SHColour CYAN ; + static const SHColour DARKBLUE ; + static const SHColour DARKGRAY ; + static const SHColour DARKGREEN ; + static const SHColour DARKMAGENTA ; + static const SHColour DARKORANGE ; + static const SHColour DARKRED ; + static const SHColour DEEPPINK ; + static const SHColour FORESTGREEN ; + static const SHColour FUCHSIA ; + static const SHColour GOLD ; + static const SHColour GRAY ; + static const SHColour GREEN ; + static const SHColour HOTPINK ; + static const SHColour INDIGO ; + static const SHColour LAVENDER ; + static const SHColour LIGHTBLUE ; + static const SHColour LIGHTGRAY ; + static const SHColour LIGHTGREEN ; + static const SHColour LIGHTPINK ; + static const SHColour LIGHTYELLOW ; + static const SHColour LIME ; + static const SHColour LIMEGREEN ; + static const SHColour MAGENTA ; + static const SHColour MAROON ; + static const SHColour MEDIUMBLUE ; + static const SHColour MEDIUMPURPLE; + static const SHColour NAVY ; + static const SHColour OLIVE ; + static const SHColour ORANGE ; + static const SHColour ORCHID ; + static const SHColour PINK ; + static const SHColour PURPLE ; + static const SHColour RED ; + static const SHColour ROYALBLUE ; + static const SHColour SALMON ; + static const SHColour SANDYBROWN ; + static const SHColour SILVER ; + static const SHColour SKYBLUE ; + static const SHColour SLATEGRAY ; + static const SHColour SNOW ; + static const SHColour STEELBLUE ; + static const SHColour TAN ; + static const SHColour TEAL ; + static const SHColour TURQUOISE ; + static const SHColour VIOLET ; + static const SHColour WHITE ; + static const SHColour YELLOW; + }; + + +} // namespace SHADE diff --git a/SHADE_Engine/src/Math/SHMatrix.cpp b/SHADE_Engine/src/Math/SHMatrix.cpp index 94c17914..571fa4e0 100644 --- a/SHADE_Engine/src/Math/SHMatrix.cpp +++ b/SHADE_Engine/src/Math/SHMatrix.cpp @@ -334,6 +334,39 @@ namespace SHADE return ss.str(); } + bool SHMatrix::Decompose(SHVec3& translation, SHVec3& rotation, SHVec3& scale) const noexcept + { + XMVECTOR s, r, t; + const XMMATRIX M = XMLoadFloat4x4(this); + + if (!XMMatrixDecompose(&s, &r, &t, M)) + return false; + + SHQuaternion orientation; + + XMStoreFloat3(&scale, s); + XMStoreFloat4(&orientation, r); + XMStoreFloat3(&translation, t); + + rotation = orientation.ToEuler(); + + return true; + } + + bool SHMatrix::Decompose(SHVec3& translation, SHQuaternion& orientation, SHVec3& scale) const noexcept + { + XMVECTOR s, r, t; + const XMMATRIX M = XMLoadFloat4x4(this); + + if (!XMMatrixDecompose(&s, &r, &t, M)) + return false; + + XMStoreFloat3(&scale, s); + XMStoreFloat4(&orientation, r); + XMStoreFloat3(&translation, t); + + return true; + } /*-----------------------------------------------------------------------------------*/ /* Static Function Member Definitions */ diff --git a/SHADE_Engine/src/Math/SHMatrix.h b/SHADE_Engine/src/Math/SHMatrix.h index 3666fbe6..7a662478 100644 --- a/SHADE_Engine/src/Math/SHMatrix.h +++ b/SHADE_Engine/src/Math/SHMatrix.h @@ -16,7 +16,6 @@ // Project Headers #include "SH_API.h" #include "Vector/SHVec4.h" -#include "SH_API.h" namespace SHADE { @@ -25,7 +24,6 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ class SHVec2; class SHVec3; - class SHVec4; class SHQuaternion; /*-----------------------------------------------------------------------------------*/ @@ -109,6 +107,24 @@ namespace SHADE [[nodiscard]] float Determinant () const noexcept; [[nodiscard]] std::string ToString () const noexcept; + /** + * @brief Decomposes a transformation matrix into translation, euler angles and scale. + * @param[out] scale The scaling factor of the matrix. + * @param[out] rotation The euler angles of the matrix. + * @param[out] translation The translation of the matrix. + * @return True if decomposition was successful. + */ + bool Decompose (SHVec3& translation, SHVec3& rotation, SHVec3& scale) const noexcept; + + /** + * @brief Decomposes a transformation matrix into translation, orientation and scale. + * @param[out] scale The scaling factor of the matrix. + * @param[out] orientation The orientation of the matrix. + * @param[out] translation The translation of the matrix. + * @return True if decomposition was successful. + */ + bool Decompose (SHVec3& translation, SHQuaternion& orientation, SHVec3& scale) const noexcept; + /*---------------------------------------------------------------------------------*/ /* Static Function Members */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/SHQuaternion.cpp b/SHADE_Engine/src/Math/SHQuaternion.cpp index a6428d30..33c568a5 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.cpp +++ b/SHADE_Engine/src/Math/SHQuaternion.cpp @@ -67,6 +67,19 @@ namespace SHADE XMStoreFloat4(this, XMQuaternionRotationMatrix(M)); } + SHQuaternion::SHQuaternion(const reactphysics3d::Vector3& rp3dEuler) noexcept + : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) + { + const SHVec3& SHADE_VEC{ rp3dEuler }; + + const XMVECTOR V = XMLoadFloat3(&SHADE_VEC); + XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(V)); + } + + SHQuaternion::SHQuaternion(const reactphysics3d::Quaternion& rp3dQuat) noexcept + : XMFLOAT4( rp3dQuat.x, rp3dQuat.y, rp3dQuat.z, rp3dQuat.w ) + {} + /*-----------------------------------------------------------------------------------*/ /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -176,6 +189,16 @@ namespace SHADE return XMQuaternionNotEqual(Q1, Q2); } + SHQuaternion::operator reactphysics3d::Quaternion() const noexcept + { + return reactphysics3d::Quaternion{ x, y, z, w }; + } + + SHQuaternion::operator reactphysics3d::Vector3() const noexcept + { + return reactphysics3d::Vector3{ ToEuler() }; + } + SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept { return rhs * lhs; diff --git a/SHADE_Engine/src/Math/SHQuaternion.h b/SHADE_Engine/src/Math/SHQuaternion.h index 61b55ef9..c94907b5 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.h +++ b/SHADE_Engine/src/Math/SHQuaternion.h @@ -11,6 +11,8 @@ #pragma once #include +#include + #include // Project Headers @@ -46,12 +48,17 @@ namespace SHADE SHQuaternion (const SHQuaternion& rhs) = default; SHQuaternion (SHQuaternion&& rhs) = default; - SHQuaternion () noexcept; - SHQuaternion (float x, float y, float z, float w) noexcept; - SHQuaternion (float yaw, float pitch, float roll) noexcept; - SHQuaternion (const SHVec3& eulerAngles) noexcept; - SHQuaternion (const SHVec3& axis, float angleInRad) noexcept; - SHQuaternion (const SHMatrix& rotationMatrix) noexcept; + SHQuaternion () noexcept; + SHQuaternion (float x, float y, float z, float w) noexcept; + SHQuaternion (float yaw, float pitch, float roll) noexcept; + SHQuaternion (const SHVec3& eulerAngles) noexcept; + SHQuaternion (const SHVec3& axis, float angleInRad) noexcept; + SHQuaternion (const SHMatrix& rotationMatrix) noexcept; + + // Conversion from other math types + + SHQuaternion (const reactphysics3d::Vector3& rp3dEuler) noexcept; + SHQuaternion (const reactphysics3d::Quaternion& rp3dQuat) noexcept; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ @@ -76,6 +83,11 @@ namespace SHADE [[nodiscard]] bool operator== (const SHQuaternion& rhs) const noexcept; [[nodiscard]] bool operator!= (const SHQuaternion& rhs) const noexcept; + // Conversion to other math types used by SHADE + + operator reactphysics3d::Quaternion () const noexcept; + operator reactphysics3d::Vector3 () const noexcept; + /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/SHRay.cpp b/SHADE_Engine/src/Math/SHRay.cpp new file mode 100644 index 00000000..87f12b81 --- /dev/null +++ b/SHADE_Engine/src/Math/SHRay.cpp @@ -0,0 +1,60 @@ +/**************************************************************************************** + * \file SHRay.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Ray. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#include + +// Primary Header +#include "SHRay.h" + +using namespace DirectX; + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHRay::SHRay() noexcept + : direction { 0.0f, 0.0f, 1.0f } + {} + + SHRay::SHRay(const SHVec3& pos, const SHVec3& dir) noexcept + : position { pos } + , direction { dir } + {} + + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + + bool SHRay::operator==(const SHRay& rhs) noexcept + { + const XMVECTOR LHS_POS = XMLoadFloat3(&position); + const XMVECTOR RHS_POS = XMLoadFloat3(&rhs.position); + + const XMVECTOR LHS_DIR = XMLoadFloat3(&direction); + const XMVECTOR RHS_DIR = XMLoadFloat3(&rhs.direction); + + return XMVector3Equal(LHS_POS, RHS_POS) && XMVector3NotEqual(LHS_DIR, RHS_DIR); + } + + bool SHRay::operator!=(const SHRay& rhs) noexcept + { + const XMVECTOR LHS_POS = XMLoadFloat3(&position); + const XMVECTOR RHS_POS = XMLoadFloat3(&rhs.position); + + const XMVECTOR LHS_DIR = XMLoadFloat3(&direction); + const XMVECTOR RHS_DIR = XMLoadFloat3(&rhs.direction); + + return XMVector3NotEqual(LHS_POS, RHS_POS) || XMVector3NotEqual(LHS_DIR, RHS_DIR); + } + + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/SHRay.h b/SHADE_Engine/src/Math/SHRay.h new file mode 100644 index 00000000..29d55b16 --- /dev/null +++ b/SHADE_Engine/src/Math/SHRay.h @@ -0,0 +1,54 @@ +/**************************************************************************************** + * \file SHRay.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Ray. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#pragma once + +#include + +// Project Headers +#include "SH_API.h" +#include "Vector/SHVec3.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + struct SH_API SHRay + { + public: + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + SHVec3 position; + SHVec3 direction; + + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHRay() noexcept; + SHRay(const SHVec3& pos, const SHVec3& dir) noexcept; + SHRay(const SHRay& rhs) noexcept = default; + SHRay(SHRay&& rhs) noexcept = default; + + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHRay& operator= (const SHRay& rhs) noexcept = default; + SHRay& operator= (SHRay&& rhs) noexcept = default; + + [[nodiscard]] bool operator==(const SHRay& rhs) noexcept; + [[nodiscard]] bool operator!=(const SHRay& rhs) noexcept; + }; +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Vector/SHVec2.cpp b/SHADE_Engine/src/Math/Vector/SHVec2.cpp index 545492cb..195a8b14 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec2.cpp +++ b/SHADE_Engine/src/Math/Vector/SHVec2.cpp @@ -38,6 +38,10 @@ namespace SHADE : XMFLOAT2( 0.0f, 0.0f ) {} + SHVec2::SHVec2(const XMFLOAT2& xmfloat2) noexcept + : XMFLOAT2 ( xmfloat2.x, xmfloat2.y ) + {} + SHVec2::SHVec2(float n) noexcept : XMFLOAT2( n, n ) {} @@ -46,10 +50,19 @@ namespace SHADE : XMFLOAT2( _x, _y ) {} + SHVec2::SHVec2(const reactphysics3d::Vector2& rp3dVec2) noexcept + : XMFLOAT2( rp3dVec2.x, rp3dVec2.y ) + {} + /*-----------------------------------------------------------------------------------*/ /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ + SHVec2::operator XMVECTOR() const noexcept + { + return XMLoadFloat2(this); + } + SHVec2& SHVec2::operator+=(const SHVec2& rhs) noexcept { return *this = *this + rhs; @@ -83,22 +96,16 @@ namespace SHADE SHVec2 SHVec2::operator+(const SHVec2& rhs) const noexcept { SHVec2 result; - - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - XMStoreFloat2(&result, XMVectorAdd(V1, V2)); + XMStoreFloat2(&result, XMVectorAdd(*this, rhs)); return result; } SHVec2 SHVec2::operator-(const SHVec2& rhs) const noexcept { SHVec2 result; - - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - XMStoreFloat2(&result, XMVectorSubtract(V1, V2)); + XMStoreFloat2(&result, XMVectorSubtract(*this, rhs)); return result; } @@ -110,59 +117,43 @@ namespace SHADE SHVec2 SHVec2::operator*(const SHVec2& rhs) const noexcept { SHVec2 result; - - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - XMStoreFloat2(&result, XMVectorMultiply(V1, V2)); + XMStoreFloat2(&result, XMVectorMultiply(*this, rhs)); return result; } SHVec2 SHVec2::operator*(float rhs) const noexcept { SHVec2 result; - - const XMVECTOR V = XMLoadFloat2(this); - XMStoreFloat2(&result, XMVectorScale(V, rhs)); + XMStoreFloat2(&result, XMVectorScale(*this, rhs)); return result; } SHVec2 SHVec2::operator/(const SHVec2& rhs) const noexcept { SHVec2 result; - - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - XMStoreFloat2(&result, XMVectorDivide(V1, V2)); + XMStoreFloat2(&result, XMVectorDivide(*this, rhs)); return result; } SHVec2 SHVec2::operator/(float rhs) const noexcept { SHVec2 result; - - const XMVECTOR V = XMLoadFloat2(this); - XMStoreFloat2(&result, XMVectorScale(V, 1.0f / rhs)); + XMStoreFloat2(&result, XMVectorScale(*this, 1.0f / rhs)); return result; } bool SHVec2::operator==(const SHVec2& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - - return XMVector2Equal(V1, V2); + return XMVector2Equal(*this, rhs); } bool SHVec2::operator!=(const SHVec2& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - - return XMVector2NotEqual(V1, V2); + return XMVector2NotEqual(*this, rhs); } float& SHVec2::operator[](int index) @@ -213,13 +204,16 @@ namespace SHADE } } + SHVec2::operator reactphysics3d::Vector2() const noexcept + { + return reactphysics3d::Vector2{ x, y }; + } + SHVec2 operator* (float lhs, const SHVec2& rhs) noexcept { SHVec2 result; - - const XMVECTOR V = XMLoadFloat2(&rhs); - XMStoreFloat2(&result, XMVectorScale(V, lhs)); + XMStoreFloat2(&result, XMVectorScale(rhs, lhs)); return result; } @@ -229,16 +223,12 @@ namespace SHADE float SHVec2::Length() const noexcept { - const XMVECTOR V = XMLoadFloat2(this); - - return XMVectorGetX(XMVector2Length(V)); + return XMVectorGetX(XMVector2Length(*this)); } float SHVec2::LengthSquared() const noexcept { - const XMVECTOR V = XMLoadFloat2(this); - - return XMVectorGetX(XMVector2LengthSq(V)); + return XMVectorGetX(XMVector2LengthSq(*this)); } std::string SHVec2::ToString() const noexcept @@ -251,20 +241,14 @@ namespace SHADE float SHVec2::Dot(const SHVec2& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - - return XMVectorGetX(XMVector2Dot(V1, V2)); + return XMVectorGetX(XMVector2Dot(*this, rhs)); } SHVec2 SHVec2::Cross(const SHVec2& rhs) const noexcept { SHVec2 result; - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - - XMStoreFloat2(&result, XMVector2Cross(V1, V2)); + XMStoreFloat2(&result, XMVector2Cross(*this, rhs)); return result; } @@ -276,9 +260,7 @@ namespace SHADE { SHVec2 result; - const XMVECTOR V = XMLoadFloat2(&vec2); - - XMStoreFloat2(&result, XMVector2Normalize(V)); + XMStoreFloat2(&result, XMVector2Normalize(vec2)); return result; } @@ -297,10 +279,10 @@ namespace SHADE SHVec2 result; - XMVECTOR min = XMLoadFloat2(&(*vec2s.begin())); + XMVECTOR min = *vec2s.begin(); for (auto it = vec2s.begin() + 1; it != vec2s.end(); ++it) { - const XMVECTOR tmp = XMLoadFloat2(&(*it)); + const XMVECTOR tmp = *it; min = XMVectorMin(min, tmp); } @@ -318,10 +300,10 @@ namespace SHADE SHVec2 result; - XMVECTOR max = XMLoadFloat2(&(*vec2s.begin())); + XMVECTOR max = *vec2s.begin(); for (auto it = vec2s.begin() + 1; it != vec2s.end(); ++it) { - const XMVECTOR tmp = XMLoadFloat2(&(*it)); + const XMVECTOR tmp = *it; max = XMVectorMax(max, tmp); } @@ -333,11 +315,7 @@ namespace SHADE { SHVec2 result; - const XMVECTOR V = XMLoadFloat2(&v); - const XMVECTOR MIN = XMLoadFloat2(&vMin); - const XMVECTOR MAX = XMLoadFloat2(&vMax); - - XMStoreFloat2(&result, XMVectorClamp(V, MIN, MAX)); + XMStoreFloat2(&result, XMVectorClamp(v, vMin, vMax)); return result; } @@ -345,10 +323,7 @@ namespace SHADE { SHVec2 result; - const XMVECTOR V1 = XMLoadFloat2(&a); - const XMVECTOR V2 = XMLoadFloat2(&b); - - XMStoreFloat2(&result, XMVectorLerp(V1, V2, t)); + XMStoreFloat2(&result, XMVectorLerp(a, b, t)); return result; } @@ -369,10 +344,7 @@ namespace SHADE float SHVec2::Angle(const SHVec2& lhs, const SHVec2& rhs) noexcept { - const XMVECTOR V1 = XMLoadFloat2(&lhs); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - - return XMVectorGetX(XMVector2AngleBetweenVectors(V1, V2)); + return XMVectorGetX(XMVector2AngleBetweenVectors(lhs, rhs)); } float SHVec2::Dot(const SHVec2& lhs, const SHVec2& rhs) noexcept @@ -384,11 +356,10 @@ namespace SHADE { SHVec2 result; - const XMVECTOR U = XMLoadFloat2(&u); const float V_DOT_U = Dot(v, u); const float U_LENSQ = u.LengthSquared(); - XMStoreFloat2(&result, XMVectorScale(U, V_DOT_U / U_LENSQ)); + XMStoreFloat2(&result, XMVectorScale(u, V_DOT_U / U_LENSQ)); return result; } @@ -396,10 +367,8 @@ namespace SHADE { SHVec2 result; - const XMVECTOR V = XMLoadFloat2(&v); - const XMVECTOR N = XMLoadFloat2(&normal); - XMStoreFloat2(&result, XMVector2Reflect(V, N)); + XMStoreFloat2(&result, XMVector2Reflect(v, normal)); return result; } @@ -407,10 +376,9 @@ namespace SHADE { SHVec2 result; - const XMVECTOR V = XMLoadFloat2(&v); const XMMATRIX R = XMMatrixRotationZ(angleInRad); - XMStoreFloat2(&result, XMVector2Transform(V, R)); + XMStoreFloat2(&result, XMVector2Transform(v, R)); return result; } @@ -418,10 +386,9 @@ namespace SHADE { SHVec2 result; - const XMVECTOR V = XMLoadFloat2(&v); const XMMATRIX TF = XMLoadFloat4x4(&transformMtx); - XMStoreFloat2(&result, XMVector2TransformCoord(V, TF)); + XMStoreFloat2(&result, XMVector2TransformCoord(v, TF)); return result; } diff --git a/SHADE_Engine/src/Math/Vector/SHVec2.h b/SHADE_Engine/src/Math/Vector/SHVec2.h index 17642126..e780d3ac 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec2.h +++ b/SHADE_Engine/src/Math/Vector/SHVec2.h @@ -11,6 +11,8 @@ #pragma once #include +#include + #include #include @@ -52,9 +54,14 @@ namespace SHADE SHVec2 (SHVec2&& rhs) = default; ~SHVec2 () = default; - SHVec2 () noexcept; - SHVec2 (float n) noexcept; - SHVec2 (float x, float y) noexcept; + SHVec2 () noexcept; + SHVec2 (const XMFLOAT2& xmfloat2) noexcept; + SHVec2 (float n) noexcept; + SHVec2 (float x, float y) noexcept; + + // Conversion from other math types to SHADE + + SHVec2 (const reactphysics3d::Vector2& rp3dVec2) noexcept; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ @@ -63,6 +70,11 @@ namespace SHADE SHVec2& operator= (const SHVec2& rhs) = default; SHVec2& operator= (SHVec2&& rhs) = default; + // Conversion to other math types used by SHADE + + operator DirectX::XMVECTOR () const noexcept; + operator reactphysics3d::Vector2 () const noexcept; + SHVec2& operator+= (const SHVec2& rhs) noexcept; SHVec2& operator-= (const SHVec2& rhs) noexcept; SHVec2& operator*= (const SHVec2& rhs) noexcept; @@ -86,6 +98,7 @@ namespace SHADE [[nodiscard]] float operator[] (int index) const; [[nodiscard]] float operator[] (size_t index) const; + /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/Vector/SHVec3.cpp b/SHADE_Engine/src/Math/Vector/SHVec3.cpp index 1bcb47b3..c3e3acf2 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec3.cpp +++ b/SHADE_Engine/src/Math/Vector/SHVec3.cpp @@ -14,6 +14,7 @@ #include "SHVec3.h" // Project Headers #include "Math/SHMatrix.h" +#include "Math/SHQuaternion.h" #include "Tools/SHLogger.h" using namespace DirectX; @@ -23,6 +24,7 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ /* Static Data Member Definitions */ /*-----------------------------------------------------------------------------------*/ + SHVec3 const SHVec3::Zero { 0.0f, 0.0f, 0.0f }; SHVec3 const SHVec3::One { 1.0f, 1.0f, 1.0f }; SHVec3 const SHVec3::Left { -1.0f, 0.0f, 0.0f }; @@ -43,6 +45,10 @@ namespace SHADE : XMFLOAT3( 0.0f, 0.0f, 0.0f ) {} + SHVec3::SHVec3(const XMFLOAT3& xmfloat3) noexcept + : XMFLOAT3 ( xmfloat3.x, xmfloat3.y, xmfloat3.z ) + {} + SHVec3::SHVec3(float n) noexcept : XMFLOAT3( n, n, n ) {} @@ -51,10 +57,24 @@ namespace SHADE : XMFLOAT3( _x, _y, _z ) {} + SHVec3::SHVec3(const reactphysics3d::Vector3& rp3dVec3) noexcept + : XMFLOAT3( rp3dVec3.x, rp3dVec3.y, rp3dVec3.z ) + {} + + SHVec3::SHVec3(const reactphysics3d::Quaternion& rp3dVec3) noexcept + : XMFLOAT3( SHQuaternion{rp3dVec3}.ToEuler() ) + {} + /*-----------------------------------------------------------------------------------*/ /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ + SHVec3::operator XMVECTOR() const noexcept + { + return XMLoadFloat3(this); + } + + SHVec3& SHVec3::operator+=(const SHVec3& rhs) noexcept { return *this = *this + rhs; @@ -88,22 +108,16 @@ namespace SHADE SHVec3 SHVec3::operator+(const SHVec3& rhs) const noexcept { SHVec3 result; - - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - XMStoreFloat3(&result, XMVectorAdd(V1, V2)); + XMStoreFloat3(&result, XMVectorAdd(*this, rhs)); return result; } SHVec3 SHVec3::operator-(const SHVec3& rhs) const noexcept { SHVec3 result; - - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - XMStoreFloat3(&result, XMVectorSubtract(V1, V2)); + XMStoreFloat3(&result, XMVectorSubtract(*this, rhs)); return result; } @@ -116,59 +130,43 @@ namespace SHADE SHVec3 SHVec3::operator*(const SHVec3& rhs) const noexcept { SHVec3 result; - - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - XMStoreFloat3(&result, XMVectorMultiply(V1, V2)); + XMStoreFloat3(&result, XMVectorMultiply(*this, rhs)); return result; } SHVec3 SHVec3::operator*(float rhs) const noexcept { SHVec3 result; - - const XMVECTOR V = XMLoadFloat3(this); - XMStoreFloat3(&result, XMVectorScale(V, rhs)); + XMStoreFloat3(&result, XMVectorScale(*this, rhs)); return result; } SHVec3 SHVec3::operator/(const SHVec3& rhs) const noexcept { SHVec3 result; - - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - XMStoreFloat3(&result, XMVectorDivide(V1, V2)); + XMStoreFloat3(&result, XMVectorDivide(*this, rhs)); return result; } SHVec3 SHVec3::operator/(float rhs) const noexcept { SHVec3 result; - - const XMVECTOR V = XMLoadFloat3(this); - XMStoreFloat3(&result, XMVectorScale(V, 1.0f / rhs)); + XMStoreFloat3(&result, XMVectorScale(*this, 1.0f / rhs)); return result; } bool SHVec3::operator==(const SHVec3& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - - return XMVector3Equal(V1, V2); + return XMVector3Equal(*this, rhs); } bool SHVec3::operator!=(const SHVec3& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - - return XMVector3NotEqual(V1, V2); + return XMVector3NotEqual(*this, rhs); } float& SHVec3::operator[](int index) @@ -223,13 +221,21 @@ namespace SHADE } } + SHVec3::operator reactphysics3d::Vector3() const noexcept + { + return reactphysics3d::Vector3{ x, y , z }; + } + + SHVec3::operator reactphysics3d::Quaternion() const noexcept + { + return reactphysics3d::Quaternion::fromEulerAngles(x, y, z); + } + SHVec3 operator* (float lhs, const SHVec3& rhs) noexcept { SHVec3 result; - - const XMVECTOR V = XMLoadFloat3(&rhs); - XMStoreFloat3(&result, XMVectorScale(V, lhs)); + XMStoreFloat3(&result, XMVectorScale(rhs, lhs)); return result; } @@ -239,16 +245,12 @@ namespace SHADE float SHVec3::Length() const noexcept { - const XMVECTOR V = XMLoadFloat3(this); - - return XMVectorGetX(XMVector3Length(V)); + return XMVectorGetX(XMVector3Length(*this)); } float SHVec3::LengthSquared() const noexcept { - const XMVECTOR V = XMLoadFloat3(this); - - return XMVectorGetX(XMVector3LengthSq(V)); + return XMVectorGetX(XMVector3LengthSq(*this)); } std::string SHVec3::ToString() const noexcept @@ -261,20 +263,14 @@ namespace SHADE float SHVec3::Dot(const SHVec3& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - - return XMVectorGetX(XMVector3Dot(V1, V2)); + return XMVectorGetX(XMVector3Dot(*this, rhs)); } SHVec3 SHVec3::Cross(const SHVec3& rhs) const noexcept { SHVec3 result; - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - - XMStoreFloat3(&result, XMVector3Cross(V1, V2)); + XMStoreFloat3(&result, XMVector3Cross(*this, rhs)); return result; } @@ -286,9 +282,7 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V = XMLoadFloat3(&v); - - XMStoreFloat3(&result, XMVector3Normalize(V)); + XMStoreFloat3(&result, XMVector3Normalize(v)); return result; } @@ -307,10 +301,10 @@ namespace SHADE SHVec3 result; - XMVECTOR min = XMLoadFloat3(&(*vs.begin())); + XMVECTOR min = *vs.begin(); for (auto it = vs.begin() + 1; it != vs.end(); ++it) { - const XMVECTOR tmp = XMLoadFloat3(&(*it)); + const XMVECTOR tmp = *it; min = XMVectorMin(min, tmp); } @@ -328,10 +322,10 @@ namespace SHADE SHVec3 result; - XMVECTOR max = XMLoadFloat3(&(*vs.begin())); + XMVECTOR max = *vs.begin(); for (auto it = vs.begin() + 1; it != vs.end(); ++it) { - const XMVECTOR tmp = XMLoadFloat3(&(*it)); + const XMVECTOR tmp = *it; max = XMVectorMax(max, tmp); } @@ -343,11 +337,7 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V = XMLoadFloat3(&v); - const XMVECTOR MIN = XMLoadFloat3(&vMin); - const XMVECTOR MAX = XMLoadFloat3(&vMax); - - XMStoreFloat3(&result, XMVectorClamp(V, MIN, MAX)); + XMStoreFloat3(&result, XMVectorClamp(v, vMin, vMax)); return result; } @@ -355,10 +345,7 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V1 = XMLoadFloat3(&a); - const XMVECTOR V2 = XMLoadFloat3(&b); - - XMStoreFloat3(&result, XMVectorLerp(V1, V2, t)); + XMStoreFloat3(&result, XMVectorLerp(a, b, t)); return result; } @@ -382,7 +369,7 @@ namespace SHADE const XMVECTOR V1 = XMLoadFloat3(&lhs); const XMVECTOR V2 = XMLoadFloat3(&rhs); - return XMVectorGetX(XMVector3AngleBetweenVectors(V1, V2)); + return XMVectorGetX(XMVector3AngleBetweenVectors(lhs, rhs)); } float SHVec3::Dot(const SHVec3& lhs, const SHVec3& rhs) noexcept @@ -399,22 +386,18 @@ namespace SHADE { SHVec3 result; - const XMVECTOR U = XMLoadFloat3(&u); const float V_DOT_U = Dot(v, u); const float U_LENSQ = u.LengthSquared(); - XMStoreFloat3(&result, XMVectorScale(U, V_DOT_U / U_LENSQ)); + XMStoreFloat3(&result, XMVectorScale(u, V_DOT_U / U_LENSQ)); return result; } SHVec3 SHVec3::Reflect(const SHVec3& v, const SHVec3& normal) noexcept { SHVec3 result; - - const XMVECTOR V = XMLoadFloat3(&v); - const XMVECTOR N = XMLoadFloat3(&normal); - XMStoreFloat3(&result, XMVector3Reflect(V, N)); + XMStoreFloat3(&result, XMVector3Reflect(v, normal)); return result; } @@ -422,12 +405,9 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V = XMLoadFloat3(&v); + const XMVECTOR Q = XMQuaternionRotationAxis(axis, angleInRad); - const XMVECTOR AXIS = XMLoadFloat3(&axis); - const XMVECTOR Q = XMQuaternionRotationAxis(AXIS, angleInRad); - - XMStoreFloat3(&result, XMVector3Rotate(V, Q)); + XMStoreFloat3(&result, XMVector3Rotate(v, Q)); return result; } @@ -435,10 +415,9 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V = XMLoadFloat3(&v); - const XMMATRIX R = XMMatrixRotationX(angleInRad); + const XMMATRIX R = XMMatrixRotationX(angleInRad); - XMStoreFloat3(&result, XMVector3TransformCoord(V, R)); + XMStoreFloat3(&result, XMVector3TransformCoord(v, R)); return result; } @@ -446,10 +425,9 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V = XMLoadFloat3(&v); - const XMMATRIX R = XMMatrixRotationY(angleInRad); + const XMMATRIX R = XMMatrixRotationY(angleInRad); - XMStoreFloat3(&result, XMVector3TransformCoord(V, R)); + XMStoreFloat3(&result, XMVector3TransformCoord(v, R)); return result; } @@ -457,10 +435,9 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V = XMLoadFloat3(&v); - const XMMATRIX R = XMMatrixRotationZ(angleInRad); + const XMMATRIX R = XMMatrixRotationZ(angleInRad); - XMStoreFloat3(&result, XMVector3TransformCoord(V, R)); + XMStoreFloat3(&result, XMVector3TransformCoord(v, R)); return result; } @@ -468,10 +445,9 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V = XMLoadFloat3(&v); const XMMATRIX TF = XMLoadFloat4x4(&transformMtx); - XMStoreFloat3(&result, XMVector3TransformCoord(V, TF)); + XMStoreFloat3(&result, XMVector3TransformCoord(v, TF)); return result; } } \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Vector/SHVec3.h b/SHADE_Engine/src/Math/Vector/SHVec3.h index cc0e043e..eab96b30 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec3.h +++ b/SHADE_Engine/src/Math/Vector/SHVec3.h @@ -11,6 +11,9 @@ #pragma once #include +#include +#include + #include #include @@ -58,39 +61,50 @@ namespace SHADE ~SHVec3 () = default; SHVec3 () noexcept; + SHVec3 (const XMFLOAT3& xmfloat3) noexcept; SHVec3 (float n) noexcept; SHVec3 (float x, float y, float z) noexcept; + // Conversion from other math types to SHADE + + SHVec3 (const reactphysics3d::Vector3& rp3dVec3) noexcept; + SHVec3 (const reactphysics3d::Quaternion& rp3dVec3) noexcept; + /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ /*---------------------------------------------------------------------------------*/ - SHVec3& operator= (const SHVec3& rhs) = default; - SHVec3& operator= (SHVec3&& rhs) = default; + SHVec3& operator= (const SHVec3& rhs) = default; + SHVec3& operator= (SHVec3&& rhs) = default; - SHVec3& operator+= (const SHVec3& rhs) noexcept; - SHVec3& operator-= (const SHVec3& rhs) noexcept; - SHVec3& operator*= (const SHVec3& rhs) noexcept; - SHVec3& operator*= (float rhs) noexcept; - SHVec3& operator/= (const SHVec3& rhs) noexcept; - SHVec3& operator/= (float rhs) noexcept; + // Conversion to other math types used by SHADE - [[nodiscard]] SHVec3 operator+ (const SHVec3& rhs) const noexcept; - [[nodiscard]] SHVec3 operator- (const SHVec3& rhs) const noexcept; - [[nodiscard]] SHVec3 operator- () const noexcept; - [[nodiscard]] SHVec3 operator* (const SHVec3& rhs) const noexcept; - [[nodiscard]] SHVec3 operator* (float rhs) const noexcept; - [[nodiscard]] SHVec3 operator/ (const SHVec3& rhs) const noexcept; - [[nodiscard]] SHVec3 operator/ (float rhs) const noexcept; + operator reactphysics3d::Vector3 () const noexcept; + operator reactphysics3d::Quaternion () const noexcept; + operator DirectX::XMVECTOR () const noexcept; - [[nodiscard]] bool operator== (const SHVec3& rhs) const noexcept; - [[nodiscard]] bool operator!= (const SHVec3& rhs) const noexcept; + SHVec3& operator+= (const SHVec3& rhs) noexcept; + SHVec3& operator-= (const SHVec3& rhs) noexcept; + SHVec3& operator*= (const SHVec3& rhs) noexcept; + SHVec3& operator*= (float rhs) noexcept; + SHVec3& operator/= (const SHVec3& rhs) noexcept; + SHVec3& operator/= (float rhs) noexcept; - [[nodiscard]] float& operator[] (int index); - [[nodiscard]] float& operator[] (size_t index); - [[nodiscard]] float operator[] (int index) const; - [[nodiscard]] float operator[] (size_t index) const; + [[nodiscard]] SHVec3 operator+ (const SHVec3& rhs) const noexcept; + [[nodiscard]] SHVec3 operator- (const SHVec3& rhs) const noexcept; + [[nodiscard]] SHVec3 operator- () const noexcept; + [[nodiscard]] SHVec3 operator* (const SHVec3& rhs) const noexcept; + [[nodiscard]] SHVec3 operator* (float rhs) const noexcept; + [[nodiscard]] SHVec3 operator/ (const SHVec3& rhs) const noexcept; + [[nodiscard]] SHVec3 operator/ (float rhs) const noexcept; + [[nodiscard]] bool operator== (const SHVec3& rhs) const noexcept; + [[nodiscard]] bool operator!= (const SHVec3& rhs) const noexcept; + + [[nodiscard]] float& operator[] (int index); + [[nodiscard]] float& operator[] (size_t index); + [[nodiscard]] float operator[] (int index) const; + [[nodiscard]] float operator[] (size_t index) const; /*---------------------------------------------------------------------------------*/ /* Function Members */ diff --git a/SHADE_Engine/src/Math/Vector/SHVec4.cpp b/SHADE_Engine/src/Math/Vector/SHVec4.cpp index d1c87865..bcf2ef97 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec4.cpp +++ b/SHADE_Engine/src/Math/Vector/SHVec4.cpp @@ -38,6 +38,10 @@ namespace SHADE : XMFLOAT4( 0.0f, 0.0f, 0.0f, 0.0f ) {} + SHVec4::SHVec4(const XMFLOAT4& xmfloat4) noexcept + : XMFLOAT4( xmfloat4.x, xmfloat4.y, xmfloat4.z, xmfloat4.w ) + {} + SHVec4::SHVec4(float _x, float _y, float _z, float _w) noexcept : XMFLOAT4( _x, _y, _z, _w ) {} @@ -46,6 +50,11 @@ namespace SHADE /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ + SHVec4::operator XMVECTOR() const noexcept + { + return XMLoadFloat4(this); + } + SHVec4& SHVec4::operator+=(const SHVec4& rhs) noexcept { return *this = *this + rhs; @@ -79,22 +88,16 @@ namespace SHADE SHVec4 SHVec4::operator+(const SHVec4& rhs) const noexcept { SHVec4 result; - - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - XMStoreFloat4(&result, XMVectorAdd(V1, V2)); + XMStoreFloat4(&result, XMVectorAdd(*this, rhs)); return result; } SHVec4 SHVec4::operator-(const SHVec4& rhs) const noexcept { SHVec4 result; - - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - XMStoreFloat4(&result, XMVectorSubtract(V1, V2)); + XMStoreFloat4(&result, XMVectorSubtract(*this, rhs)); return result; } @@ -106,59 +109,43 @@ namespace SHADE SHVec4 SHVec4::operator*(const SHVec4& rhs) const noexcept { SHVec4 result; - - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - XMStoreFloat4(&result, XMVectorMultiply(V1, V2)); + XMStoreFloat4(&result, XMVectorMultiply(*this, rhs)); return result; } SHVec4 SHVec4::operator*(float rhs) const noexcept { SHVec4 result; - - const XMVECTOR V = XMLoadFloat4(this); - XMStoreFloat4(&result, XMVectorScale(V, rhs)); + XMStoreFloat4(&result, XMVectorScale(*this, rhs)); return result; } SHVec4 SHVec4::operator/(const SHVec4& rhs) const noexcept { SHVec4 result; - - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - XMStoreFloat4(&result, XMVectorDivide(V1, V2)); + XMStoreFloat4(&result, XMVectorDivide(*this, rhs)); return result; } SHVec4 SHVec4::operator/(float rhs) const noexcept { SHVec4 result; - - const XMVECTOR V = XMLoadFloat4(this); - XMStoreFloat4(&result, XMVectorScale(V, 1.0f / rhs)); + XMStoreFloat4(&result, XMVectorScale(*this, 1.0f / rhs)); return result; } bool SHVec4::operator==(const SHVec4& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - - return XMVector4Equal(V1, V2); + return XMVector4Equal(*this, rhs); } bool SHVec4::operator!=(const SHVec4& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - - return XMVector4NotEqual(V1, V2); + return XMVector4NotEqual(*this, rhs); } float& SHVec4::operator[](int index) @@ -220,10 +207,8 @@ namespace SHADE SHVec4 operator* (float lhs, const SHVec4& rhs) noexcept { SHVec4 result; - - const XMVECTOR V = XMLoadFloat4(&rhs); - XMStoreFloat4(&result, XMVectorScale(V, lhs)); + XMStoreFloat4(&result, XMVectorScale(rhs, lhs)); return result; } @@ -233,30 +218,22 @@ namespace SHADE float SHVec4::Length() const noexcept { - const XMVECTOR V = XMLoadFloat4(this); - - return XMVectorGetX(XMVector4Length(V)); + return XMVectorGetX(XMVector4Length(*this)); } float SHVec4::Length3D() const noexcept { - const XMVECTOR V = XMLoadFloat4(this); - - return XMVectorGetX(XMVector3Length(V)); + return XMVectorGetX(XMVector3Length(*this)); } float SHVec4::LengthSquared() const noexcept { - const XMVECTOR V = XMLoadFloat4(this); - - return XMVectorGetX(XMVector4LengthSq(V)); + return XMVectorGetX(XMVector4LengthSq(*this)); } float SHVec4::LengthSquared3D() const noexcept { - const XMVECTOR V = XMLoadFloat4(this); - - return XMVectorGetX(XMVector3LengthSq(V)); + return XMVectorGetX(XMVector3LengthSq(*this)); } std::string SHVec4::ToString() const noexcept @@ -269,28 +246,19 @@ namespace SHADE float SHVec4::Dot(const SHVec4& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - - return XMVectorGetX(XMVector4Dot(V1, V2)); + return XMVectorGetX(XMVector4Dot(*this, rhs)); } float SHVec4::Dot3D(const SHVec4& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - - return XMVectorGetX(XMVector3Dot(V1, V2)); + return XMVectorGetX(XMVector3Dot(*this, rhs)); } SHVec4 SHVec4::Cross3D(const SHVec4& rhs) const noexcept { SHVec4 result; - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - - XMStoreFloat4(&result, XMVector3Cross(V1, V2)); + XMStoreFloat4(&result, XMVector3Cross(*this, rhs)); result.w = 1.0f; return result; } @@ -299,11 +267,7 @@ namespace SHADE { SHVec4 result; - const XMVECTOR V3 = XMLoadFloat4(this); - const XMVECTOR V1 = XMLoadFloat4(&v1); - const XMVECTOR V2 = XMLoadFloat4(&v2); - - XMStoreFloat4(&result, XMVector4Cross(V3, V1, V2)); + XMStoreFloat4(&result, XMVector4Cross(*this, v1, v2)); return result; } @@ -315,9 +279,7 @@ namespace SHADE { SHVec4 result; - const XMVECTOR V = XMLoadFloat4(&v); - - XMStoreFloat4(&result, XMVector4Normalize(V)); + XMStoreFloat4(&result, XMVector4Normalize(v)); return result; } @@ -325,9 +287,7 @@ namespace SHADE { SHVec4 result; - const XMVECTOR V = XMLoadFloat4(&v); - - XMStoreFloat4(&result, XMVector3Normalize(V)); + XMStoreFloat4(&result, XMVector3Normalize(v)); result.w = 1.0f; return result; } @@ -347,10 +307,10 @@ namespace SHADE SHVec4 result; - XMVECTOR min = XMLoadFloat4(&(*vs.begin())); + XMVECTOR min = *vs.begin(); for (auto it = vs.begin() + 1; it != vs.end(); ++it) { - const XMVECTOR tmp = XMLoadFloat4(&(*it)); + const XMVECTOR tmp = *it; min = XMVectorMin(min, tmp); } @@ -368,10 +328,10 @@ namespace SHADE SHVec4 result; - XMVECTOR max = XMLoadFloat4(&(*vs.begin())); + XMVECTOR max = *vs.begin(); for (auto it = vs.begin() + 1; it != vs.end(); ++it) { - const XMVECTOR tmp = XMLoadFloat4(&(*it)); + const XMVECTOR tmp = *it; max = XMVectorMax(max, tmp); } @@ -383,11 +343,7 @@ namespace SHADE { SHVec4 result; - const XMVECTOR V = XMLoadFloat4(&v); - const XMVECTOR MIN = XMLoadFloat4(&vMin); - const XMVECTOR MAX = XMLoadFloat4(&vMax); - - XMStoreFloat4(&result, XMVectorClamp(V, MIN, MAX)); + XMStoreFloat4(&result, XMVectorClamp(v, vMin, vMax)); return result; } @@ -395,10 +351,7 @@ namespace SHADE { SHVec4 result; - const XMVECTOR V1 = XMLoadFloat4(&a); - const XMVECTOR V2 = XMLoadFloat4(&b); - - XMStoreFloat4(&result, XMVectorLerp(V1, V2, t)); + XMStoreFloat4(&result, XMVectorLerp(a, b, t)); return result; } @@ -429,18 +382,12 @@ namespace SHADE float SHVec4::Angle(const SHVec4& lhs, const SHVec4& rhs) noexcept { - const XMVECTOR V1 = XMLoadFloat4(&lhs); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - - return XMVectorGetX(XMVector4AngleBetweenVectors(V1, V2)); + return XMVectorGetX(XMVector4AngleBetweenVectors(lhs,rhs)); } float SHVec4::Angle3D(const SHVec4& lhs, const SHVec4& rhs) noexcept { - const XMVECTOR V1 = XMLoadFloat4(&lhs); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - - return XMVectorGetX(XMVector3AngleBetweenVectors(V1, V2)); + return XMVectorGetX(XMVector3AngleBetweenVectors(lhs,rhs)); } float SHVec4::Dot(const SHVec4& lhs, const SHVec4& rhs) noexcept @@ -467,11 +414,10 @@ namespace SHADE { SHVec4 result; - const XMVECTOR U = XMLoadFloat4(&u); const float V_DOT_U = Dot(v, u); const float U_LENSQ = u.LengthSquared(); - XMStoreFloat4(&result, XMVectorScale(U, V_DOT_U / U_LENSQ)); + XMStoreFloat4(&result, XMVectorScale(u, V_DOT_U / U_LENSQ)); return result; } @@ -479,11 +425,10 @@ namespace SHADE { SHVec4 result; - const XMVECTOR U = XMLoadFloat4(&u); const float V_DOT_U = Dot3D(v, u); const float U_LENSQ = u.LengthSquared3D(); - XMStoreFloat4(&result, XMVectorScale(U, V_DOT_U / U_LENSQ)); + XMStoreFloat4(&result, XMVectorScale(u, V_DOT_U / U_LENSQ)); result.w = 1.0f; return result; } @@ -491,11 +436,8 @@ namespace SHADE SHVec4 SHVec4::Reflect(const SHVec4& v, const SHVec4& normal) noexcept { SHVec4 result; - - const XMVECTOR V = XMLoadFloat4(&v); - const XMVECTOR N = XMLoadFloat4(&normal); - XMStoreFloat4(&result, XMVector4Reflect(V, N)); + XMStoreFloat4(&result, XMVector4Reflect(v, normal)); result.w = 1.0f; return result; } @@ -503,11 +445,8 @@ namespace SHADE SHVec4 SHVec4::Reflect3D(const SHVec4& v, const SHVec4& normal) noexcept { SHVec4 result; - - const XMVECTOR V = XMLoadFloat4(&v); - const XMVECTOR N = XMLoadFloat4(&normal); - XMStoreFloat4(&result, XMVector3Reflect(V, N)); + XMStoreFloat4(&result, XMVector3Reflect(v, normal)); result.w = 1.0f; return result; } @@ -516,10 +455,9 @@ namespace SHADE { SHVec4 result; - const XMVECTOR V = XMLoadFloat4(&v); const XMMATRIX TF = XMLoadFloat4x4(&transformMtx); - XMStoreFloat4(&result, XMVector3TransformCoord(V, TF)); + XMStoreFloat4(&result, XMVector3TransformCoord(v, TF)); return result; } } \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Vector/SHVec4.h b/SHADE_Engine/src/Math/Vector/SHVec4.h index 59038065..911a714e 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec4.h +++ b/SHADE_Engine/src/Math/Vector/SHVec4.h @@ -52,8 +52,9 @@ namespace SHADE SHVec4 (SHVec4&& rhs) = default; ~SHVec4 () = default; - SHVec4 () noexcept; - SHVec4 (float x, float y, float z, float w) noexcept; + SHVec4 () noexcept; + SHVec4 (const XMFLOAT4& xmfloat4) noexcept; + SHVec4 (float x, float y, float z, float w) noexcept; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ @@ -62,6 +63,8 @@ namespace SHADE SHVec4& operator= (const SHVec4& rhs) = default; SHVec4& operator= (SHVec4&& rhs) = default; + operator DirectX::XMVECTOR () const noexcept; + SHVec4& operator+= (const SHVec4& rhs) noexcept; SHVec4& operator-= (const SHVec4& rhs) noexcept; SHVec4& operator*= (const SHVec4& rhs) noexcept; diff --git a/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp index 73e7ccbd..71183f00 100644 --- a/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp @@ -15,6 +15,7 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" +#include "Math/SHMathHelpers.h" #include "Physics/SHPhysicsSystem.h" namespace SHADE @@ -24,7 +25,8 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHColliderComponent::SHColliderComponent() noexcept - : system { nullptr } + : system { nullptr } + , colliders {} {} /*-----------------------------------------------------------------------------------*/ @@ -87,12 +89,17 @@ namespace SHADE system->RemoveCollider(GetEID()); } - SHBoundingBox* SHColliderComponent::AddBoundingBox() noexcept + SHBoundingBox* SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset) noexcept { const auto TYPE = SHCollider::Type::BOX; - const auto BOX_PAIR = std::make_pair(SHCollider{TYPE}, true); - auto& collider = colliders.emplace_back(BOX_PAIR).first; + auto boxPair = std::make_pair(SHCollider{TYPE}, true); + auto& collider = colliders.emplace_back(boxPair).first; + + const auto* tf = SHComponentManager::GetComponent(GetEID()); + + collider.SetPositionOffset(posOffset); + collider.SetAsBoundingBox(tf->GetWorldScale() * halfExtents); if (!system) { @@ -101,23 +108,37 @@ namespace SHADE } // Notify Physics System - system->AddCollisionShape(GetEID(), collider.GetShape()); + system->AddCollisionShape(GetEID(), &collider); return reinterpret_cast(collider.GetShape()); } - //void SHColliderComponent::AddSphere() noexcept - //{ - // const auto TYPE = SHCollider::Type::SPHERE; + SHBoundingSphere* SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept + { + const auto TYPE = SHCollider::Type::SPHERE; - // if (!system) - // { - // SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!") - // return; - // } + auto spherePair = std::make_pair(SHCollider{ TYPE }, true); + auto& collider = colliders.emplace_back(spherePair).first; - // // Notify Physics System - //} + const auto* tf = SHComponentManager::GetComponent(GetEID()); + + collider.SetPositionOffset(posOffset); + + const SHVec3 TF_WORLD_SCALE = tf->GetWorldScale(); + const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z }); + collider.SetAsBoundingSphere(MAX_SCALE * 0.5f); + + if (!system) + { + SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!") + return nullptr; + } + + // Notify Physics System + system->AddCollisionShape(GetEID(), &collider); + + return reinterpret_cast(collider.GetShape()); + } void SHColliderComponent::RemoveCollider(int index) { diff --git a/SHADE_Engine/src/Physics/Components/SHColliderComponent.h b/SHADE_Engine/src/Physics/Components/SHColliderComponent.h index cb9696d9..22d5ceee 100644 --- a/SHADE_Engine/src/Physics/Components/SHColliderComponent.h +++ b/SHADE_Engine/src/Physics/Components/SHColliderComponent.h @@ -15,6 +15,13 @@ // Project Headers #include "ECS_Base/Components/SHComponent.h" #include "Physics/SHCollider.h" +#include "Math/Geometry/SHBoundingBox.h" +#include "Math/Geometry/SHBoundingSphere.h" + +//namespace SHADE +//{ +// class SHPhysicsSystem; +//} namespace SHADE { @@ -30,6 +37,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ friend class SHPhysicsSystem; + friend class SHPhysicsObject; /*---------------------------------------------------------------------------------*/ /* Type Definitions */ @@ -76,10 +84,11 @@ namespace SHADE void OnCreate () override; void OnDestroy () override; - SHBoundingBox* AddBoundingBox () noexcept; - void RemoveCollider (int index); + SHBoundingBox* AddBoundingBox (const SHVec3& halfExtents = SHVec3::One, const SHVec3& posOffset = SHVec3::Zero) noexcept; + SHBoundingSphere* AddBoundingSphere (float radius = 1.0f, const SHVec3& posOffset = SHVec3::Zero) noexcept; + private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp index 5f961de4..e5938717 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp @@ -392,9 +392,9 @@ RTTR_REGISTRATION registration::enumeration("RigidBody Type") ( - value("Static", SHRigidBodyComponent::Type::STATIC), - value("Dynamic", SHRigidBodyComponent::Type::DYNAMIC), - value("Kinematic", SHRigidBodyComponent::Type::KINEMATIC) + value("Static", SHRigidBodyComponent::Type::STATIC), + value("Kinematic", SHRigidBodyComponent::Type::KINEMATIC), + value("Dynamic", SHRigidBodyComponent::Type::DYNAMIC) ); registration::class_("RigidBody Component") diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h index 0793b2ff..03b350e1 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h +++ b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h @@ -14,7 +14,13 @@ // Project Headers #include "ECS_Base/Components/SHComponent.h" -#include "Physics/SHPhysicsObject.h" +#include "Math/Vector/SHVec3.h" +#include "Math/SHQuaternion.h" + +//namespace SHADE +//{ +// class SHPhysicsSystem; +//} namespace SHADE { @@ -30,6 +36,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ friend class SHPhysicsSystem; + friend class SHPhysicsObject; public: /*---------------------------------------------------------------------------------*/ @@ -137,6 +144,9 @@ namespace SHADE /* Data Members */ /*---------------------------------------------------------------------------------*/ + static constexpr size_t NUM_FLAGS = 8; + static constexpr size_t NUM_DIRTY_FLAGS = 16; + Type type; // rX rY rZ pX pY pZ slp g @@ -162,10 +172,6 @@ namespace SHADE SHVec3 position; SHQuaternion orientation; - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - RTTR_ENABLE() }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHCollider.cpp b/SHADE_Engine/src/Physics/SHCollider.cpp index 724db19c..f5899cfc 100644 --- a/SHADE_Engine/src/Physics/SHCollider.cpp +++ b/SHADE_Engine/src/Physics/SHCollider.cpp @@ -12,6 +12,9 @@ // Primary Header #include "SHCollider.h" +// Project Headers +#include "Math/Geometry/SHBoundingBox.h" +#include "Math/Geometry/SHBoundingSphere.h" namespace SHADE { @@ -25,34 +28,41 @@ namespace SHADE , dirty { true } , shape { nullptr } { - CreateShape(); + switch (type) + { + case Type::BOX: + { + SetAsBoundingBox(SHVec3::One); + break; + } + case Type::SPHERE: + { + SetAsBoundingSphere(1.0f); + break; + } + default: break; + } } SHCollider::SHCollider(const SHCollider& rhs) noexcept - : type { rhs.type} - , isTrigger { rhs.isTrigger } - , dirty { true } - , shape { nullptr } - { - CreateShape(); - - // TODO(Diren): Copy transform data over - } + : type { rhs.type} + , isTrigger { rhs.isTrigger } + , dirty { true } + , shape { rhs.shape } + , positionOffset { rhs.positionOffset } + {} SHCollider::SHCollider(SHCollider&& rhs) noexcept - : type { rhs.type} - , isTrigger { rhs.isTrigger } - , dirty { true } - , shape { nullptr } - { - CreateShape(); - - // TODO(Diren): Copy transform data over - } + : type { rhs.type} + , isTrigger { rhs.isTrigger } + , dirty { true } + , shape { rhs.shape } + , positionOffset { rhs.positionOffset } + {} SHCollider::~SHCollider() noexcept { - delete shape; + shape = nullptr; } /*-----------------------------------------------------------------------------------*/ @@ -61,26 +71,25 @@ namespace SHADE SHCollider& SHCollider::operator=(const SHCollider& rhs) noexcept { - type = rhs.type; - isTrigger = rhs.isTrigger; - dirty = true; - - CreateShape(); - - // TODO(Diren): Copy transform data over + if (this == &rhs) + return *this; + + type = rhs.type; + isTrigger = rhs.isTrigger; + dirty = true; + shape = rhs.shape; + positionOffset = rhs.positionOffset; return *this; } SHCollider& SHCollider::operator=(SHCollider&& rhs) noexcept { - type = rhs.type; - isTrigger = rhs.isTrigger; - dirty = true; - - CreateShape(); - - // TODO(Diren): Copy transform data over + type = rhs.type; + isTrigger = rhs.isTrigger; + dirty = true; + shape = rhs.shape; + positionOffset = rhs.positionOffset; return *this; } @@ -104,11 +113,6 @@ namespace SHADE return type; } - SHShape* SHCollider::GetShape() const noexcept - { - return shape; - } - float SHCollider::GetFriction() const noexcept { // TODO(Diren): Fix after implementing materials @@ -126,36 +130,37 @@ namespace SHADE return 0.0f; } - SHVec3 SHCollider::GetPosition() const noexcept - { - // TODO(Diren): Fix after linking transform data - return SHVec3::Zero; - } - const SHVec3& SHCollider::GetPositionOffset() const noexcept { return positionOffset; } - SHQuaternion SHCollider::GetOrientation() const noexcept + SHShape* SHCollider::GetShape() noexcept { - // TODO(Diren): Fix after linking transform data - return SHQuaternion::Identity; + dirty = true; + return shape; } /*-----------------------------------------------------------------------------------*/ /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHCollider::SetType(Type newType) noexcept + void SHCollider::SetAsBoundingBox(const SHVec3& halfExtents) { - if (type == newType) - return; - dirty = true; + type = Type::BOX; - type = newType; - CreateShape(); + delete shape; + shape = new SHBoundingBox{ positionOffset, halfExtents }; + } + + void SHCollider::SetAsBoundingSphere(float radius) + { + dirty = true; + type = Type::SPHERE; + + delete shape; + shape = new SHBoundingSphere{ positionOffset, radius }; } void SHCollider::SetIsTrigger(bool trigger) noexcept @@ -184,32 +189,21 @@ namespace SHADE dirty = true; positionOffset = posOffset; } +} // namespace SHADE - /*-----------------------------------------------------------------------------------*/ - /* Private Member Function Definitions */ - /*-----------------------------------------------------------------------------------*/ +RTTR_REGISTRATION +{ + using namespace SHADE; + using namespace rttr; - void SHCollider::CreateShape() - { - // Remove current shape - delete shape; + registration::enumeration("Collider Type") + ( + value("Box", SHCollider::Type::BOX), + value("Sphere", SHCollider::Type::SPHERE) + // TODO(Diren): Add More Shapes + ); - switch (type) - { - case Type::BOX: CreateBoundingBox(); break; - case Type::SPHERE: CreateSphere(); break; - default: break; - } - } - - void SHCollider::CreateBoundingBox() - { - shape = new SHBoundingBox{ SHVec3::Zero, SHVec3::One }; - } - - void SHCollider::CreateSphere() - { - - } - -} // namespace SHADE \ No newline at end of file + registration::class_("Collider") + .property("Position Offset", &SHCollider::GetPositionOffset, &SHCollider::SetPositionOffset); + // TODO(Diren): Add Physics Materials +} \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHCollider.h b/SHADE_Engine/src/Physics/SHCollider.h index fce4a5b2..0e024f09 100644 --- a/SHADE_Engine/src/Physics/SHCollider.h +++ b/SHADE_Engine/src/Physics/SHCollider.h @@ -10,8 +10,10 @@ #pragma once +#include + // Project Headers -#include "Math/Geometry/SHBoundingBox.h" +#include "Math/Geometry/SHShape.h" #include "Math/SHQuaternion.h" namespace SHADE @@ -32,15 +34,13 @@ namespace SHADE BOX , SPHERE , CAPSULE - , CONVEX_HULL - , CONVEX_MESH }; /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHCollider (Type colliderType); + SHCollider (Type colliderType = Type::BOX); SHCollider (const SHCollider& rhs) noexcept; SHCollider (SHCollider&& rhs) noexcept; @@ -62,28 +62,28 @@ namespace SHADE [[nodiscard]] bool IsTrigger () const noexcept; [[nodiscard]] Type GetType () const noexcept; - [[nodiscard]] SHShape* GetShape () const noexcept; [[nodiscard]] float GetFriction () const noexcept; [[nodiscard]] float GetBounciness () const noexcept; [[nodiscard]] float GetDensity () const noexcept; - [[nodiscard]] SHVec3 GetPosition () const noexcept; [[nodiscard]] const SHVec3& GetPositionOffset () const noexcept; - [[nodiscard]] SHQuaternion GetOrientation () const noexcept; + + [[nodiscard]] SHShape* GetShape () noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetType (Type newType) noexcept; + void SetAsBoundingBox (const SHVec3& halfExtents); + void SetAsBoundingSphere (float radius); - void SetIsTrigger (bool isTrigger) noexcept; - void SetFriction (float friction) noexcept; - void SetBounciness (float bounciness) noexcept; - void SetDensity (float density) noexcept; + void SetIsTrigger (bool isTrigger) noexcept; + void SetFriction (float friction) noexcept; + void SetBounciness (float bounciness) noexcept; + void SetDensity (float density) noexcept; - void SetPositionOffset (const SHVec3& positionOffset) noexcept; + void SetPositionOffset (const SHVec3& positionOffset) noexcept; private: /*---------------------------------------------------------------------------------*/ @@ -96,13 +96,7 @@ namespace SHADE SHShape* shape; SHVec3 positionOffset; - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - - void CreateShape (); - void CreateBoundingBox (); - void CreateSphere (); + RTTR_ENABLE() }; } // namespace SHADE diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp index 844803b1..36f7c57e 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp @@ -15,7 +15,8 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" -#include "SHPhysicsSystem.h" +#include "ECS_Base/Managers/SHComponentManager.h" + namespace SHADE { @@ -23,16 +24,20 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHPhysicsObject::SHPhysicsObject() noexcept - : entityID { MAX_EID } + SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept + : entityID { eid } , isRigidBody { false } , hasColliders{ false } + , factory { physicsFactory } + , world { physicsWorld } , rp3dBody { nullptr } {} SHPhysicsObject::~SHPhysicsObject() noexcept { - rp3dBody = nullptr; + factory = nullptr; + world = nullptr; + rp3dBody = nullptr; } /*-----------------------------------------------------------------------------------*/ @@ -44,10 +49,7 @@ namespace SHADE SHVec3 result; if (rp3dBody) - { - const auto& RP3D_RESULT = rp3dBody->getTransform().getPosition(); - result = SHVec3{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z }; - } + result = SHVec3{ rp3dBody->getTransform().getPosition() }; return result; } @@ -57,10 +59,7 @@ namespace SHADE SHQuaternion result; if (rp3dBody) - { - const auto& RP3D_RESULT = rp3dBody->getTransform().getOrientation(); - result = SHQuaternion{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z, RP3D_RESULT.w }; - } + result = SHQuaternion{ rp3dBody->getTransform().getOrientation() }; return result; } @@ -70,10 +69,7 @@ namespace SHADE SHVec3 result; if (rp3dBody) - { - const auto& RP3D_RESULT = rp3dBody->getTransform().getOrientation(); - result = SHQuaternion{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z, RP3D_RESULT.w }.ToEuler(); - } + result = SHQuaternion{ rp3dBody->getTransform().getOrientation() }.ToEuler(); return result; } @@ -84,10 +80,14 @@ namespace SHADE void SHPhysicsObject::SetPosition(const SHVec3& position) noexcept { - const rp3d::Vector3 RP3D_POS { position.x, position.y, position.z }; + if (!rp3dBody) + { + SHLOG_ERROR("Cannot set position of a non-existent physics body for Entity {}", entityID) + return; + } rp3d::Transform rp3dTF; - rp3dTF.setPosition(RP3D_POS); + rp3dTF.setPosition(position); rp3dTF.setOrientation(rp3dBody->getTransform().getOrientation()); rp3dBody->setTransform(rp3dTF); @@ -96,11 +96,15 @@ namespace SHADE void SHPhysicsObject::SetOrientation(const SHQuaternion& orientation) noexcept { - const rp3d::Quaternion RP3D_ORIENTATION { orientation.x, orientation.y, orientation.z, orientation.w }; + if (!rp3dBody) + { + SHLOG_ERROR("Cannot set orientation of a non-existent physics body for Entity {}", entityID) + return; + } rp3d::Transform rp3dTF; rp3dTF.setPosition(rp3dBody->getTransform().getPosition()); - rp3dTF.setOrientation(RP3D_ORIENTATION); + rp3dTF.setOrientation(orientation); rp3dBody->setTransform(rp3dTF); prevTransform = rp3dTF; @@ -108,14 +112,253 @@ namespace SHADE void SHPhysicsObject::SetRotation(const SHVec3& rotation) noexcept { - const rp3d::Quaternion RP3D_ORIENTATION = rp3d::Quaternion::fromEulerAngles( rotation.x, rotation.y, rotation.z ); + if (!rp3dBody) + { + SHLOG_ERROR("Cannot set rotation of a non-existent physics body for Entity {}", entityID) + return; + } rp3d::Transform rp3dTF; rp3dTF.setPosition(rp3dBody->getTransform().getPosition()); - rp3dTF.setOrientation(RP3D_ORIENTATION); + rp3dTF.setOrientation(rotation); rp3dBody->setTransform(rp3dTF); prevTransform = rp3dTF; } + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsObject::CreateRigidBody(const SHTransformComponent* tf, SHRigidBodyComponent* rb, SHColliderComponent* c) + { + // If collider already exists, recreate the collision body as a rigid body + if (hasColliders) + world->destroyCollisionBody(rp3dBody); + + rp3dBody = world->createRigidBody(rp3d::Transform{ tf->GetWorldPosition(), tf->GetWorldRotation() }); + isRigidBody = true; + + rb->position = tf->GetWorldPosition(); + rb->orientation = tf->GetWorldRotation(); + + if (hasColliders) + { + c->position = tf->GetWorldPosition(); + c->orientation = tf->GetWorldRotation(); + // Get array of colliders and add them back into the rigidbody + for (auto& collider : c->colliders | std::views::keys) + AddCollider(&collider); + } + } + + void SHPhysicsObject::CreateCollisionBody(const SHTransformComponent* tf, SHColliderComponent* c) + { + if (rp3dBody == nullptr) + rp3dBody = world->createCollisionBody(rp3d::Transform{ tf->GetWorldPosition(), tf->GetWorldRotation() }); + + hasColliders = true; + + c->position = tf->GetWorldPosition(); + c->orientation = tf->GetWorldRotation(); + + for (auto& collider : c->colliders | std::views::keys) + AddCollider(&collider); + } + + int SHPhysicsObject::AddCollider(SHCollider* collider) + { + switch (collider->GetType()) + { + case SHCollider::Type::BOX: + { + const auto* box = reinterpret_cast(collider->GetShape()); + rp3d::BoxShape* newBox = factory->createBoxShape(box->GetHalfExtents()); + + rp3dBody->addCollider(newBox, rp3d::Transform{ collider->GetPositionOffset(), SHQuaternion::Identity }); + break; + } + case SHCollider::Type::SPHERE: + { + const auto* sphere = reinterpret_cast(collider->GetShape()); + rp3d::SphereShape* newSphere = factory->createSphereShape(sphere->GetRadius()); + + rp3dBody->addCollider(newSphere, rp3d::Transform{ collider->GetPositionOffset(), SHQuaternion::Identity }); + break; + } + // TODO(Diren): Add more collider shapes + default: break; + } + + return static_cast(rp3dBody->getNbColliders()) - 1; + } + + void SHPhysicsObject::DestroyRigidBody(SHColliderComponent* c) noexcept + { + world->destroyRigidBody(reinterpret_cast(rp3dBody)); + + if (hasColliders) + { + // Preserve colliders as a collision body + rp3dBody = world->createCollisionBody(rp3d::Transform{ c->position, c->orientation }); + for (auto& collider : c->colliders | std::views::keys) + AddCollider(&collider); + } + + isRigidBody = false; + } + + void SHPhysicsObject::DestroyCollisionBody() noexcept + { + // Remove all colliders + for (uint32_t i = 0; i < rp3dBody->getNbColliders(); ++i) + { + auto* collider = rp3dBody->getCollider(i); + rp3dBody->removeCollider(collider); + } + } + + void SHPhysicsObject::RemoveCollider(int index) + { + const int NUM_COLLIDERS = static_cast(rp3dBody->getNbColliders()); + if (NUM_COLLIDERS == 0) + return; + + if (index < 0 || index >= NUM_COLLIDERS) + throw std::invalid_argument("Index out of range!"); + + auto* collider = rp3dBody->getCollider(index); + rp3dBody->removeCollider(collider); + } + + void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent* rb) const noexcept + { + SHASSERT(rp3dBody != nullptr, "ReactPhysics body does not exist!") + + if (rb->dirtyFlags == 0) + return; + + auto* rigidBody = reinterpret_cast(rp3dBody); + + const uint16_t RB_FLAGS = rb->dirtyFlags; + for (size_t i = 0; i < SHRigidBodyComponent::NUM_DIRTY_FLAGS; ++i) + { + // Check if current dirty flag has been set to true + if (RB_FLAGS & 1U << i) + { + switch (i) + { + case 0: // Gravity + { + rigidBody->enableGravity(rb->IsGravityEnabled()); + break; + } + case 1: // Sleeping + { + rigidBody->setIsAllowedToSleep(rb->IsAllowedToSleep()); + break; + } + case 2: // Linear Constraints + { + const rp3d::Vector3 CONSTRAINTS + { + rb->flags & 1U << 2 ? 0.0f : 1.0f, + rb->flags & 1U << 3 ? 0.0f : 1.0f, + rb->flags & 1U << 4 ? 0.0f : 1.0f + }; + + + rigidBody->setLinearLockAxisFactor(CONSTRAINTS); + break; + } + case 3: // Angular Constraints + { + const rp3d::Vector3 CONSTRAINTS + { + rb->flags & 1U << 5 ? 0.0f : 1.0f, + rb->flags & 1U << 6 ? 0.0f : 1.0f, + rb->flags & 1U << 7 ? 0.0f : 1.0f + }; + + rigidBody->setAngularLockAxisFactor(CONSTRAINTS); + break; + } + case 4: // Type + { + rigidBody->setType(static_cast(rb->GetType())); + break; + } + case 5: // Mass + { + rigidBody->setMass(rb->GetMass()); + break; + } + case 6: // Drag + { + rigidBody->setLinearDamping(rb->GetDrag()); + break; + } + case 7: // Angular Drag + { + rigidBody->setAngularDamping(rb->GetAngularDrag()); + break; + } + case 8: // Linear Velocity + { + rigidBody->setLinearVelocity(rb->GetLinearVelocity()); + break; + } + case 9: // Angular Velocity + { + rigidBody->setAngularVelocity(rb->GetAngularVelocity()); + break; + } + default: break; + } + } + } + + rb->dirtyFlags = 0; + } + + void SHPhysicsObject::SyncColliders(SHColliderComponent* c) const noexcept + { + int index = 0; + for (auto& [collider, dirty] : c->colliders) + { + if (!dirty) + continue; + + // Update offsets + auto* rp3dCollider = rp3dBody->getCollider(index); + rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), SHQuaternion::Identity)); + + switch (collider.GetType()) + { + case SHCollider::Type::BOX: + { + const auto* box = reinterpret_cast(collider.GetShape()); + + auto* rp3dBoxShape = reinterpret_cast(rp3dCollider->getCollisionShape()); + rp3dBoxShape->setHalfExtents(box->GetHalfExtents()); + + break; + } + case SHCollider::Type::SPHERE: + { + const auto* sphere = reinterpret_cast(collider.GetShape()); + + auto* rp3dSphereShape = reinterpret_cast(rp3dCollider->getCollisionShape()); + rp3dSphereShape->setRadius(sphere->GetRadius()); + + break; + } + default: break; + } + + dirty = false; + ++index; + } + } + } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.h b/SHADE_Engine/src/Physics/SHPhysicsObject.h index cdff2f5b..39a85421 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.h +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.h @@ -13,9 +13,9 @@ #include // Project Headers -#include "Math/Vector/SHVec3.h" -#include "Math/SHQuaternion.h" -#include "ECS_Base/Entity/SHEntity.h" +#include "Math/Transform/SHTransformComponent.h" +#include "Components/SHRigidBodyComponent.h" +#include "Components/SHColliderComponent.h" namespace SHADE { @@ -31,15 +31,13 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ friend class SHPhysicsSystem; - friend class SHRigidBodyComponent; - friend class SHColliderComponent; public: /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHPhysicsObject () noexcept; + SHPhysicsObject (EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept; SHPhysicsObject (const SHPhysicsObject& rhs) noexcept = default; SHPhysicsObject (SHPhysicsObject&& rhs) noexcept = default; virtual ~SHPhysicsObject () noexcept; @@ -63,9 +61,24 @@ namespace SHADE /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetPosition (const SHVec3& position) noexcept; - void SetOrientation (const SHQuaternion& orientation) noexcept; - void SetRotation (const SHVec3& rotation) noexcept; + void SetPosition (const SHVec3& position) noexcept; + void SetOrientation (const SHQuaternion& orientation) noexcept; + void SetRotation (const SHVec3& rotation) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + void CreateRigidBody (const SHTransformComponent* tf, SHRigidBodyComponent* rb, SHColliderComponent* c); + void CreateCollisionBody (const SHTransformComponent* tf, SHColliderComponent* c); + int AddCollider (SHCollider* collider); + + void DestroyRigidBody (SHColliderComponent* c) noexcept; + void RemoveCollider (int index); + void DestroyCollisionBody () noexcept; + + void SyncRigidBody (SHRigidBodyComponent* rb) const noexcept; + void SyncColliders (SHColliderComponent* c) const noexcept; private: /*---------------------------------------------------------------------------------*/ @@ -76,14 +89,9 @@ namespace SHADE bool isRigidBody; bool hasColliders; + rp3d::PhysicsCommon* factory; + rp3d::PhysicsWorld* world; rp3d::CollisionBody* rp3dBody; // Can be either a collision body or a rigid body rp3d::Transform prevTransform; // Cached transform for interpolation - - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - - - }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp index f3a4c276..c5a7aa57 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp @@ -68,10 +68,7 @@ namespace SHADE if (world) { - const auto RP3D_GRAVITY = world->getGravity(); - result.x = RP3D_GRAVITY.x; - result.y = RP3D_GRAVITY.y; - result.z = RP3D_GRAVITY.z; + result = world->getGravity(); } else { @@ -112,8 +109,7 @@ namespace SHADE { if (world) { - const rp3d::Vector3 G { gravity.x, gravity.y, gravity.z }; - world->setGravity(G); + world->setGravity(gravity); } else { @@ -161,8 +157,7 @@ namespace SHADE { if (world) { - const rp3d::Vector3 G { settings.gravity.x, settings.gravity.y, settings.gravity.z }; - world->setGravity(G); + world->setGravity(settings.gravity); world->setNbIterationsVelocitySolver(settings.numVelocitySolverIterations); world->setNbIterationsPositionSolver(settings.numPositionSolverIterations); world->enableSleeping(settings.sleepingEnabled); @@ -207,69 +202,14 @@ namespace SHADE SHLOG_INFO("Adding a Rigidbody to the Physics World.") #endif - // Check if entity is already a physics object - auto* physicsObject = GetPhysicsObject(entityID); - if (!physicsObject) - { - physicsObject = &(map.emplace(entityID, SHPhysicsObject{}).first->second); - physicsObject->entityID = entityID; - } + auto* physicsObject = CreatePhysicsObject(entityID); - // Get entity transform - auto const* SHADE_TF = SHComponentManager::GetComponent_s(entityID); - - // Possibly redundant - if (!SHADE_TF) - { - SHComponentManager::AddComponent(entityID); - SHADE_TF = SHComponentManager::GetComponent(entityID); - } - - const SHVec3& SHADE_POS = SHADE_TF->GetWorldPosition(); - const SHVec3& SHADE_ROT = SHADE_TF->GetWorldRotation(); - - const rp3d::Vector3 RP3D_POS { SHADE_POS.x, SHADE_POS.y, SHADE_POS.z }; - const rp3d::Quaternion RP3D_ROT = rp3d::Quaternion::fromEulerAngles( SHADE_ROT.x, SHADE_ROT.y, SHADE_ROT.z ); - - const rp3d::Transform RP3D_TF { RP3D_POS, RP3D_ROT }; - - // If collider already exists - if (physicsObject->hasColliders) - world->destroyCollisionBody(physicsObject->rp3dBody); - - physicsObject->rp3dBody = world->createRigidBody(RP3D_TF); - physicsObject->isRigidBody = true; - - // Recreate colliders - if (physicsObject->hasColliders) - { - const auto& COLLIDERS = SHComponentManager::GetComponent(entityID)->GetColliders(); - for (const auto& collider : COLLIDERS | std::views::keys) - { - switch (collider.GetType()) - { - case SHCollider::Type::BOX: - { - SHBoundingBox* box = reinterpret_cast(collider.GetShape()); - const SHVec3& SHADE_EXTENTS = box->GetHalfExtents(); - - rp3d::Vector3 RP3D_EXTENTS { SHADE_EXTENTS.x, SHADE_EXTENTS.y, SHADE_EXTENTS.z }; - rp3d::BoxShape* newBox = factory.createBoxShape(RP3D_EXTENTS); - - // TODO(Diren): Handle offsets - physicsObject->rp3dBody->addCollider(newBox, RP3D_TF); - break; - } - case SHCollider::Type::SPHERE: - { - break; - } - // TODO(Diren): Add more collider shapes - default: break; - } - } - } - + physicsObject->CreateRigidBody + ( + EnsureTransform(entityID), + SHComponentManager::GetComponent(entityID), + SHComponentManager::GetComponent_s(entityID) + ); } void SHPhysicsSystem::AddCollider(EntityID entityID) noexcept @@ -278,63 +218,13 @@ namespace SHADE SHLOG_INFO("Adding a Collider to the Physics World.") #endif - // Check if entity is already a physics object - auto* physicsObject = GetPhysicsObject(entityID); - if (!physicsObject) - { - physicsObject = &(map.emplace(entityID, SHPhysicsObject{}).first->second); - physicsObject->entityID = entityID; - } + auto* physicsObject = CreatePhysicsObject(entityID); - // Get entity transform - auto const* SHADE_TF = SHComponentManager::GetComponent_s(entityID); - - // Possibly redundant - if (!SHADE_TF) - { - SHComponentManager::AddComponent(entityID); - SHADE_TF = SHComponentManager::GetComponent(entityID); - } - - const SHVec3& SHADE_POS = SHADE_TF->GetWorldPosition(); - const SHVec3& SHADE_ROT = SHADE_TF->GetWorldRotation(); - - const rp3d::Vector3 RP3D_POS { SHADE_POS.x, SHADE_POS.y, SHADE_POS.z }; - const rp3d::Quaternion RP3D_ROT = rp3d::Quaternion::fromEulerAngles( SHADE_ROT.x, SHADE_ROT.y, SHADE_ROT.z ); - - const rp3d::Transform RP3D_TF { RP3D_POS, RP3D_ROT }; - - // No rb - if (!physicsObject->isRigidBody) - physicsObject->rp3dBody = world->createCollisionBody(RP3D_TF); - - const auto& COLLIDERS = SHComponentManager::GetComponent(entityID)->GetColliders(); - for (const auto& collider : COLLIDERS | std::views::keys) - { - switch (collider.GetType()) - { - case SHCollider::Type::BOX: - { - SHBoundingBox* box = reinterpret_cast(collider.GetShape()); - const SHVec3& SHADE_EXTENTS = box->GetHalfExtents(); - - rp3d::Vector3 RP3D_EXTENTS { SHADE_EXTENTS.x, SHADE_EXTENTS.y, SHADE_EXTENTS.z }; - rp3d::BoxShape* newBox = factory.createBoxShape(RP3D_EXTENTS); - - // TODO(Diren): Handle offsets - physicsObject->rp3dBody->addCollider(newBox, RP3D_TF); - break; - } - case SHCollider::Type::SPHERE: - { - break; - } - // TODO(Diren): Add more collider shapes - default: break; - } - } - - physicsObject->hasColliders = true; + physicsObject->CreateCollisionBody + ( + EnsureTransform(entityID), + SHComponentManager::GetComponent(entityID) + ); } void SHPhysicsSystem::RemoveRigidBody(EntityID entityID) noexcept @@ -343,6 +233,13 @@ namespace SHADE SHLOG_INFO("Removing a Rigidbody from the Physics World.") #endif + auto* physicsObject = GetPhysicsObject(entityID); + SHASSERT(physicsObject != nullptr, "Physics object has been lost from the world!") + + physicsObject->DestroyRigidBody(SHComponentManager::GetComponent_s(entityID)); + + if (physicsObject->rp3dBody == nullptr) + DestroyPhysicsObject(entityID); } void SHPhysicsSystem::RemoveCollider(EntityID entityID) noexcept @@ -392,33 +289,10 @@ namespace SHADE } - void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHShape* shape) + void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHCollider* collider) { auto* physicsObject = GetPhysicsObject(entityID); - - switch (shape->GetType()) - { - case SHShape::Type::BOUNDING_BOX: - { - auto* box = reinterpret_cast(shape); - const SHVec3& SHADE_EXTENTS = box->GetHalfExtents(); - - rp3d::Vector3 RP3D_EXTENTS { SHADE_EXTENTS.x, SHADE_EXTENTS.y, SHADE_EXTENTS.z }; - rp3d::BoxShape* newBox = factory.createBoxShape(RP3D_EXTENTS); - - // TODO(Diren): Handle offsets - - rp3d::Transform tf = rp3d::Transform::identity(); - physicsObject->rp3dBody->addCollider(newBox, tf); - break; - } - case SHShape::Type::SPHERE: - { - break; - } - // TODO(Diren): Add more collider shapes - default: break; - } + physicsObject->AddCollider(collider); } void SHPhysicsSystem::RemoveCollisionShape(EntityID entityID, int index) @@ -475,6 +349,7 @@ namespace SHADE if (system->worldUpdated) { system->SyncTransforms(); + // TODO(Diren): Handle trigger messages for scripting } } @@ -483,6 +358,18 @@ namespace SHADE /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ + SHPhysicsObject* SHPhysicsSystem::CreatePhysicsObject(EntityID entityID) noexcept + { + const auto it = map.find(entityID); + if (it == map.end()) + { + auto* newPhysicsObject = &map.emplace(entityID, SHPhysicsObject{entityID, &factory, world}).first->second; + return newPhysicsObject; + } + + return &(it->second); + } + SHPhysicsObject* SHPhysicsSystem::GetPhysicsObject(EntityID entityID) noexcept { const auto it = map.find(entityID); @@ -495,6 +382,19 @@ namespace SHADE return &(it->second); } + void SHPhysicsSystem::DestroyPhysicsObject(EntityID entityID) noexcept + { + map.erase(entityID); + } + + void SHPhysicsSystem::SyncActiveStates(SHPhysicsObject* physicsObject, bool componentActive) noexcept + { + const bool RP3D_ACTIVE = physicsObject->rp3dBody->isActive(); + if (RP3D_ACTIVE != componentActive) + physicsObject->rp3dBody->setIsActive(componentActive); + } + + void SHPhysicsSystem::SyncRigidBodyComponents(std::vector& denseArray) noexcept { if (denseArray.empty()) @@ -505,23 +405,16 @@ namespace SHADE const EntityID ENTITY_ID = comp.GetEID(); // Get physicsObject - auto const* physicsObject = GetPhysicsObject(ENTITY_ID); + auto* physicsObject = GetPhysicsObject(ENTITY_ID); - const bool RP3D_ACTIVE = physicsObject->rp3dBody->isActive(); // TODO(Diren): Check if active in hierarchy const bool COMPONENT_ACTIVE = comp.isActive; - - if (RP3D_ACTIVE != COMPONENT_ACTIVE) - physicsObject->rp3dBody->setIsActive(COMPONENT_ACTIVE); + SyncActiveStates(physicsObject, COMPONENT_ACTIVE); if (!COMPONENT_ACTIVE) continue; - if (comp.dirtyFlags > 0) - { - SyncRigidBody(physicsObject, &comp); - comp.dirtyFlags = 0; - } + physicsObject->SyncRigidBody(&comp); } } @@ -535,29 +428,23 @@ namespace SHADE const EntityID ENTITY_ID = comp.GetEID(); // Get physicsObject - auto const* physicsObject = GetPhysicsObject(ENTITY_ID); + auto* physicsObject = GetPhysicsObject(ENTITY_ID); - const bool RP3D_ACTIVE = physicsObject->rp3dBody->isActive(); // TODO(Diren): Check if active in hierarchy const bool COMPONENT_ACTIVE = comp.isActive; - - if (RP3D_ACTIVE != COMPONENT_ACTIVE) - physicsObject->rp3dBody->setIsActive(COMPONENT_ACTIVE); + SyncActiveStates(physicsObject, COMPONENT_ACTIVE); if (!COMPONENT_ACTIVE) continue; - SyncCollider(physicsObject, &comp); + physicsObject->SyncColliders(&comp); } } void SHPhysicsSystem::SyncTransforms() noexcept { - for (auto& pair : map) + for (auto& [entityID, physicsObject] : map) { - const EntityID ENTITY_ID = pair.first; - SHPhysicsObject& physicsObject = pair.second; - rp3d::Vector3 rp3dPos; rp3d::Quaternion rp3dRot; @@ -567,7 +454,7 @@ namespace SHADE if (physicsObject.isRigidBody) { - auto const* rbComponent = SHComponentManager::GetComponent(ENTITY_ID); + auto* rbComponent = SHComponentManager::GetComponent(entityID); if (rbComponent->GetType() == SHRigidBodyComponent::Type::STATIC) continue; @@ -585,6 +472,16 @@ namespace SHADE rp3dPos = CURRENT_TF.getPosition(); rp3dRot = CURRENT_TF.getOrientation(); } + + rbComponent->position = CURRENT_TF.getPosition(); + rbComponent->orientation = CURRENT_TF.getOrientation(); + + if (physicsObject.hasColliders) + { + auto* colliderComponent = SHComponentManager::GetComponent(entityID); + colliderComponent->position = CURRENT_TF.getPosition(); + colliderComponent->orientation = CURRENT_TF.getOrientation(); + } } else { @@ -593,155 +490,29 @@ namespace SHADE } // Convert RP3D Transform to SHADE - const SHVec3 SHADE_POS = SHVec3{ rp3dPos.x, rp3dPos.y, rp3dPos.z }; - const SHVec3 SHADE_ROT = SHQuaternion{ rp3dRot.x, rp3dRot.y, rp3dRot.z, rp3dRot.w }.ToEuler(); + auto* tfComponent = SHComponentManager::GetComponent(entityID); + tfComponent->SetWorldPosition(rp3dPos); + tfComponent->SetWorldRotation(SHQuaternion{ rp3dRot }.ToEuler()); - auto* tfComponent = SHComponentManager::GetComponent(ENTITY_ID); - tfComponent->SetWorldPosition(SHADE_POS); - tfComponent->SetWorldRotation(SHADE_ROT); // Cache transforms physicsObject.prevTransform = CURRENT_TF; } } - void SHPhysicsSystem::SyncRigidBody(SHPhysicsObject const* physicsObject, const SHRigidBodyComponent* comp) noexcept + SHTransformComponent* SHPhysicsSystem::EnsureTransform(EntityID entityID) { - auto* rigidBody = reinterpret_cast(physicsObject->rp3dBody); + auto* tf = SHComponentManager::GetComponent_s(entityID); - const uint16_t RB_FLAGS = comp->dirtyFlags; - const size_t NUM_FLAGS = sizeof(RB_FLAGS) * 8U; - for (size_t i = 0; i < NUM_FLAGS; ++i) + // Possibly redundant + if (!tf) { - // Check if current dirty flag has been set to true - if (RB_FLAGS & 1U << i) - { - switch (i) - { - case 0: // Gravity - { - rigidBody->enableGravity(comp->IsGravityEnabled()); - break; - } - case 1: // Sleeping - { - rigidBody->setIsAllowedToSleep(comp->IsAllowedToSleep()); - break; - } - case 2: // Linear Constraints - { - SetRP3DLinearConstraints(rigidBody, comp->flags); - break; - } - case 3: // Angular Constraints - { - SetRP3DAngularConstraints(rigidBody, comp->flags); - break; - } - case 4: // Type - { - rigidBody->setType(static_cast(comp->GetType())); - break; - } - case 5: // Mass - { - rigidBody->setMass(comp->GetMass()); - break; - } - case 6: // Drag - { - rigidBody->setLinearDamping(comp->GetDrag()); - break; - } - case 7: // Angular Drag - { - rigidBody->setAngularDamping(comp->GetAngularDrag()); - break; - } - case 8: // Linear Velocity - { - const SHVec3& SHADE_VEL = comp->GetLinearVelocity(); - rp3d::Vector3 RP3D_VEL { SHADE_VEL.x, SHADE_VEL.y, SHADE_VEL.z }; - - rigidBody->setLinearVelocity(RP3D_VEL); - break; - } - case 9: // Angular Velocity - { - const SHVec3& SHADE_VEL = comp->GetAngularVelocity(); - rp3d::Vector3 RP3D_VEL { SHADE_VEL.x, SHADE_VEL.y, SHADE_VEL.z }; - - rigidBody->setAngularVelocity(RP3D_VEL); - break; - } - default: break; - } - } + SHComponentManager::AddComponent(entityID); + tf = SHComponentManager::GetComponent(entityID); } + + return tf; } - void SHPhysicsSystem::SetRP3DLinearConstraints(rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept - { - const rp3d::Vector3 CONSTRAINTS - { - rbFlags & 1U << 2 ? 0.0f : 1.0f, - rbFlags & 1U << 3 ? 0.0f : 1.0f, - rbFlags & 1U << 4 ? 0.0f : 1.0f - }; - - - rp3dRigidBody->setLinearLockAxisFactor(CONSTRAINTS); - } - - void SHPhysicsSystem::SetRP3DAngularConstraints(rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept - { - const rp3d::Vector3 CONSTRAINTS - { - rbFlags & 1U << 5 ? 0.0f : 1.0f, - rbFlags & 1U << 6 ? 0.0f : 1.0f, - rbFlags & 1U << 7 ? 0.0f : 1.0f - }; - - rp3dRigidBody->setAngularLockAxisFactor(CONSTRAINTS); - } - - void SHPhysicsSystem::SyncCollider(SHPhysicsObject const* physicsObject, SHColliderComponent* comp) noexcept - { - int index = 0; - for (auto& [collider, dirty] : comp->colliders) - { - if (!dirty) - continue; - - switch (collider.GetType()) - { - case SHCollider::Type::BOX: - { - SHBoundingBox* box = reinterpret_cast(collider.GetShape()); - const SHVec3& SHADE_EXTENTS = box->GetHalfExtents(); - - rp3d::Vector3 RP3D_EXTENTS { SHADE_EXTENTS.x, SHADE_EXTENTS.y, SHADE_EXTENTS.z }; - - auto* rp3dBoxShape = reinterpret_cast(physicsObject->rp3dBody->getCollider(index)->getCollisionShape()); - rp3dBoxShape->setHalfExtents(RP3D_EXTENTS); - - if (rp3dBoxShape) - { - SHLOG_INFO("Updating box things") - } - - break; - } - case SHCollider::Type::SPHERE: - { - break; - } - default: break; - } - - dirty = false; - ++index; - } - } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/SHPhysicsSystem.h index 4eaf4a89..bc6a1ba2 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.h @@ -19,6 +19,7 @@ #include "SHPhysicsObject.h" #include "Components/SHRigidBodyComponent.h" #include "Components/SHColliderComponent.h" +#include "Math/Transform/SHTransformComponent.h" #include "Scene/SHSceneGraph.h" #include "ECS_Base/System/SHSystemRoutine.h" @@ -81,8 +82,8 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - void Init () override; - void Exit () override; + void Init () override; + void Exit () override; void AddRigidBody (EntityID entityID) noexcept; void AddCollider (EntityID entityID) noexcept; @@ -100,7 +101,7 @@ namespace SHADE void AddTorque (EntityID entityID, const SHVec3& torque) const noexcept; void AddRelativeTorque (EntityID entityID, const SHVec3& relativeTorque) const noexcept; - void AddCollisionShape (EntityID entityID, SHShape* shape); + void AddCollisionShape (EntityID entityID, SHCollider* collider); void RemoveCollisionShape (EntityID entityID, int index); /*---------------------------------------------------------------------------------*/ @@ -185,18 +186,18 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept; + SHPhysicsObject* CreatePhysicsObject (EntityID entityID) noexcept; + SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept; + void DestroyPhysicsObject (EntityID entityID) noexcept; - void SyncRigidBodyComponents (std::vector& denseArray) noexcept; - void SyncColliderComponents (std::vector& denseArray) noexcept; - void SyncTransforms () noexcept; + void SyncActiveStates (SHPhysicsObject* physicsObject, bool componentActive) noexcept; + void SyncRigidBodyComponents (std::vector& denseArray) noexcept; + void SyncColliderComponents (std::vector& denseArray) noexcept; + void SyncTransforms () noexcept; // TODO(Diren): Trigger handling - static void SyncRigidBody (SHPhysicsObject const* physicsObject, const SHRigidBodyComponent* comp) noexcept; - static void SetRP3DLinearConstraints (rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept; - static void SetRP3DAngularConstraints (rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept; - - static void SyncCollider (SHPhysicsObject const* physicsObject, SHColliderComponent* comp) noexcept; + // TODO(Diren): Remove when responsibility shifted to editor + SHTransformComponent* EnsureTransform (EntityID entityID); }; diff --git a/SHADE_Managed/premake5.lua b/SHADE_Managed/premake5.lua index 052be24a..6d37122c 100644 --- a/SHADE_Managed/premake5.lua +++ b/SHADE_Managed/premake5.lua @@ -30,8 +30,9 @@ project "SHADE_Managed" "%{IncludeDir.imguizmo}", "%{IncludeDir.imnodes}", "%{IncludeDir.yamlcpp}", - "%{IncludeDir.RTTR}/include", + "%{IncludeDir.RTTR}/include", "%{IncludeDir.dotnet}\\include", + "%{IncludeDir.reactphysics3d}\\include", "%{wks.location}/SHADE_Engine/src" }