// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Types/BaseTypes.h"
///
/// Describes how one bounding volume contains another.
///
enum class ContainmentType
{
///
/// The two bounding volumes don't intersect at all.
///
Disjoint,
///
/// One bounding volume completely contains another.
///
Contains,
///
/// The two bounding volumes overlap.
///
Intersects
};
///
/// Describes the result of an intersection with a plane in three dimensions.
///
enum class PlaneIntersectionType
{
///
/// The object is behind the plane.
///
Back,
///
/// The object is in front of the plane.
///
Front,
///
/// The object is intersecting the plane.
///
Intersecting
};
///
/// Contains static methods to help in determining intersections, containment, etc.
///
class FLAXENGINE_API CollisionsHelper
{
public:
///
/// Determines the closest point between a point and a line.
///
/// The point to test.
/// The line first point.
/// The line second point.
/// When the method completes, contains the closest point between the two objects.
static void ClosestPointPointLine(const Float2& point, const Float2& p0, const Float2& p1, Float2& result);
///
/// Determines the closest point between a point and a line.
///
/// The point to test.
/// The line first point.
/// The line second point.
/// The closest point between the two objects.
static Float2 ClosestPointPointLine(const Float2& point, const Float2& p0, const Float2& p1);
///
/// Determines the closest point between a point and a line.
///
/// The point to test.
/// The line first point.
/// The line second point.
/// When the method completes, contains the closest point between the two objects.
static void ClosestPointPointLine(const Vector3& point, const Vector3& p0, const Vector3& p1, Vector3& result);
///
/// Determines the closest point between a point and a line.
///
/// The point to test.
/// The line first point.
/// The line second point.
/// The closest point between the two objects.
static Vector3 ClosestPointPointLine(const Vector3& point, const Vector3& p0, const Vector3& p1);
///
/// Determines the closest point between a point and a triangle.
///
/// The point to test.
/// The first vertex to test.
/// The second vertex to test.
/// The third vertex to test.
/// When the method completes, contains the closest point between the two objects.
static void ClosestPointPointTriangle(const Vector3& point, const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3, Vector3& result);
///
/// Determines the closest point between a point and a triangle.
///
/// The point to test.
/// The first vertex to test.
/// The second vertex to test.
/// The third vertex to test.
/// The closest point between the two objects.
static Vector3 ClosestPointPointTriangle(const Vector3& point, const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3);
///
/// Determines the closest point between a and a point.
///
/// The plane to test.
/// The point to test.
/// When the method completes, contains the closest point between the two objects.
static void ClosestPointPlanePoint(const Plane& plane, const Vector3& point, Vector3& result);
///
/// Determines the closest point between a and a point.
///
/// The plane to test.
/// The point to test.
/// The closest point between the two objects.
static Vector3 ClosestPointPlanePoint(const Plane& plane, const Vector3& point);
///
/// Determines the closest point between a and a point.
///
/// The box to test.
/// The point to test.
/// When the method completes, contains the closest point between the two objects.
static void ClosestPointBoxPoint(const BoundingBox& box, const Vector3& point, Vector3& result);
///
/// Determines the closest point between a and a point.
///
/// The box to test.
/// The point to test.
/// The closest point between the two objects.
static Vector3 ClosestPointBoxPoint(const BoundingBox& box, const Vector3& point);
///
/// Determines the closest point between a and a point.
///
/// The rectangle to test.
/// The point to test.
/// When the method completes, contains the closest point between the two objects.
static void ClosestPointRectanglePoint(const Rectangle& rect, const Float2& point, Float2& result);
///
/// Determines the closest point between a and a point.
///
/// The rectangle to test.
/// The point to test.
/// The closest point between the two objects.
static Float2 ClosestPointRectanglePoint(const Rectangle& rect, const Float2& point);
///
/// Determines the closest point between a and a point.
///
/// The sphere to test.
/// The point to test.
/// When the method completes, contains the closest point between the two objects; or, if the point is directly in the center of the sphere, contains .
static void ClosestPointSpherePoint(const BoundingSphere& sphere, const Vector3& point, Vector3& result);
///
/// Determines the closest point between a and a point.
///
/// The sphere to test.
/// The point to test.
/// The closest point between the two objects; or, if the point is directly in the center of the sphere, contains .
static Vector3 ClosestPointSpherePoint(const BoundingSphere& sphere, const Vector3& point);
///
/// Determines the closest point between a and a .
///
/// The first sphere to test.
/// The second sphere to test.
/// When the method completes, contains the closest point between the two objects; or, if the point is directly in the center of the sphere, contains .
///
/// If the two spheres are overlapping, but not directly on top of each other, the closest point
/// is the 'closest' point of intersection. This can also be considered is the deepest point of
/// intersection.
///
static void ClosestPointSphereSphere(const BoundingSphere& sphere1, const BoundingSphere& sphere2, Vector3& result);
///
/// Determines the closest point between a and a .
///
/// The first sphere to test.
/// The second sphere to test.
/// The closest point between the two objects; or, if the point is directly in the center of the sphere, contains .
///
/// If the two spheres are overlapping, but not directly on top of each other, the closest point
/// is the 'closest' point of intersection. This can also be considered is the deepest point of
/// intersection.
///
static Vector3 ClosestPointSphereSphere(const BoundingSphere& sphere1, const BoundingSphere& sphere2);
///
/// Determines the distance between a and a point.
///
/// The plane to test.
/// The point to test.
/// The distance between the two objects.
static Real DistancePlanePoint(const Plane& plane, const Vector3& point);
///
/// Determines the distance between a and a point.
///
/// The box to test.
/// The point to test.
/// The distance between the two objects.
static Real DistanceBoxPoint(const BoundingBox& box, const Vector3& point);
///
/// Determines the distance between a and a .
///
/// The first box to test.
/// The second box to test.
/// The distance between the two objects.
static Real DistanceBoxBox(const BoundingBox& box1, const BoundingBox& box2);
///
/// Determines the distance between a and a point.
///
/// The sphere to test.
/// The point to test.
/// The distance between the two objects.
static Real DistanceSpherePoint(const BoundingSphere& sphere, const Vector3& point);
///
/// Determines the distance between a and a .
///
/// The first sphere to test.
/// The second sphere to test.
/// The distance between the two objects.
static Real DistanceSphereSphere(const BoundingSphere& sphere1, const BoundingSphere& sphere2);
///
/// Determines whether there is an intersection between a and a point.
///
/// The ray to test.
/// The point to test.
/// Whether the two objects intersect.
static bool RayIntersectsPoint(const Ray& ray, const Vector3& point);
///
/// Determines whether there is an intersection between a and a .
///
/// The first ray to test.
/// The second ray to test.
/// When the method completes, contains the point of intersection, or if there was no intersection.
/// Whether the two objects intersect.
///
/// This method performs a ray vs ray intersection test based on the following formula
/// from Goldman.
/// s = det([o_2 - o_1, d_2, d_1 x d_2]) / ||d_1 x d_2||^2
/// t = det([o_2 - o_1, d_1, d_1 x d_2]) / ||d_1 x d_2||^2
/// Where o_1 is the position of the first ray, o_2 is the position of the second ray,
/// d_1 is the normalized direction of the first ray, d_2 is the normalized direction
/// of the second ray, det denotes the determinant of a matrix, x denotes the cross
/// product, [ ] denotes a matrix, and || || denotes the length or magnitude of a vector.
///
static bool RayIntersectsRay(const Ray& ray1, const Ray& ray2, Vector3& point);
///
/// Determines whether there is an intersection between a and a .
///
/// The ray to test.
/// The plane to test.
/// When the method completes, contains the distance of the intersection, or 0 if there was no intersection.
/// Whether the two objects intersect.
static bool RayIntersectsPlane(const Ray& ray, const Plane& plane, Real& distance);
///
/// Determines whether there is an intersection between a and a .
///
/// The ray to test.
/// The plane to test
/// When the method completes, contains the point of intersection, or if there was no intersection.
/// Whether the two objects intersected.
static bool RayIntersectsPlane(const Ray& ray, const Plane& plane, Vector3& point);
///
/// Determines whether there is an intersection between a and a triangle.
///
/// The ray to test.
/// The first vertex of the triangle to test.
/// The second vertex of the triangle to test.
/// The third vertex of the triangle to test.
/// When the method completes, contains the distance of the intersection, or 0 if there was no intersection.
/// Whether the two objects intersected.
///
/// This method tests if the ray intersects either the front or back of the triangle.
/// If the ray is parallel to the triangle's plane, no intersection is assumed to have
/// happened. If the intersection of the ray and the triangle is behind the origin of
/// the ray, no intersection is assumed to have happened. In both cases of assumptions,
/// this method returns false.
///
static bool RayIntersectsTriangle(const Ray& ray, const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3, Real& distance);
///
/// Determines whether there is an intersection between a and a triangle.
///
/// The ray to test.
/// The first vertex of the triangle to test.
/// The second vertex of the triangle to test.
/// The third vertex of the triangle to test.
/// When the method completes, contains the distance of the intersection, or 0 if there was no intersection.
/// When the method completes, contains the intersection surface normal vector, or Vector3::Up if there was no intersection.
/// Whether the two objects intersected.
///
/// This method tests if the ray intersects either the front or back of the triangle.
/// If the ray is parallel to the triangle's plane, no intersection is assumed to have
/// happened. If the intersection of the ray and the triangle is behind the origin of
/// the ray, no intersection is assumed to have happened. In both cases of assumptions,
/// this method returns false.
///
static bool RayIntersectsTriangle(const Ray& ray, const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3, Real& distance, Vector3& normal);
///
/// Determines whether there is an intersection between a and a triangle.
///
/// The ray to test.
/// The first vertex of the triangle to test.
/// The second vertex of the triangle to test.
/// The third vertex of the triangle to test.
/// When the method completes, contains the point of intersection, or if there was no intersection.
/// Whether the two objects intersected.
static bool RayIntersectsTriangle(const Ray& ray, const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3, Vector3& point);
///
/// Determines whether there is an intersection between a and a .
///
/// The ray to test.
/// The box to test.
/// When the method completes, contains the distance of the intersection, or 0 if there was no intersection.
/// Whether the two objects intersected.
static bool RayIntersectsBox(const Ray& ray, const BoundingBox& box, Real& distance);
///
/// Determines whether there is an intersection between a and a .
///
/// The ray to test.
/// The box to test.
/// When the method completes, contains the distance of the intersection, or 0 if there was no intersection.
/// When the method completes, contains the intersection surface normal vector, or Vector3::Up if there was no intersection.
/// Whether the two objects intersected.
static bool RayIntersectsBox(const Ray& ray, const BoundingBox& box, Real& distance, Vector3& normal);
///
/// Determines whether there is an intersection between a and a .
///
/// The ray to test.
/// The box to test.
/// When the method completes, contains the point of intersection, or if there was no intersection.
/// Whether the two objects intersected.
static bool RayIntersectsBox(const Ray& ray, const BoundingBox& box, Vector3& point);
///
/// Determines whether there is an intersection between a and a .
///
/// The ray to test.
/// The sphere to test.
/// When the method completes, contains the distance of the intersection, or 0 if there was no intersection.
/// Whether the two objects intersected.
static bool RayIntersectsSphere(const Ray& ray, const BoundingSphere& sphere, Real& distance);
///
/// Determines whether there is an intersection between a and a .
///
/// The ray to test.
/// The sphere to test.
/// When the method completes, contains the distance of the intersection, or 0 if there was no intersection.
/// When the method completes, contains the intersection surface normal vector, or Vector3::Up if there was no intersection.
/// Whether the two objects intersected.
static bool RayIntersectsSphere(const Ray& ray, const BoundingSphere& sphere, Real& distance, Vector3& normal);
///
/// Determines whether there is an intersection between a and a .
///
/// The ray to test.
/// The sphere to test.
/// When the method completes, contains the point of intersection, or if there was no intersection.
/// Whether the two objects intersected.
static bool RayIntersectsSphere(const Ray& ray, const BoundingSphere& sphere, Vector3& point);
///
/// Determines whether there is an intersection between a and a point.
///
/// The plane to test.
/// The point to test.
/// Whether the two objects intersected.
static PlaneIntersectionType PlaneIntersectsPoint(const Plane& plane, const Vector3& point);
///
/// Determines whether there is an intersection between a and a .
///
/// The first plane to test.
/// The second plane to test.
/// Whether the two objects intersected.
static bool PlaneIntersectsPlane(const Plane& plane1, const Plane& plane2);
///
/// Determines whether there is an intersection between a and a .
///
/// The first plane to test.
/// The second plane to test.
/// When the method completes, contains the line of intersection as a , or a zero ray if there was no intersection.
///
/// Whether the two objects intersected.
///
/// Although a ray is set to have an origin, the ray returned by this method is really
/// a line in three dimensions which has no real origin. The ray is considered valid when
/// both the positive direction is used and when the negative direction is used.
///
static bool PlaneIntersectsPlane(const Plane& plane1, const Plane& plane2, Ray& line);
///
/// Determines whether there is an intersection between a and a triangle.
///
/// The plane to test.
/// The first vertex of the triangle to test.
/// The second vertex of the triangle to test.
/// The third vertex of the triangle to test.
/// Whether the two objects intersected.
static PlaneIntersectionType PlaneIntersectsTriangle(const Plane& plane, const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3);
///
/// Determines whether there is an intersection between a and a .
///
/// The plane to test.
/// The box to test.
/// Whether the two objects intersected.
static PlaneIntersectionType PlaneIntersectsBox(const Plane& plane, const BoundingBox& box);
///
/// Determines whether there is an intersection between a and a .
///
/// The plane to test.
/// The sphere to test.
/// Whether the two objects intersected.
static PlaneIntersectionType PlaneIntersectsSphere(const Plane& plane, const BoundingSphere& sphere);
///
/// Determines whether there is an intersection between a and a .
///
/// The first box to test.
/// The second box to test.
/// Whether the two objects intersected.
static bool BoxIntersectsBox(const BoundingBox& box1, const BoundingBox& box2);
///
/// Determines whether there is an intersection between a and a .
///
/// The box to test.
/// The sphere to test.
/// Whether the two objects intersected.
static bool BoxIntersectsSphere(const BoundingBox& box, const BoundingSphere& sphere);
///
/// Determines whether there is an intersection between a and a triangle.
///
/// The sphere to test.
/// The first vertex of the triangle to test.
/// The second vertex of the triangle to test.
/// The third vertex of the triangle to test.
/// Whether the two objects intersected.
static bool SphereIntersectsTriangle(const BoundingSphere& sphere, const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3);
///
/// Determines whether there is an intersection between a and a
/// .
///
/// First sphere to test.
/// Second sphere to test.
/// Whether the two objects intersected.
static bool SphereIntersectsSphere(const BoundingSphere& sphere1, const BoundingSphere& sphere2);
///
/// Determines whether a contains a point.
///
/// The box to test.
/// The point to test.
/// The type of containment the two objects have.
static ContainmentType BoxContainsPoint(const BoundingBox& box, const Vector3& point);
///
/// Determines whether a contains a .
///
/// The first box to test.
/// The second box to test.
/// The type of containment the two objects have.
static ContainmentType BoxContainsBox(const BoundingBox& box1, const BoundingBox& box2);
///
/// Determines whether a contains a .
///
/// The box to test.
/// The sphere to test.
/// The type of containment the two objects have.
static ContainmentType BoxContainsSphere(const BoundingBox& box, const BoundingSphere& sphere);
///
/// Determines whether a contains a point.
///
/// The sphere to test.
/// The point to test.
/// The type of containment the two objects have.
static ContainmentType SphereContainsPoint(const BoundingSphere& sphere, const Vector3& point);
///
/// Determines whether a contains a triangle.
///
/// The sphere to test.
/// The first vertex of the triangle to test.
/// The second vertex of the triangle to test.
/// The third vertex of the triangle to test.
/// The type of containment the two objects have.
static ContainmentType SphereContainsTriangle(const BoundingSphere& sphere, const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3);
///
/// Determines whether a contains a .
///
/// The sphere to test.
/// The box to test.
/// The type of containment the two objects have.
static ContainmentType SphereContainsBox(const BoundingSphere& sphere, const BoundingBox& box);
///
/// Determines whether a contains a .
///
/// The first sphere to test.
/// The second sphere to test.
/// The type of containment the two objects have.
static ContainmentType SphereContainsSphere(const BoundingSphere& sphere1, const BoundingSphere& sphere2);
static bool FrustumIntersectsBox(const BoundingFrustum& frustum, const BoundingBox& box);
static ContainmentType FrustumContainsBox(const BoundingFrustum& frustum, const BoundingBox& box);
///
/// Determines whether a line intersects with the other line.
///
/// The first line point 0.
/// The first line point 1.
/// The second line point 0.
/// The second line point 1.
/// True if line intersects with the other line
static bool LineIntersectsLine(const Float2& l1p1, const Float2& l1p2, const Float2& l2p1, const Float2& l2p2);
///
/// Determines whether a line intersects with the rectangle.
///
/// The line point 0.
/// The line point 1.
/// The rectangle.
/// True if line intersects with the rectangle
static bool LineIntersectsRect(const Float2& p1, const Float2& p2, const Rectangle& rect);
// Hits axis-aligned box (boxMin, boxMax) with a line (lineStart, lineEnd).
// Returns the intersections on the line (x - closest, y - furthest).
// Line hits the box if: intersections.x < intersections.y.
// Hit point is: hitPoint = lineStart + (lineEnd - lineStart) * intersections.x/y.
static Vector2 LineHitsBox(const Vector3& lineStart, const Vector3& lineEnd, const Vector3& boxMin, const Vector3& boxMax);
///
/// Determines whether the given 2D point is inside the specified triangle.
///
/// The point to check.
/// The first vertex of the triangle.
/// The second vertex of the triangle.
/// The third vertex of the triangle.
/// true if point is inside the triangle; otherwise, false.
static bool IsPointInTriangle(const Float2& point, const Float2& a, const Float2& b, const Float2& c);
};