956 lines
23 KiB
C++
956 lines
23 KiB
C++
#pragma once
|
|
|
|
|
|
// TODO: Transform
|
|
|
|
#include "Core/Math/Boilerplate.h"
|
|
#include "Core/Math/MathFwd.h"
|
|
|
|
#include "Core/Math/Line.hpp"
|
|
#include "Core/Math/Ray.hpp"
|
|
#include "Core/Math/Vector3.hpp"
|
|
|
|
namespace Phanes::Core::Math {
|
|
|
|
// Plane in 3D space, defined as: P: ax + by + cz = d;
|
|
|
|
template<RealType T, bool S>
|
|
struct TPlane
|
|
{
|
|
public:
|
|
using Real = T;
|
|
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
/** X Part of the normal. */
|
|
Real x;
|
|
|
|
/** Y Part of the normal. */
|
|
Real y;
|
|
|
|
/** Z Part of the normal. */
|
|
Real z;
|
|
};
|
|
|
|
TVector3<Real, S> normal;
|
|
|
|
};
|
|
|
|
/// <summary>
|
|
/// Scalar component of plane
|
|
/// </summary>
|
|
Real d;
|
|
};
|
|
|
|
/// <summary>
|
|
/// Vector containing all components of vector (x, y, z and d).
|
|
/// </summary>
|
|
TVector4<Real, S> comp;
|
|
};
|
|
|
|
public:
|
|
|
|
/**
|
|
* Default constructor.
|
|
*/
|
|
|
|
TPlane() = default;
|
|
|
|
/**
|
|
* Construct plane from normal and d
|
|
*
|
|
* @param(normal) Normal of plane
|
|
* @param(d) Scalar component
|
|
*
|
|
* @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<Real, S>& normal, Real d);
|
|
|
|
/**
|
|
* Construct plane from normal and base point.
|
|
*
|
|
* @param(normal) Normal of plane
|
|
* @param(base) Base point
|
|
*/
|
|
|
|
TPlane(const TVector3<Real, S>& normal, const TVector3<Real, S>& base);
|
|
|
|
/**
|
|
* Construct plane from coefficients. The components should be normalized.
|
|
*
|
|
* @param(x) X coefficient
|
|
* @param(y) Y coefficient
|
|
* @param(z) Z coefficient
|
|
* @param(d) D coefficient
|
|
*/
|
|
|
|
TPlane(Real x, Real y, Real z, Real d);
|
|
|
|
/**
|
|
* Construct plane from 3 points
|
|
*
|
|
* @param(p1) Point one
|
|
* @param(p2) Point two
|
|
* @param(p3) Point three
|
|
*/
|
|
|
|
TPlane(const TVector3<Real, S>& p1, const TVector3<Real, S>& p2, const TVector3<Real, S>& 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<RealType T, bool S>
|
|
TPlane<T, S> operator+= (TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
|
|
|
|
/**
|
|
* 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<RealType T, bool S>
|
|
TPlane<T, S> operator-= (TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
|
|
|
|
/**
|
|
* 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<RealType T, bool S>
|
|
TPlane<T, S> operator*= (TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
|
|
|
|
/// <summary>
|
|
/// Divides pl1 by pl2
|
|
/// </summary>
|
|
/// <param name="pl1"></param>
|
|
/// <param name="pl2"></param>
|
|
/// <returns></returns>
|
|
template<RealType T, bool S>
|
|
TPlane<T, S> operator/= (TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
|
|
|
|
/// <summary>
|
|
/// Add scalar to plane
|
|
/// </summary>
|
|
/// <param name="pl1"></param>
|
|
/// <param name="s"></param>
|
|
/// <returns></returns>
|
|
template<RealType T, bool S>
|
|
TPlane<T, S> operator+= (TPlane<T, S>& pl1, T s);
|
|
|
|
/// <summary>
|
|
/// Substract scalar from plane
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <typeparam name="S"></typeparam>
|
|
/// <param name="pl1"></param>
|
|
/// <param name="s"></param>
|
|
/// <returns></returns>
|
|
template<RealType T, bool S>
|
|
TPlane<T, S> operator-= (TPlane<T, S>& pl1, T s);
|
|
|
|
/**
|
|
* Multiplies pl1 with a scalar
|
|
*
|
|
* @param(pl1) Plane to multiply
|
|
* @param(s) Scalar to multiply with
|
|
*/
|
|
|
|
template<RealType T, bool S>
|
|
TPlane<T, S> operator*= (TPlane<T, S>& pl1, T s);
|
|
|
|
/**
|
|
* Divides pl1 with a scalar
|
|
*
|
|
* @param(pl1) Plane to divide
|
|
* @param(s) Scalar to divide with
|
|
*/
|
|
|
|
template<RealType T, bool S>
|
|
TPlane<T, S> operator/= (TPlane<T, S>& pl1, T s);
|
|
|
|
|
|
/**
|
|
* Add two planes.
|
|
*
|
|
* @param(pl1) Plane
|
|
* @param(pl2) Plane
|
|
*
|
|
* @return Sum of planes
|
|
*/
|
|
|
|
template<RealType T, bool S>
|
|
TPlane<T, S> operator+ (const TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
|
|
|
|
/**
|
|
* Substracts two planes.
|
|
*
|
|
* @param(pl1) Plane
|
|
* @param(pl2) Plane
|
|
*
|
|
* @return Difference of the planes
|
|
*/
|
|
|
|
template<RealType T, bool S>
|
|
TPlane<T, S> operator- (const TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
|
|
|
|
/**
|
|
* Multiplies two planes.
|
|
*
|
|
* @param(pl1) Plane
|
|
* @param(pl2) Plane
|
|
*
|
|
* @return Product of planes
|
|
*/
|
|
|
|
template<RealType T, bool S>
|
|
TPlane<T, S> operator* (const TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
|
|
|
|
/// <summary>
|
|
/// Divides plane by plane
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <typeparam name="S"></typeparam>
|
|
/// <param name="pl1"></param>
|
|
/// <param name="pl2"></param>
|
|
/// <returns></returns>
|
|
template<RealType T, bool S>
|
|
TPlane<T, S> operator/ (const TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
|
|
|
|
/// <summary>
|
|
/// Add scalar to plane
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <typeparam name="S"></typeparam>
|
|
/// <param name="pl1"></param>
|
|
/// <param name="s"></param>
|
|
/// <returns></returns>
|
|
template<RealType T, bool S>
|
|
TPlane<T, S> operator+ (const TPlane<T, S>& pl1, T s);
|
|
|
|
/// <summary>
|
|
/// Substracts scalar from plane
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <typeparam name="S"></typeparam>
|
|
/// <param name="pl1"></param>
|
|
/// <param name="s"></param>
|
|
/// <returns></returns>
|
|
template<RealType T, bool S>
|
|
TPlane<T, S> operator- (const TPlane<T, S>& pl1, T s);
|
|
|
|
/**
|
|
* Multiplies pl1 with a scalar
|
|
*
|
|
* @param(pl1) Plane to multiply
|
|
* @param(s) Scalar to multiply with
|
|
*
|
|
* @return Product of plane and scalar
|
|
*/
|
|
|
|
template<RealType T, bool S>
|
|
TPlane<T, S> operator* (const TPlane<T, S>& pl1, T s);
|
|
|
|
/**
|
|
* Divides pl1 with a scalar
|
|
*
|
|
* @param(pl1) Plane to divide
|
|
* @param(s) Scalar to divide with
|
|
*
|
|
* @return Quotient of plane and scalar
|
|
*/
|
|
|
|
template<RealType T, bool S>
|
|
TPlane<T, S> operator/ (const TPlane<T, S>& pl1, T 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<RealType T>
|
|
FORCEINLINE bool operator== (const TPlane<T, false>& pl1, const TPlane<T, false>& pl2)
|
|
{
|
|
return pl1.comp == pl2.comp;
|
|
}
|
|
|
|
/**
|
|
* 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<RealType T>
|
|
FORCEINLINE bool operator!= (const TPlane<T, false>& pl1, const TPlane<T, false>& pl2)
|
|
{
|
|
return pl1.comp != pl2.comp;
|
|
}
|
|
|
|
|
|
// ======================= //
|
|
// 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<RealType T>
|
|
inline bool IsPerpendicular(const TPlane<T, false>& pl1, const TPlane<T, false>& 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<RealType T>
|
|
inline bool IsParallel(const TPlane<T, false>& pl1, const TPlane<T, false>& 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<RealType T>
|
|
inline bool IsCoincident(const TPlane<T, false>& pl1, const TPlane<T, false>& 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<RealType T>
|
|
inline bool IsNormalized(const TPlane<T, false>& 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<RealType T>
|
|
inline bool IsSame(const TPlane<T, false>& pl1, const TPlane<T, false>& 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<RealType T>
|
|
TPlane<T, false> PlaneNormalizeV(TPlane<T, false>& 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<RealType T>
|
|
TPlane<T, false> PlaneNormalize(TPlane<T, false>& pl1)
|
|
{
|
|
T normVec = SqrMagnitude(pl1);
|
|
|
|
T scale = (normVec > P_FLT_INAC) ? (T)1.0 / sqrt(normVec) : 1.0f;
|
|
|
|
return TPlane<T, false>(pl1.normal * scale, pl1.d * scale);
|
|
}
|
|
|
|
/**
|
|
* Normalizes plane.
|
|
*
|
|
* @param(pl1) Plane
|
|
*
|
|
* @note Does not check for zero vector pl1.normal.
|
|
*/
|
|
|
|
template<RealType T>
|
|
TPlane<T, false> PlaneUnsafeNormalizeV(TPlane<T, false>& 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<RealType T>
|
|
TPlane<T, false> PlaneUnsafeNormalize(TPlane<T, false>& pl1)
|
|
{
|
|
T scale = (T)1.0 / Magnitude(pl1);
|
|
|
|
return TPlane<T, false>(pl1.normal * scale, pl1.d * scale);
|
|
}
|
|
|
|
/**
|
|
* Get dot product between two planes
|
|
*
|
|
* @param(pl1) Plane one
|
|
* @param(pl2) Plane two
|
|
*/
|
|
|
|
template<RealType T>
|
|
FORCEINLINE T PlaneDotP(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2)
|
|
{
|
|
return DotP(pl1.normal, pl2.normal);
|
|
}
|
|
|
|
/**
|
|
* Get angle between two planes
|
|
*
|
|
* @param(pl1) Plane one
|
|
* @param(pl2) Plane two
|
|
*/
|
|
|
|
template<RealType T>
|
|
FORCEINLINE T PlaneAngle(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2)
|
|
{
|
|
return Angle(pl1.normal, pl2.normal);
|
|
}
|
|
|
|
/**
|
|
* Get cosine of angle between two planes
|
|
*
|
|
* @param(pl1) Plane one
|
|
* @param(pl2) Plane two
|
|
*/
|
|
|
|
template<RealType T>
|
|
FORCEINLINE T PlaneCosAngle(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2)
|
|
{
|
|
return CosineAngle(pl1.normal, pl2.normal);
|
|
}
|
|
|
|
/**
|
|
* Flip plane.
|
|
*
|
|
* @param(pl1) Plane
|
|
*/
|
|
|
|
template<RealType T>
|
|
TPlane<T, false> FlipV(const TPlane<T, false>& pl1)
|
|
{
|
|
pl1.normal = -pl1.normal;
|
|
pl1.d = -pl1.d;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get flipped plane.
|
|
*
|
|
* @param(pl1) Plane
|
|
*
|
|
* @return Flipped plane
|
|
*/
|
|
|
|
template<RealType T>
|
|
TPlane<T, false> Flip(const TPlane<T, false>& pl1)
|
|
{
|
|
return TPlane<T, false>(-pl1.normal, -pl1.d);
|
|
}
|
|
|
|
/**
|
|
* Transform plane with Transform
|
|
*
|
|
* @param(pl) Plane
|
|
* @param(tr) Transform
|
|
*/
|
|
|
|
template<RealType T>
|
|
FORCEINLINE TPlane<T, false> TransformV(TPlane<T, false>& pl, const TTransform<T>& tr)
|
|
{
|
|
// TODO: Do with operator*
|
|
}
|
|
|
|
|
|
/**
|
|
* Transform plane with Transform
|
|
*
|
|
* @param(pl) Plane
|
|
* @param(tr) Transform
|
|
*
|
|
* @return Transformed plane.
|
|
*/
|
|
|
|
template<RealType T>
|
|
FORCEINLINE TPlane<T, false> Transform(const TPlane<T, false>& pl, const TTransform<T>& tr)
|
|
{
|
|
// 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<RealType T>
|
|
T PointDistance(const TPlane<T, false>& pl1, const TVector3<T, false>& 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<RealType T>
|
|
TVector3<T, false> GetOrigin(const TPlane<T, false>& pl1)
|
|
{
|
|
return TVector3<T, false>(pl1.normal * pl1.d);
|
|
}
|
|
|
|
/**
|
|
* Translates plane by vector
|
|
*
|
|
* @param(pl1) Plane
|
|
* @param(v1) Vector
|
|
*/
|
|
|
|
template<RealType T>
|
|
TPlane<T, false> TranslateV(TPlane<T, false>& pl1, const TVector3<T, false>& v1)
|
|
{
|
|
|
|
pl1.d = DotP(pl1.normal, GetOrigin(pl1) + v1);
|
|
|
|
return pl1;
|
|
}
|
|
|
|
/**
|
|
* Translates plane by vector
|
|
*
|
|
* @param(pl1) Plane
|
|
* @param(v1) Vector
|
|
*/
|
|
|
|
template<RealType T>
|
|
TPlane<T, false> Translate(TPlane<T, false>& pl1, const TVector3<T, false>& v1)
|
|
{
|
|
return TPlane<T, false>(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<RealType T>
|
|
bool GetSide(const TPlane<T, false>& pl1, const TVector3<T, false>& p1)
|
|
{
|
|
return (pl1.d <= DotP(pl1.normal, p1));
|
|
}
|
|
|
|
/**
|
|
* Projects vector onto plane
|
|
*
|
|
* @param(v1) Vector to reject
|
|
* @param(plane) Plane
|
|
*
|
|
* @note result is stored in v1.
|
|
* @note Simply rejects v1 from normal
|
|
*/
|
|
|
|
template<RealType T>
|
|
FORCEINLINE TVector3<T, false> ProjectOntoPlaneV(TVector3<T, false>& v1, const TPlane<T, false>& plane)
|
|
{
|
|
return RejectV(v1, plane.normal);
|
|
}
|
|
|
|
|
|
/**
|
|
* Projects vector onto plane
|
|
*
|
|
* @param(v1) Vector to reject
|
|
* @param(normal) Normal of the plane
|
|
*
|
|
* @note result is stored in v1.
|
|
* @note Simply rejects v1 from normal
|
|
*/
|
|
|
|
template<RealType T>
|
|
FORCEINLINE TVector3<T, false> ProjectOntoPlaneV(TVector3<T, false>& v1, const TVector3<T, false>& normal)
|
|
{
|
|
return RejectV(v1, normal);
|
|
}
|
|
|
|
/**
|
|
* Reflect from plane
|
|
*
|
|
* @param(v1) Vector to mirror
|
|
* @param(plane) Plane to mirror on
|
|
*
|
|
* @note result is stored in v1.
|
|
*/
|
|
|
|
template<RealType T>
|
|
FORCEINLINE TVector3<T, false> ReflectFromPlaneV(TVector3<T, false>& v1, const TPlane<T, false>& plane)
|
|
{
|
|
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<RealType T>
|
|
FORCEINLINE TVector3<T, false> ReflectFromPlaneV(TVector3<T, false>& v1, const TVector3<T, false>& normal)
|
|
{
|
|
return ReflectV(v1, normal);
|
|
}
|
|
|
|
|
|
/**
|
|
* Reflect from plane
|
|
*
|
|
* @param(v1) Vector to mirror
|
|
* @param(plane) Plane to mirror on
|
|
*
|
|
* @return Reflected vector
|
|
*/
|
|
|
|
template<RealType T>
|
|
FORCEINLINE TVector3<T, false> ReflectFromPlane(const TVector3<T, false>& v1, const TPlane<T, false>& plane)
|
|
{
|
|
return Reflect(v1, plane.normal);
|
|
}
|
|
|
|
/**
|
|
* Reflect from plane
|
|
*
|
|
* @param(v1) Vector to mirror
|
|
* @param(plane) Normal of plane
|
|
*
|
|
* @return Reflected vector
|
|
*/
|
|
|
|
template<RealType T>
|
|
FORCEINLINE TVector3<T, false> ReflectFromPlane(const TVector3<T, false>& v1, const TVector3<T, false>& normal)
|
|
{
|
|
return Reflect(v1, normal);
|
|
}
|
|
|
|
/**
|
|
* Projects vector onto plane
|
|
*
|
|
* @see [FUNC]PointProjectOntoPlane
|
|
*
|
|
* @param(v1) Vector to reject
|
|
* @param(normal) Normal of the plane
|
|
*
|
|
* @return Projected vector
|
|
* @note Simply rejects the vector from normal
|
|
*/
|
|
|
|
template<RealType T>
|
|
FORCEINLINE TVector3<T, false> ProjectOntoPlane(const TVector3<T, false>& v1, const TVector3<T, false>& normal)
|
|
{
|
|
return Reject(v1, normal);
|
|
}
|
|
|
|
|
|
/**
|
|
* Projects vector onto plane
|
|
*
|
|
* @see [FUNC]PointProjectOntoPlane
|
|
*
|
|
* @param(v1) Vector to reject
|
|
* @param(plane) Plane
|
|
*
|
|
* @return Projected vector
|
|
* @note Simply rejects the vector from normal
|
|
*/
|
|
|
|
template<RealType T>
|
|
FORCEINLINE TVector3<T, false> ProjectOntoPlane(const TVector3<T, false>& v1, const TPlane<T, false>& plane)
|
|
{
|
|
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<RealType T>
|
|
inline bool Equals(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2, T threshold = P_FLT_INAC)
|
|
{
|
|
return Equals(pl1.normal, pl2.normal, threshold) && abs(pl1.d - pl2.d) < threshold;
|
|
}
|
|
|
|
|
|
/** Tests whether a point is on a plane
|
|
*
|
|
* @param(pl1) Plane
|
|
* @param(p1) Point
|
|
*
|
|
* @return True, if p1 on pl1, false if not.
|
|
*/
|
|
template<RealType T>
|
|
FORCEINLINE bool IsPointOnPlane(const TPlane<T, false>& pl1, const TVector3<T, false>& p1)
|
|
{
|
|
return (Equals(DotP(pl1.normal, p1), p1.d));
|
|
}
|
|
|
|
/**
|
|
* 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<RealType T>
|
|
bool PlanesIntersect2(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2, Ref<TLine<T>> interLine, T threshold = P_FLT_INAC)
|
|
{
|
|
TVector3<T, false> dirLine = CrossP(pl1.normal, pl2.normal);
|
|
T det = SqrMagnitude(dirLine);
|
|
|
|
if (abs(det) > P_FLT_INAC)
|
|
{
|
|
interLine = MakeRef<TLine<T>>(dirLine, (CrossP(dirLine, pl2.normal) * pl1.d + CrossP(dirLine, pl1.normal) * pl2.d) / det);
|
|
NormalizeV(interLine);
|
|
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<RealType T>
|
|
bool PlanesIntersect3(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2, const TPlane<T, false>& pl3, Ref<TVector3<T, false>> interPoint, T threshold = P_FLT_INAC)
|
|
{
|
|
T det = DotP(CrossP(pl1.normal, pl2.normal), pl3.normal);
|
|
|
|
if (abs(det) > P_FLT_INAC)
|
|
{
|
|
interPoint = MakeRef<TVector3<T, false>>((CrossP(pl3.normal, pl2.normal) * pl1.d + CrossP(pl1.normal, pl3.normal) * pl2.d) / det);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Mirrors a point through plane
|
|
*
|
|
* @param(p1) Point to mirror
|
|
* @param(pl1) Plane
|
|
*
|
|
* @return Mirrored point.
|
|
*/
|
|
|
|
template<RealType T>
|
|
TVector3<T, false> PlaneMirrorPoint(const TVector3<T, false>& p1, const TPlane<T, false>& pl1)
|
|
{
|
|
return p1 - pl1.normal * ((T)2.0 * PointDistance(pl1, p1));
|
|
}
|
|
|
|
/**
|
|
* Projects point onto plane
|
|
*
|
|
* @param(p1) Point to project
|
|
* @param(pl1) Plane
|
|
*
|
|
* @return Projected point.
|
|
*/
|
|
|
|
template<RealType T>
|
|
TVector3<T, false> PointProjectOntoPlane(const TVector3<T, false>& p1, const TPlane<T, false>& pl1)
|
|
{
|
|
return p1 - PointDistance(pl1, p1) * pl1.normal;
|
|
}
|
|
|
|
/**
|
|
* Calculates the intersection point, of a line with a plane, if there is one
|
|
*
|
|
* @param(pl1) Plane
|
|
* @param(l1) Line
|
|
* @param(p1) Point
|
|
*
|
|
* @return True, if they intersect, false if not.
|
|
*/
|
|
|
|
template<RealType T>
|
|
bool LineIntersect(const TPlane<T, false>& pl1, const TLine<T>& l1, Ref<TVector3<T, false>> p1)
|
|
{
|
|
T dotProduct = DotP(l1.normal, pl1.normal);
|
|
|
|
if (abs(dotProduct) > P_FLT_INAC)
|
|
{
|
|
p1 = MakeRef<TVector3<T, false>>(l1.base - l1.normal * (DotP(l1.normal * p1.base) / dotProduct));
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Calculates, the intersection point, of a plane and a ray.
|
|
*
|
|
* @param(pl1) Plane
|
|
* @param(r1) Ray
|
|
* @param(p1) Intersection point
|
|
*
|
|
* @return True, if they intersect, false if not.
|
|
*/
|
|
|
|
template<RealType T>
|
|
bool RayIntersect(const TPlane<T, false>& pl1, const TRay<T, false>& r1, Ref<TVector3<T, false>> p1)
|
|
{
|
|
T pr = DotP(pl1.normal, Normalize(r1.direction));
|
|
T parameter = DotP((GetOrigin(pl1) - r1.origin), pl1.normal) / pr;
|
|
|
|
if (p1 > P_FLT_INAC && parameter >= 0)
|
|
{
|
|
p1 = MakeRef<TVector3<T, false>>(PointAt(r1, parameter));
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
} // Phanes::Core::Math
|
|
|
|
// Include operator impl.
|
|
#include "Core/Math/Plane.inl" |