From aa72adac7106dceb257d9a78862a5649bf7e2c16 Mon Sep 17 00:00:00 2001 From: scorpioblood <77296181+scorpioblood@users.noreply.github.com> Date: Tue, 21 May 2024 22:43:07 +0200 Subject: [PATCH] Adding functionality to TPlane. --- Engine/src/Runtime/Core/public/Math/MathFwd.h | 10 + Engine/src/Runtime/Core/public/Math/Plane.hpp | 574 +++++++++++++++++- 2 files changed, 574 insertions(+), 10 deletions(-) diff --git a/Engine/src/Runtime/Core/public/Math/MathFwd.h b/Engine/src/Runtime/Core/public/Math/MathFwd.h index b7302fa..bf9a53f 100644 --- a/Engine/src/Runtime/Core/public/Math/MathFwd.h +++ b/Engine/src/Runtime/Core/public/Math/MathFwd.h @@ -30,6 +30,7 @@ namespace Phanes::Core::Math { template struct TVector3; template struct TVector4; template struct TRay; + template struct TLine; template struct TPlane; template struct TMatrix2; template struct TMatrix3; @@ -96,6 +97,15 @@ namespace Phanes::Core::Math { typedef std::vector Matrix3List; typedef std::vector Matrix3Listd; + + // TPlane + typedef TPlane Plane; + typedef TPlane Planed; + + typedef std::vector PlaneList; + typedef std::vector PlaneListd; + + } // Phanes::Core::Math::coretypes namespace Phanes::Core::Math::Internal diff --git a/Engine/src/Runtime/Core/public/Math/Plane.hpp b/Engine/src/Runtime/Core/public/Math/Plane.hpp index 3a42faa..f79b75e 100644 --- a/Engine/src/Runtime/Core/public/Math/Plane.hpp +++ b/Engine/src/Runtime/Core/public/Math/Plane.hpp @@ -1,8 +1,12 @@ #pragma once + +// TODO: Transform + #include "Core/public/Math/Boilerplate.h" #include "Core/public/Math/MathFwd.h" +#include "Core/public/Math/Line.hpp" #include "Core/public/Math/Vector3.hpp" namespace Phanes::Core::Math { @@ -13,9 +17,32 @@ namespace Phanes::Core::Math { struct TPlane { public: - TVector3 normal; - T d; + using Real = T; + union + { + struct + { + /** X Part of the normal. */ + Real x; + + /** Y Part of the normal. */ + Real y; + + /** Z Part of the normal. */ + Real z; + }; + + TVector3 normal; + }; + + /** Scalar component of plane. */ + union + { + Real d; + Real w; + }; + public: /** @@ -28,13 +55,13 @@ namespace Phanes::Core::Math { * Copy constructor */ - TPlane(const TPlane& plane) : normal(plane.normal), d(plane.d) {}; + TPlane(const TPlane& plane) : normal(plane.normal), d(plane.d) {}; /** * Move constructor */ - TPlane(TPlane&& plane) : + TPlane(TPlane&& plane) : normal(std::move(plane.normal)), d(std::move(plane.d)) {} @@ -49,7 +76,7 @@ namespace Phanes::Core::Math { * @note Normal is NOT normalized, make sure to normalize [PARAM]normal, or use [FUNC]CreateFromVector. Otherwise unexpected results may occur using the plane. */ - TPlane(const TVector3& normal, T d) : + TPlane(const TVector3& normal, Real d) : normal(normal), d(d) {} @@ -61,7 +88,7 @@ namespace Phanes::Core::Math { * @param(base) Base point */ - TPlane(const TVector3& normal, const TVector3& base) : + TPlane(const TVector3& normal, const TVector3& base) : normal(normal) { this->d = DotP(this->normal, base); @@ -76,10 +103,10 @@ namespace Phanes::Core::Math { * @param(d) D coefficient */ - TPlane(T x, T y, T z, T d) : + TPlane(Real x, Real y, Real z, Real d) : d(d) { - this->normal = TVector3(x, y, z); + this->normal = TVector3(x, y, z); } /** @@ -90,13 +117,380 @@ namespace Phanes::Core::Math { * @param(p3) Point three */ - TPlane(const TVector3& p1, const TVector3& p2, const TVector3& p3) + TPlane(const TVector3& p1, const TVector3& p2, const TVector3& p3) { this->normal = Normalize(CrossP(p1, p2)); this->d = DotP(this->normal, p3); } }; + + // ======================== // + // Operators for TPlane // + // ======================== // + + + /** + * Adds pl2 to pl1. + * + * @param(pl1) Plane to add to + * @param(pl2) Plane to add + * + * @note This leads to the plane not being normalized anymore. Use PlaneNormalizeV to normalize again. + * @see [FUNC] PlaneNormalizeV + */ + + template + TPlane operator+= (TPlane& pl1, const TPlane& pl2) + { + pl1.normal += pl2.normal; pl1.d += pl2.d; + + return pl1; + } + + /** + * Substracts pl2 from pl1. + * + * @param(pl1) Plane to substract from + * @param(pl2) Plane to substract + * + * @note This leads to the plane not being normalized anymore. Use PlaneNormalizeV to normalize again. + * @see [FUNC] PlaneNormalizeV + */ + + template + TPlane operator-= (TPlane& pl1, const TPlane& pl2) + { + pl1.normal -= pl2.normal; pl1.d -= pl2.d; + + return pl1; + } + + /** + * Multiplies pl1 with pl2. + * + * @param(pl1) Plane to multiply + * @param(pl2) Plane to multiply with + * + * @note This leads to the plane not being normalized anymore. Use PlaneNormalizeV to normalize again. + * @see [FUNC] PlaneNormalizeV + */ + + template + TPlane operator*= (TPlane& pl1, const TPlane& pl2) + { + pl1.x *= pl2.x; pl1.y *= pl2.y; pl1.z *= pl2.z; pl1.d *= pl2.d; + + return pl1; + } + + /** + * Multiplies pl1 with a scalar + * + * @param(pl1) Plane to multiply + * @param(s) Scalar to multiply with + */ + + template + TPlane operator*= (TPlane& pl1, T s) + { + pl1.normal *= s; pl1 *= s; + + return pl1; + } + + /** + * Divides pl1 with a scalar + * + * @param(pl1) Plane to divide + * @param(s) Scalar to divide with + */ + + template + TPlane operator/= (TPlane& pl1, T s) + { + T _1_s = (T)1.0 / s; + + pl1.normal *= _1_s; pl1 *= _1_s; + + return pl1; + } + + + /** + * Add two planes. + * + * @param(pl1) Plane + * @param(pl2) Plane + * + * @return Sum of planes + */ + + template + TPlane operator+ (const TPlane& pl1, const TPlane& pl2) + { + return TPlane(pl1.normal + pl2.normal, pl1.d + pl2.d); + } + + /** + * Substracts two planes. + * + * @param(pl1) Plane + * @param(pl2) Plane + * + * @return Difference of the planes + */ + + template + TPlane operator- (const TPlane& pl1, const TPlane& pl2) + { + return TPlane(pl1.normal - pl2.normal, pl1.d - pl2.d); + } + + /** + * Multiplies two planes. + * + * @param(pl1) Plane + * @param(pl2) Plane + * + * @return Product of planes + */ + + template + TPlane operator* (const TPlane& pl1, const TPlane& pl2) + { + return TPlane(pl1.x * pl2.x, pl1.y * pl2.y, pl1.z * pl2.z, pl1.d * pl2.d); + } + + /** + * Multiplies pl1 with a scalar + * + * @param(pl1) Plane to multiply + * @param(s) Scalar to multiply with + * + * @return Product of plane and scalar + */ + + template + TPlane operator*= (const TPlane& pl1, T s) + { + return TPlane(pl1.normal * s, pl1.d * s); + } + + /** + * Divides pl1 with a scalar + * + * @param(pl1) Plane to divide + * @param(s) Scalar to divide with + * + * @return Quotient of plane and scalar + */ + + template + TPlane operator/= (const TPlane& pl1, T s) + { + T _1_s = (T)1.0 / s; + + return TPlane(pl1.normal * _1_s, pl1.d * _1_s); + } + + /** + * Tests two planes for equality + * + * @see [FUNC] Equals + * + * @param(pl1) Plane one + * @param(pl2) Plane two + * + * @return True, if planes are equal, false, if not. + */ + + template + bool operator== (const TPlane& pl1, const TPlane& pl2) + { + return pl1.normal == pl2.normal && abs(pl1.d - pl2.d) < P_FLT_INAC; + } + + /** + * Tests two planes for inequality + * + * @see [FUNC] Equals + * + * @param(pl1) Plane one + * @param(pl2) Plane two + * + * @return True, if planes are inequal, false, if not. + */ + + template + bool operator!= (const TPlane& pl1, const TPlane& pl2) + { + return pl1.normal != pl2.normal || abs(pl1.d - pl2.d) >= P_FLT_INAC; + } + + + // ======================= // + // Functions of TPlane // + // ======================= // + + + + + /** + * Tests whether two planes are perpendicular. + * + * @param(pl1) Plane one + * @param(pl2) Plane two + * @param(threshold) Allowed T inaccuracy + * + * @return True if perpendicular, false if not. + */ + + template + inline bool IsPerpendicular(const TPlane& pl1, const TPlane& pl2, T threshold = P_FLT_INAC) + { + return (abs(DotP(pl1.normal, pl2.normal)) < threshold); + } + + /** + * Tests whether two planes are parallel. + * + * @param(pl1) Plane one + * @param(pl2) Plane two + * @param(threshold) Allowed T inaccuracy from one (e.g. 0.98f) + * + * @return True if parallel, false if not. + */ + + template + inline bool IsParallel(const TPlane& pl1, const TPlane& pl2, T threshold = 1.0f - P_FLT_INAC) + { + return (abs(DotP(pl1.normal, pl2.normal)) > threshold); + } + + /** + * Tests whether two planes are coincident (Parallel and point in same direction). + * + * @param(pl1) Plane one + * @param(pl2) Plane two + * @param(threshold) Allowed T inaccuracy from one (e.g. 0.98f) + * + * @return True if coincident, false if not. + */ + + template + inline bool IsCoincident(const TPlane& pl1, const TPlane& pl2, T threshold = 1.0f - P_FLT_INAC) + { + return (DotP(pl1.normal, pl2.normal) > threshold); + } + + /** + * Tests whether pl1 plane is a unit vector. + * + * @param(pl1) Plane + * @param(threshold) Allowed T inaccuracy + * + * @return True if unit vector, false if not. + */ + + template + inline bool IsNormalized(const TPlane& pl1, T threshold = P_FLT_INAC) + { + return (SqrMagnitude(pl1.normal) < threshold); + } + + /** + * Tests whether two planes are the same + * + * @see [FUNC]Equals + * + * @param(pl1) Plane one + * @param(pl2) Plane two + * @param(threshold) Allowed T inaccuracy + * + * @return True if same, false if not. + * @note Planes must be normalized. + */ + + template + inline bool IsSame(const TPlane& pl1, const TPlane& pl2, T threshold = P_FLT_INAC) + { + + return DotP(pl1.normal, pl2.normal) > threshold && abs(pl1.d - pl2.d) < P_FLT_INAC; + } + + /** + * Normalizes plane. + * + * @param(pl1) Plane + */ + + template + TPlane PlaneNormalizeV(TPlane& pl1) + { + T normVec = SqrMagnitude(pl1); + + T scale = (normVec > P_FLT_INAC) ? (T)1.0 / sqrt(normVec) : 1.0f; + + pl1.normal *= scale; pl1.d *= scale; + + return pl1; + } + + /** + * Normalizes plane. + * + * @param(pl1) Plane + * + * @return Normalized plane + */ + + template + TPlane PlaneNormalize(TPlane& pl1) + { + T normVec = SqrMagnitude(pl1); + + T scale = (normVec > P_FLT_INAC) ? (T)1.0 / sqrt(normVec) : 1.0f; + + return TPlane(pl1.normal * scale, pl1.d * scale); + } + + /** + * Normalizes plane. + * + * @param(pl1) Plane + * + * @note Does not check for zero vector pl1.normal. + */ + + template + TPlane PlaneUnsafeNormalizeV(TPlane& pl1) + { + T scale = (T)1.0 / Magnitude(pl1); + + pl1.normal *= scale; pl1.d *= scale; + + return pl1; + } + + /** + * Normalizes plane. + * + * @param(pl1) Plane + * + * @return Normalized plane + * + * @note Does not check for zero vector pl1.normal. + */ + + template + TPlane PlaneUnsafeNormalize(TPlane& pl1) + { + T scale = (T)1.0 / Magnitude(pl1); + + return TPlane(pl1.normal * scale, pl1.d * scale); + } + /** * Get dot product between two planes * @@ -193,6 +587,80 @@ namespace Phanes::Core::Math { // TODO: Do with operator* } + /** + * Calculates distance bewteen point and plane. + * + * @param(pl1) Plane + * @param(p1) Point + * + * @return Distance from point to plane + * @note Distance is 0 if point is on plane, >0 if it's in front and <0 if it's on the backside. + */ + + template + T PointDistance(const TPlane& pl1, const TVector3& p1) + { + return (pl1.x * p1.x + pl1.y * p1.y + pl1.z * p1.z) - pl1.d; + } + + /** + * Gets the origin point (base) of the plane + * + * @param(pl1) Plane + * + * @return Base of plane + */ + + template + TVector3 GetOrigin(const TPlane& pl1) + { + return TVector3(pl1.normal * d); + } + + /** + * Translates plane by vector + * + * @param(pl1) Plane + * @param(v1) Vector + */ + + template + TPlane TranslateV(TPlane& pl1, const TVector3& v1) + { + + pl1.d = DotP(this->normal, GetOrigin(pl1) + v1); + + return pl1; + } + + /** + * Translates plane by vector + * + * @param(pl1) Plane + * @param(v1) Vector + */ + + template + TPlane Translate(TPlane& pl1, const TVector3& v1) + { + return TPlane(pl1.normal, GetOrigin(pl1) + v1); + } + + /** + * Returns the side a point is on. + * + * @param(pl1) Plane + * @param(p1) Point + * + * @return True, if it's in the front and false, if it's on the back. + */ + + template + bool GetSide(const TPlane& pl1, const TVector3& p1) + { + return (pl1.d <= DotP(pl1.normal, p1)); + } + /** * Projects vector onto plane * @@ -227,7 +695,7 @@ namespace Phanes::Core::Math { } /** - * Reflect by plane + * Reflect from plane * * @param(v1) Vector to mirror * @param(plane) Plane to mirror on @@ -241,6 +709,21 @@ namespace Phanes::Core::Math { return ReflectV(v1, plane.normal); } + /** + * Reflect from plane + * + * @param(v1) Vector to mirror + * @param(normal) Normal of plane + * + * @note result is stored in v1. + */ + + template + FORCEINLINE TVector3 ReflectFromPlaneV(TVector3& v1, const TVector3& normal) + { + return ReflectV(v1, normal); + } + /** * Reflect from plane @@ -305,6 +788,77 @@ namespace Phanes::Core::Math { return Reject(v1, plane.normal); } + /** + * Tests planes for equality + * + * @param(pl1) Plane one + * @param(pl2) Plane two + * @param(threshold) Allowed inaccuracy + * + * @return True, if equal, false if not. + */ + + template + inline bool Equals(const TPlane& pl1, const TPlane& pl2, T threshold = P_FLT_INAC) + { + return Equals(pl1.normal, pl2.normal, threshold) && abs(pl1.d - pl2.d) < threshold; + } + + + + /** + * Tests whether two planes intersect. Sets line to intersection-line if true. + * + * @param(pl1) Plane one + * @param(pl2) Plane two + * @param(interLine) Line of intersection + * @param(threshold) Threshold for parallel planes. + * + * @return True, if planes intersect, false, if not. + */ + + template + inline bool PlanesIntersect(const TPlane& pl1, const TPlane& pl2, Ref> interLine, T threshold = P_FLT_INAC) + { + TVector3 dirLine = CrossP(pl1.normal, pl2.normal); + T det = SqrMagnitude(dirLine); + + if (abs(det) > P_FLT_INAC) + { + interLine = MakeRef(dirLine, (CrossP(dirLine, pl2.normal) * pl1.d + CrossP(dirLine, pl1.normal) * pl2.d) / det); + return true; + } + + return false; + } + + /** + * Tests whether three planes intersect. Sets line to intersection-line if true. + * + * @param(pl1) Plane one + * @param(pl2) Plane two + * @param(pl3) Plane three + * @param(interPoint) Point of intersection + * @param(threshold) Threshold for parallel planes. + * + * @return True, if all planes intersect, false, if not. + */ + + template + inline bool PlanesIntersect(const TPlane& pl1, const TPlane& pl2, const TPlane& pl3, Ref> interPoint, T threshold = P_FLT_INAC) + { + T det = DotP(CrossP(pl1.normal, pl2.normal), pl3.normal); + + if (abs(det) > P_FLT_INAC) + { + interPoint = MakeRef>((CrossP(pl3.normal, pl2.normal) * pl1.d + CrossP(pl1.normal, pl3.normal) * pl2.d) / det); + return true; + } + + return false; + } + + } // Phanes::Core::Math \ No newline at end of file