From 887dbe7b497246e7fc5f07080ac771276a5b92f8 Mon Sep 17 00:00:00 2001 From: Danilo Date: Thu, 16 May 2024 17:23:52 -0300 Subject: [PATCH] Implementa BoundingFrustum --- framework/CMakeLists.txt | 6 +- framework/common/collision.cpp | 199 +++++++++++++++++++++++++++ framework/common/gjk.cpp | 104 ++++++++++++++ inc/common/collision.hpp | 239 +++++++++++++++++++++++++++++++++ inc/common/gjk.hpp | 71 ++++++++++ inc/common/math.hpp | 12 +- inc/common/point.hpp | 14 +- inc/common/rectangle.hpp | 15 ++- inc/common/vectors.hpp | 16 ++- inc/enums.hpp | 14 +- inc/forward.hpp | 20 +-- inc/xna.hpp | 3 +- 12 files changed, 679 insertions(+), 34 deletions(-) create mode 100644 framework/common/collision.cpp create mode 100644 framework/common/gjk.cpp create mode 100644 inc/common/collision.hpp create mode 100644 inc/common/gjk.hpp diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt index cebfb03..da8dfe6 100644 --- a/framework/CMakeLists.txt +++ b/framework/CMakeLists.txt @@ -47,7 +47,11 @@ add_executable (xna WIN32 "platform/init-dx.cpp" "game/servicecontainer.cpp" "common/color.cpp" -"common/math.cpp" "common/quaternion.cpp") +"common/math.cpp" +"common/quaternion.cpp" +"common/collision.cpp" +"common/gjk.cpp" +) if (CMAKE_VERSION VERSION_GREATER 3.12) set_property(TARGET xna PROPERTY CXX_STANDARD 20) diff --git a/framework/common/collision.cpp b/framework/common/collision.cpp new file mode 100644 index 0000000..d8c8f55 --- /dev/null +++ b/framework/common/collision.cpp @@ -0,0 +1,199 @@ +#include "common/collision.hpp" + +namespace xna { + bool BoundingFrustum::Intersects(BoundingBox const& box) { + gjk.Reset(); + Vector3 result1 = Vector3::Subtract(corners[0], box.Min); + + if (result1.LengthSquared() < 9.9999997473787516E-06) + result1 = Vector3::Subtract(corners[0], box.Max); + + auto num1 = FloatMaxValue; + float num2 = 0; + do + { + Vector3 v; + v.X = -result1.X; + v.Y = -result1.Y; + v.Z = -result1.Z; + Vector3 result2; + SupportMapping(v, result2); + Vector3 result3; + box.SupportMapping(result1, result3); + Vector3 result4 = Vector3::Subtract(result2, result3); + + if (result1.X * result4.X + result1.Y * result4.Y + result1.Z * result4.Z > 0.0) + return false; + + gjk.AddSupportPoint(result4); + result1 = gjk.ClosestPoint(); + float num3 = num1; + num1 = result1.LengthSquared(); + + if (num3 - num1 <= 9.9999997473787516E-06 * num3) + return false; + + num2 = 4E-05f * gjk.MaxLengthSquared(); + } while (!gjk.FullSimplex() && num1 >= num2); + + return true; + } + + std::optional BoundingFrustum::Intersects(Ray const& ray) const { + auto result1 = Contains(ray.Position); + + if (result1 == ContainmentType::Contains) + return 0.0F; + + auto num1 = FloatMinValue; + auto num2 = FloatMaxValue; + + for (size_t i = 0; i < planes.size(); ++i) { + const auto& plane = planes[i]; + + Vector3 normal = plane.Normal; + const auto result2 = Vector3::Dot(ray.Direction, normal); + float result3 = Vector3::Dot(ray.Position, normal); + + result3 += plane.D; + + if (std::abs(static_cast(result2)) < 9.9999997473787516E-06) + { + if (result3 > 0.0) + return {}; + } + else + { + const auto num3 = -result3 / result2; + if (result2 < 0.0) + { + if (num3 > num2) + return {}; + if (num3 > num1) + num1 = num3; + } + else + { + if (num3 < num1) + return {}; + if (num3 < num2) + num2 = num3; + } + } + } + + auto num4 = num1 >= 0.0F ? num1 : num2; + + if (num4 < 0.0) + return{}; + + return num4; + } + + bool BoundingFrustum::Intersects(BoundingSphere const& sphere) { + gjk.Reset(); + auto result1 = Vector3::Subtract(corners[0], sphere.Center); + + if (result1.LengthSquared() < 9.9999997473787516E-06) + result1 = Vector3::UnitX(); + + auto num1 = FloatMaxValue; + auto num2 = 0.0F; + + do + { + Vector3 v; + v.X = -result1.X; + v.Y = -result1.Y; + v.Z = -result1.Z; + + Vector3 result2; + SupportMapping(v, result2); + + Vector3 result3; + sphere.SupportMapping(result1, result3); + + Vector3 result4 = Vector3::Subtract(result2, result3); + + if (result1.X * result4.X + result1.Y * result4.Y + result1.Z * result4.Z > 0.0) + return false; + + gjk.AddSupportPoint(result4); + + result1 = gjk.ClosestPoint(); + + auto num3 = num1; + + num1 = result1.LengthSquared(); + + if (num3 - num1 <= 9.9999997473787516E-06 * num3) + return false; + + num2 = 4E-05f * gjk.MaxLengthSquared(); + + } while (!gjk.FullSimplex() && num1 >= num2); + + return true; + } + + bool BoundingFrustum::Intersects(BoundingFrustum const& frustum) { + gjk.Reset(); + Vector3 result1 = Vector3::Subtract(corners[0], frustum.corners[0]); + + if (result1.LengthSquared() < 9.9999997473787516E-06) + result1 = Vector3::Subtract(corners[0], frustum.corners[1]); + + float num1 = FloatMaxValue; + float num2 = 0; + + do + { + Vector3 v; + v.X = -result1.X; + v.Y = -result1.Y; + v.Z = -result1.Z; + + Vector3 result2; + SupportMapping(v, result2); + + Vector3 result3; + frustum.SupportMapping(result1, result3); + + const auto result4 = Vector3::Subtract(result2, result3); + + if (result1.X * result4.X + result1.Y * result4.Y + result1.Z * result4.Z > 0.0) + return false; + + gjk.AddSupportPoint(result4); + + result1 = gjk.ClosestPoint(); + + const auto num3 = num1; + + num1 = result1.LengthSquared(); + num2 = 4E-05f * gjk.MaxLengthSquared(); + + if (num3 - num1 <= 9.9999997473787516E-06 * num3) + return false; + + } while (!gjk.FullSimplex() && num1 >= num2); + return true; + } + + ContainmentType BoundingFrustum::Contains(BoundingFrustum const& frustum) { + ContainmentType containmentType = ContainmentType::Disjoint; + + if (Intersects(frustum)) { + containmentType = ContainmentType::Contains; + + for (size_t index = 0; index < corners.size(); ++index) { + if (Contains(frustum.corners[index]) == ContainmentType::Disjoint) + { + containmentType = ContainmentType::Intersects; + break; + } + } + } + return containmentType; + } +} \ No newline at end of file diff --git a/framework/common/gjk.cpp b/framework/common/gjk.cpp new file mode 100644 index 0000000..d4d3811 --- /dev/null +++ b/framework/common/gjk.cpp @@ -0,0 +1,104 @@ +#include "common/gjk.hpp" + +namespace xna { + Vector3 Gjk::ComputeClosestPoint() { + auto num1 = 0.0f; + Vector3 zero = Vector3::Zero(); + maxLengthSq = 0.0f; + + for (auto bitsToIndex = Gjk::BitsToIndices[simplexBits]; bitsToIndex != 0; bitsToIndex >>= 3) + { + auto index = (bitsToIndex & 7) - 1; + auto num2 = det[simplexBits][index]; + num1 += num2; + zero += y[index] * num2; + maxLengthSq = MathHelper::Max(maxLengthSq, yLengthSq[index]); + } + + return zero / num1; + } + + bool Gjk::UpdateSimplex(Int newIndex) { + auto yBits = simplexBits | 1 << newIndex; + auto xBits = 1 << newIndex; + for (auto sb = simplexBits; sb != 0; --sb) + { + if ((sb & yBits) == sb && IsSatisfiesRule(sb | xBits, yBits)) + { + simplexBits = sb | xBits; + closestPoint = ComputeClosestPoint(); + return true; + } + } + + bool flag = false; + + if (IsSatisfiesRule(xBits, yBits)) { + simplexBits = xBits; + closestPoint = y[newIndex]; + maxLengthSq = yLengthSq[newIndex]; + flag = true; + } + + return flag; + } + + void Gjk::UpdateDeterminant(Int xmIdx) { + auto index1 = 1 << xmIdx; + det[index1][xmIdx] = 1.0f; + auto bitsToIndex = Gjk::BitsToIndices[simplexBits]; + auto num1 = bitsToIndex; + auto num2 = 0; + while (num1 != 0) + { + auto index2 = (num1 & 7) - 1; + auto num3 = 1 << index2; + auto index3 = num3 | index1; + det[index3][index2] = Vector3::Dot(edges[xmIdx][index2], y[xmIdx]); + det[index3][xmIdx] = Vector3::Dot(edges[index2][xmIdx], y[index2]); + auto num4 = bitsToIndex; + for (auto index4 = 0; index4 < num2; ++index4) + { + auto index5 = (num4 & 7) - 1; + auto num5 = 1 << index5; + auto index6 = index3 | num5; + auto index7 = Gjk::edgeLengthSq[index2][index5] < Gjk::edgeLengthSq[xmIdx][index5] ? index2 : xmIdx; + det[index6][index5] = (Gjk::det[index3][index2] * Vector3::Dot(edges[index7][index5], y[index2]) + Gjk::det[index3][xmIdx] * Vector3::Dot(edges[index7][index5], y[xmIdx])); + auto index8 = Gjk::edgeLengthSq[index5][index2] < Gjk::edgeLengthSq[xmIdx][index2] ? index5 : xmIdx; + det[index6][index2] = (Gjk::det[num5 | index1][index5] * Vector3::Dot(edges[index8][index2], y[index5]) + Gjk::det[num5 | index1][xmIdx] * Vector3::Dot(edges[index8][index2], y[xmIdx])); + auto index9 = Gjk::edgeLengthSq[index2][xmIdx] < Gjk::edgeLengthSq[index5][xmIdx] ? index2 : index5; + det[index6][xmIdx] = (Gjk::det[num3 | num5][index5] * Vector3::Dot(edges[index9][xmIdx], y[index5]) + Gjk::det[num3 | num5][index2] * Vector3::Dot(edges[index9][xmIdx], y[index2])); + num4 >>= 3; + } + num1 >>= 3; + ++num2; + } + + if ((simplexBits | index1) != 15) + return; + auto index10 = Gjk::edgeLengthSq[1][0] < Gjk::edgeLengthSq[2][0] ? (Gjk::edgeLengthSq[1][0] < Gjk::edgeLengthSq[3][0] ? 1 : 3) : (Gjk::edgeLengthSq[2][0] < Gjk::edgeLengthSq[3][0] ? 2 : 3); + det[15][0] = (Gjk::det[14][1] * Vector3::Dot(edges[index10][0], y[1]) + Gjk::det[14][2] * Vector3::Dot(edges[index10][0], y[2]) + Gjk::det[14][3] * Vector3::Dot(edges[index10][0], y[3])); + auto index11 = Gjk::edgeLengthSq[0][1] < Gjk::edgeLengthSq[2][1] ? (Gjk::edgeLengthSq[0][1] < Gjk::edgeLengthSq[3][1] ? 0 : 3) : (Gjk::edgeLengthSq[2][1] < Gjk::edgeLengthSq[3][1] ? 2 : 3); + det[15][1] = (Gjk::det[13][0] * Vector3::Dot(edges[index11][1], y[0]) + Gjk::det[13][2] * Vector3::Dot(edges[index11][1], y[2]) + Gjk::det[13][3] * Vector3::Dot(edges[index11][1], y[3])); + auto index12 = Gjk::edgeLengthSq[0][2] < Gjk::edgeLengthSq[1][2] ? (Gjk::edgeLengthSq[0][2] < Gjk::edgeLengthSq[3][2] ? 0 : 3) : (Gjk::edgeLengthSq[1][2] < Gjk::edgeLengthSq[3][2] ? 1 : 3); + det[15][2] = (Gjk::det[11][0] * Vector3::Dot(edges[index12][2], y[0]) + Gjk::det[11][1] * Vector3::Dot(edges[index12][2], y[1]) + Gjk::det[11][3] * Vector3::Dot(edges[index12][2], y[3])); + auto index13 = Gjk::edgeLengthSq[0][3] < Gjk::edgeLengthSq[1][3] ? (Gjk::edgeLengthSq[0][3] < Gjk::edgeLengthSq[2][3] ? 0 : 2) : (Gjk::edgeLengthSq[1][3] < Gjk::edgeLengthSq[2][3] ? 1 : 2); + det[15][3] = (Gjk::det[7][0] * Vector3::Dot(edges[index13][3], y[0]) + Gjk::det[7][1] * Vector3::Dot(edges[index13][3], y[1]) + Gjk::det[7][2] * Vector3::Dot(edges[index13][3], y[2])); + } + + bool Gjk::AddSupportPoint(Vector3 const& newPoint) { + auto index1 = (Gjk::BitsToIndices[simplexBits ^ 15] & 7) - 1; + y[index1] = newPoint; + yLengthSq[index1] = newPoint.LengthSquared(); + for (auto bitsToIndex = Gjk::BitsToIndices[simplexBits]; bitsToIndex != 0; bitsToIndex >>= 3) + { + auto index2 = (bitsToIndex & 7) - 1; + Vector3 vector3 = y[index2] - newPoint; + edges[index2][index1] = vector3; + edges[index1][index2] = -vector3; + edgeLengthSq[index1][index2] = edgeLengthSq[index2][index1] = vector3.LengthSquared(); + } + UpdateDeterminant(index1); + return UpdateSimplex(index1); + } +} \ No newline at end of file diff --git a/inc/common/collision.hpp b/inc/common/collision.hpp new file mode 100644 index 0000000..a194684 --- /dev/null +++ b/inc/common/collision.hpp @@ -0,0 +1,239 @@ +#ifndef XNA_COMMON_SHAPES_HPP +#define XNA_COMMON_SHAPES_HPP + +#include "default.hpp" +#include "vectors.hpp" +#include "matrix.hpp" +#include "gjk.hpp" +#include + +namespace xna { + struct Plane { + Vector3 Normal{ 0 }; + float D{ 0 }; + }; + + struct BoundingFrustum { + inline static constexpr int CornerCount = 8; + inline static constexpr int PlaneCount = 6; + + Plane Near() { return planes[0]; } + Plane Far() { return planes[1]; } + Plane Left() { return planes[2]; } + Plane Right() { return planes[3]; } + Plane Top() { return planes[4]; } + Plane Bottom() { return planes[5]; } + + constexpr bool operator==(BoundingFrustum const& other) const { + return matrix == other.matrix; + } + + constexpr void GetCorners(std::vector& destination) const; + constexpr Matrix GetMatrix() const { return matrix; } + constexpr void SetMatrix(Matrix const& value); + bool Intersects(BoundingBox const& box); + bool Intersects(BoundingSphere const& box); + constexpr PlaneIntersectionType Intersects(Plane const& plane) const; + bool Intersects(BoundingFrustum const& frustum); + std::optional Intersects(Ray const& ray) const; + constexpr ContainmentType Contains(BoundingBox const& box) const; + ContainmentType Contains(BoundingFrustum const& box); + constexpr ContainmentType Contains(Vector3 const& point) const; + constexpr ContainmentType Contains(BoundingSphere const& box) const; + constexpr void SupportMapping(Vector3 const& v, Vector3& result) const; + + private: + std::vector planes{ 6 }; + std::vector corners{ 8 }; + Matrix matrix{ Matrix::Identity() }; + Gjk gjk{}; + + private: + static constexpr Ray ComputeIntersectionLine(Plane const& p1, Plane const& p2); + static constexpr Vector3 ComputeIntersection(Plane const& plane, Ray const& ray); + }; + + struct BoundingBox { + Vector3 Min{}; + Vector3 Max{}; + + constexpr PlaneIntersectionType Intersects(Plane const& plane) const { + return PlaneIntersectionType::Intersecting; + } + + void SupportMapping(Vector3 const& v, Vector3& result) const { + + } + }; + + struct BoundingSphere { + Vector3 Center{}; + float Radius{ 0 }; + + void SupportMapping(Vector3 const& v, Vector3& result) const { + //TODO + } + }; + + struct Ray { + Vector3 Position{}; + Vector3 Direction{}; + }; + + //---------------------------------------------------------------------------------// + // IMPLEMENTATIONS // + //---------------------------------------------------------------------------------// + + constexpr void BoundingFrustum::GetCorners(std::vector& destination) const { + if (destination.size() < CornerCount) + destination.resize(CornerCount); + + for (size_t i = 0; i < CornerCount; ++i) + destination[i] = corners[i]; + } + + constexpr Ray BoundingFrustum::ComputeIntersectionLine(Plane const& p1, Plane const& p2) { + Ray intersectionLine{}; + intersectionLine.Direction = Vector3::Cross(p1.Normal, p2.Normal); + const auto num = intersectionLine.Direction.LengthSquared(); + intersectionLine.Position = Vector3::Cross(-p1.D * p2.Normal + p2.D * p1.Normal, intersectionLine.Direction) / num; + return intersectionLine; + } + + constexpr Vector3 BoundingFrustum::ComputeIntersection(Plane const& plane, Ray const& ray) { + const auto num = (-plane.D - Vector3::Dot(plane.Normal, ray.Position)) / Vector3::Dot(plane.Normal, ray.Direction); + return ray.Position + ray.Direction * num; + } + + constexpr void BoundingFrustum::SupportMapping(Vector3 const& v, Vector3& result) const { + size_t index1 = 0; + auto result1 = Vector3::Dot(corners[0], v); + + for (size_t index2 = 1; index2 < CornerCount; ++index2) + { + auto result2 = Vector3::Dot(corners[index2], v); + if (result2 > result1) + { + index1 = index2; + result1 = result2; + } + } + result = corners[index1]; + } + + constexpr PlaneIntersectionType BoundingFrustum::Intersects(Plane const& plane) const { + int num = 0; + for (size_t index = 0; index < CornerCount; ++index) + { + auto result = Vector3::Dot(corners[index], plane.Normal); + + if (result + plane.D > 0.0F) + num |= 1; + else + num |= 2; + + if (num == 3) + return PlaneIntersectionType::Intersecting; + } + return num != 1 ? PlaneIntersectionType::Back : PlaneIntersectionType::Front; + } + + constexpr ContainmentType BoundingFrustum::Contains(Vector3 const& point) const { + for (size_t i = 0; i < PlaneCount; ++i) { + const auto& plane = planes[i]; + + if ((static_cast(plane.Normal.X * point.X + plane.Normal.Y * point.Y + plane.Normal.Z * point.Z) + plane.D) > 9.9999997473787516E-06) + return ContainmentType::Disjoint; + } + + return ContainmentType::Contains; + } + + constexpr ContainmentType BoundingFrustum::Contains(BoundingBox const& box) const { + bool flag = false; + for (size_t i = 0; i < PlaneCount; ++i) + { + const auto& plane = planes[i]; + + switch (box.Intersects(plane)) + { + case PlaneIntersectionType::Front: + return ContainmentType::Disjoint; + case PlaneIntersectionType::Intersecting: + flag = true; + break; + } + } + return !flag ? ContainmentType::Contains : ContainmentType::Intersects; + } + + constexpr ContainmentType BoundingFrustum::Contains(BoundingSphere const& sphere) const { + auto center = sphere.Center; + auto radius = sphere.Radius; + auto num1 = 0; + for (size_t i = 0; i < PlaneCount; ++i) + { + const auto& plane = planes[i]; + + auto num2 = (plane.Normal.X * center.X + plane.Normal.Y * center.Y + plane.Normal.Z * center.Z) + plane.D; + + if (num2 > radius) + return ContainmentType::Disjoint; + + if (num2 < -radius) + ++num1; + } + + return num1 != 6 ? ContainmentType::Intersects : ContainmentType::Contains; + } + + constexpr void BoundingFrustum::SetMatrix(Matrix const& value) { + matrix = value; + planes[2].Normal.X = -value.M14 - value.M11; + planes[2].Normal.Y = -value.M24 - value.M21; + planes[2].Normal.Z = -value.M34 - value.M31; + planes[2].D = -value.M44 - value.M41; + planes[3].Normal.X = -value.M14 + value.M11; + planes[3].Normal.Y = -value.M24 + value.M21; + planes[3].Normal.Z = -value.M34 + value.M31; + planes[3].D = -value.M44 + value.M41; + planes[4].Normal.X = -value.M14 + value.M12; + planes[4].Normal.Y = -value.M24 + value.M22; + planes[4].Normal.Z = -value.M34 + value.M32; + planes[4].D = -value.M44 + value.M42; + planes[5].Normal.X = -value.M14 - value.M12; + planes[5].Normal.Y = -value.M24 - value.M22; + planes[5].Normal.Z = -value.M34 - value.M32; + planes[5].D = -value.M44 - value.M42; + planes[0].Normal.X = -value.M13; + planes[0].Normal.Y = -value.M23; + planes[0].Normal.Z = -value.M33; + planes[0].D = -value.M43; + planes[1].Normal.X = -value.M14 + value.M13; + planes[1].Normal.Y = -value.M24 + value.M23; + planes[1].Normal.Z = -value.M34 + value.M33; + planes[1].D = -value.M44 + value.M43; + + for (size_t index = 0; index < PlaneCount; ++index) + { + const auto num = planes[index].Normal.Length(); + planes[index].Normal = planes[index].Normal / num; + planes[index].D /= num; + } + + Ray intersectionLine1 = BoundingFrustum::ComputeIntersectionLine(planes[0], planes[2]); + corners[0] = BoundingFrustum::ComputeIntersection(planes[4], intersectionLine1); + corners[3] = BoundingFrustum::ComputeIntersection(planes[5], intersectionLine1); + Ray intersectionLine2 = BoundingFrustum::ComputeIntersectionLine(planes[3], planes[0]); + corners[1] = BoundingFrustum::ComputeIntersection(planes[4], intersectionLine2); + corners[2] = BoundingFrustum::ComputeIntersection(planes[5], intersectionLine2); + intersectionLine2 = BoundingFrustum::ComputeIntersectionLine(planes[2], planes[1]); + corners[4] = BoundingFrustum::ComputeIntersection(planes[4], intersectionLine2); + corners[7] = BoundingFrustum::ComputeIntersection(planes[5], intersectionLine2); + intersectionLine2 = BoundingFrustum::ComputeIntersectionLine(planes[1], planes[3]); + corners[5] = BoundingFrustum::ComputeIntersection(planes[4], intersectionLine2); + corners[6] = BoundingFrustum::ComputeIntersection(planes[5], intersectionLine2); + } +} + +#endif \ No newline at end of file diff --git a/inc/common/gjk.hpp b/inc/common/gjk.hpp new file mode 100644 index 0000000..a857579 --- /dev/null +++ b/inc/common/gjk.hpp @@ -0,0 +1,71 @@ +#ifndef XNA_COMMON_GDK_HPP +#define XNA_COMMON_GDK_HPP + +#include "default.hpp" +#include "vectors.hpp" +#include "math.hpp" + +namespace xna { + class Gjk { + public: + constexpr Gjk() = default; + + constexpr bool FullSimplex() const { return simplexBits == 15; } + constexpr float MaxLengthSquared() const { return maxLengthSq; } + constexpr Vector3 ClosestPoint() const { return closestPoint; } + + constexpr void Reset() { + simplexBits = 0; + maxLengthSq = 0.0f; + } + + bool AddSupportPoint(Vector3 const& newPoint); + + private: + using listv3 = std::vector; + using listv3v3 = std::vector>; + using listf = std::vector; + using listff = std::vector>; + + void UpdateDeterminant(Int xmIdx); + bool UpdateSimplex(Int newIndex); + Vector3 ComputeClosestPoint(); + + constexpr bool IsSatisfiesRule(Int xBits, Int yBits) const { + bool flag = true; + for (auto bitsToIndex = Gjk::BitsToIndices[yBits]; bitsToIndex != 0; bitsToIndex >>= 3) + { + auto index = (bitsToIndex & 7) - 1; + auto num = 1 << index; + + if ((num & xBits) != 0) { + if (static_cast(det[xBits][index]) <= 0.0F) { + flag = false; + break; + } + } + else if (static_cast(det[xBits | num][index]) > 0.0F) { + flag = false; + break; + } + } + return flag; + } + + private: + inline static auto BitsToIndices = std::vector { + 0, 1, 2, 17, 3, 25, 26, 209, 4, 33, 34, 273, 35, 281, 282, 2257 + }; + + Vector3 closestPoint{}; + Int simplexBits{0}; + float maxLengthSq{0}; + listv3 y = listv3(4); + listf yLengthSq = listf(4); + listv3v3 edges = listv3v3(4, listv3(4)); + listff edgeLengthSq = listff(4, listf(4)); + listff det = listff(16, listf(4)); + }; +} + +#endif \ No newline at end of file diff --git a/inc/common/math.hpp b/inc/common/math.hpp index 9d71509..46a9955 100644 --- a/inc/common/math.hpp +++ b/inc/common/math.hpp @@ -6,16 +6,16 @@ namespace xna { struct MathHelper { - static constexpr double E = 2.7182818284590452354; - static constexpr double PI = 3.14159265358979323846; - static constexpr double TAU = PI * 2; - static constexpr double EPSILON = std::numeric_limits::epsilon(); + static constexpr double E = 2.7182818284590451; + static constexpr double PI = 3.1415926535897931; + static constexpr double TAU = 6.2831853071795862; + static constexpr double EPSILON = 4.94065645841247E-324; static constexpr float ToRadians(float degrees) { return degrees * (static_cast(PI) / 180.0f); } static constexpr float ToDegrees(float radians) { return radians * 57.2957764F; } static float Distance(float value1, float value2) { return std::abs(value1 - value2); } - static float Min(float value1, float value2) { return (std::min)(value1, value2); } - static float Max(float value1, float value2) { return (std::max)(value1, value2); } + static constexpr float Min(float value1, float value2) { return (std::min)(value1, value2); } + static constexpr float Max(float value1, float value2) { return (std::max)(value1, value2); } static constexpr float Clamp(float value, float min, float max) { value = value > max ? max : value; diff --git a/inc/common/point.hpp b/inc/common/point.hpp index c8a1264..a37d8ec 100644 --- a/inc/common/point.hpp +++ b/inc/common/point.hpp @@ -4,19 +4,7 @@ #include "../types.hpp" namespace xna { - struct Point { - Int X{0}; - Int Y{ 0 }; - - constexpr Point() = default; - - constexpr Point(const Int& X, const Int& Y) - : X(X), Y(Y) {} - - constexpr bool operator==(const Point& other) const { - return X == other.X && Y == other.Y; - } - }; + } #endif \ No newline at end of file diff --git a/inc/common/rectangle.hpp b/inc/common/rectangle.hpp index ed14fdc..c884c55 100644 --- a/inc/common/rectangle.hpp +++ b/inc/common/rectangle.hpp @@ -2,9 +2,22 @@ #define XNA_COMMON_RECTANGLE_HPP #include "../types.hpp" -#include "point.hpp" namespace xna { + struct Point { + Int X{ 0 }; + Int Y{ 0 }; + + constexpr Point() = default; + + constexpr Point(const Int& X, const Int& Y) + : X(X), Y(Y) {} + + constexpr bool operator==(const Point& other) const { + return X == other.X && Y == other.Y; + } + }; + struct Rectangle { Int X{ 0 }; Int Y{ 0 }; diff --git a/inc/common/vectors.hpp b/inc/common/vectors.hpp index 20a3abb..01e6cae 100644 --- a/inc/common/vectors.hpp +++ b/inc/common/vectors.hpp @@ -263,7 +263,7 @@ namespace xna { return x * x + y * y + z * z; } - static float Dot(Vector3 const& vector1, Vector3 const& vector2) { + static constexpr float Dot(Vector3 const& vector1, Vector3 const& vector2) { return vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z; } @@ -487,6 +487,20 @@ namespace xna { friend constexpr Vector3 operator/(float divider, Vector3 const& value) { return Vector3::Divide(value, divider); } + + friend constexpr Vector3 operator+=(Vector3 const& value1, Vector3 const& value2) { + auto vec = value1; + vec.X += value2.X; + vec.Y += value2.Y; + return vec; + } + + friend constexpr Vector3 operator-=(Vector3 const& value1, Vector3 const& value2) { + auto vec = value1; + vec.X -= value2.X; + vec.Y -= value2.Y; + return vec; + } }; struct Vector4 { diff --git a/inc/enums.hpp b/inc/enums.hpp index 62ba815..06323a3 100644 --- a/inc/enums.hpp +++ b/inc/enums.hpp @@ -114,7 +114,13 @@ namespace xna { Blue, Alpha, All - }; + }; + + enum class ContainmentType { + Disjoint, + Contains, + Intersects, + }; enum class ComparisonFunction { Never, @@ -379,6 +385,12 @@ namespace xna { Down, }; + enum class PlaneIntersectionType { + Front, + Back, + Intersecting, + }; + enum class PlayerIndex { One, diff --git a/inc/forward.hpp b/inc/forward.hpp index 3085424..1019762 100644 --- a/inc/forward.hpp +++ b/inc/forward.hpp @@ -24,20 +24,20 @@ namespace xna { class ContentTypeReader; class ContentTypeReaderManager; - //Framework - class BoundingBox; - class BoundingFrustum; - class BoundinSphere; + //Common + struct BoundingBox; + struct BoundingFrustum; + struct BoundingSphere; struct Color; - class Curve; - class CurveContinuity; - class CurveKey; - class CurveKeyCollection; + struct Curve; + struct CurveContinuity; + struct CurveKey; + struct CurveKeyCollection; struct Matrix; - class Plane; + struct Plane; struct Point; struct Quaternion; - class Ray; + struct Ray; struct Rectangle; struct Vector2; struct Vector3; diff --git a/inc/xna.hpp b/inc/xna.hpp index d85cfbc..d4deadc 100644 --- a/inc/xna.hpp +++ b/inc/xna.hpp @@ -3,16 +3,17 @@ #include "helpers.hpp" #include "forward.hpp" #include "enums.hpp" -#include "default.hpp" #include "audio/audioengine.hpp" #include "audio/soundeffect.hpp" #include "common/color.hpp" +#include "common/gjk.hpp" #include "common/math.hpp" #include "common/matrix.hpp" #include "common/packedvalue.hpp" #include "common/point.hpp" #include "common/quaternion.hpp" #include "common/rectangle.hpp" +#include "common/collision.hpp" #include "common/vectors.hpp" #include "content/defaultreaders.hpp" #include "content/manager.hpp"