// 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); };