// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Platform/Platform.h"
#include "Vector3.h"
#include "CollisionsHelper.h"
struct Viewport;
///
/// Represents a three dimensional line based on a point in space and a direction.
///
API_STRUCT() struct Ray
{
DECLARE_SCRIPTING_TYPE_MINIMAL(Ray);
public:
///
/// The position in three dimensional space where the ray starts.
///
API_FIELD() Vector3 Position;
///
/// The normalized direction in which the ray points.
///
API_FIELD() Vector3 Direction;
public:
///
/// Identity ray (at zero origin pointing forwards).
///
static Ray Identity;
public:
///
/// Empty constructor.
///
Ray()
{
}
///
/// Initializes a new instance of the struct.
///
/// The ray origin position in 3D space.
/// The normalized ray direction in 3D space.
Ray(const Vector3& position, const Vector3& direction)
: Position(position)
, Direction(direction)
{
}
public:
String ToString() const;
public:
FORCE_INLINE bool operator==(const Ray& other) const
{
return Position == other.Position && Direction == other.Direction;
}
FORCE_INLINE bool operator!=(const Ray& other) const
{
return Position != other.Position || Direction != other.Direction;
}
static bool NearEqual(const Ray& a, const Ray& b)
{
return Vector3::NearEqual(a.Position, b.Position) && Vector3::NearEqual(a.Direction, b.Direction);
}
static bool NearEqual(const Ray& a, const Ray& b, float epsilon)
{
return Vector3::NearEqual(a.Position, b.Position, epsilon) && Vector3::NearEqual(a.Direction, b.Direction, epsilon);
}
public:
///
/// Gets a point at distance long ray.
///
/// The distance from ray origin.
/// The calculated point.
Vector3 GetPoint(float distance) const;
///
/// Determines if there is an intersection between the current object and a point.
///
/// The point to test.
/// Whether the two objects intersected.
bool Intersects(const Vector3& point) const
{
return CollisionsHelper::RayIntersectsPoint(*this, point);
}
///
/// Determines if there is an intersection between the current object and a .
///
/// The ray to test.
/// Whether the two objects intersected.
bool Intersects(const Ray& ray) const
{
Vector3 point;
return CollisionsHelper::RayIntersectsRay(*this, ray, point);
}
///
/// Determines if there is an intersection between the current object and a .
///
/// The ray to test.
/// When the method completes, contains the point of intersection, or if there was no intersection.
///
/// Whether the two objects intersected.
bool Intersects(const Ray& ray, Vector3& point) const
{
return CollisionsHelper::RayIntersectsRay(*this, ray, point);
}
///
/// Determines if there is an intersection between the current object and a .
///
/// The plane to test
/// Whether the two objects intersected.
bool Intersects(const Plane& plane) const
{
float distance;
return CollisionsHelper::RayIntersectsPlane(*this, plane, distance);
}
///
/// Determines if there is an intersection between the current object and a .
///
/// 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 intersected.
bool Intersects(const Plane& plane, float& distance) const
{
return CollisionsHelper::RayIntersectsPlane(*this, plane, distance);
}
///
/// Determines if there is an intersection between the current object and a .
///
/// The plane to test.
/// When the method completes, contains the point of intersection, or if there was no intersection.
/// Whether the two objects intersected.
bool Intersects(const Plane& plane, Vector3& point) const
{
return CollisionsHelper::RayIntersectsPlane(*this, plane, point);
}
///
/// Determines if there is an intersection between the current object and a triangle.
///
/// 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.
bool Intersects(const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3) const
{
float distance;
return CollisionsHelper::RayIntersectsTriangle(*this, vertex1, vertex2, vertex3, distance);
}
///
/// Determines if there is an intersection between the current object and a triangle.
///
/// 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.
bool Intersects(const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3, float& distance) const
{
return CollisionsHelper::RayIntersectsTriangle(*this, vertex1, vertex2, vertex3, distance);
}
///
/// Determines if there is an intersection between the current object and a triangle.
///
/// 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.
bool Intersects(const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3, Vector3& point) const
{
return CollisionsHelper::RayIntersectsTriangle(*this, vertex1, vertex2, vertex3, point);
}
///
/// Determines if there is an intersection between the current object and a .
///
/// The box to test.
/// Whether the two objects intersected.
bool Intersects(const BoundingBox& box) const
{
float distance;
return CollisionsHelper::RayIntersectsBox(*this, box, distance);
}
///
/// Determines if there is an intersection between the current object and a .
///
/// 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.
bool Intersects(const BoundingBox& box, float& distance) const
{
return CollisionsHelper::RayIntersectsBox(*this, box, distance);
}
///
/// Determines if there is an intersection between the current object and a .
///
/// The box to test.
/// When the method completes, contains the point of intersection, or if there was no intersection.
/// Whether the two objects intersected.
bool Intersects(const BoundingBox& box, Vector3& point) const
{
return CollisionsHelper::RayIntersectsBox(*this, box, point);
}
///
/// Determines if there is an intersection between the current object and a .
///
/// The sphere to test.
/// Whether the two objects intersected.
bool Intersects(const BoundingSphere& sphere) const
{
float distance;
return CollisionsHelper::RayIntersectsSphere(*this, sphere, distance);
}
///
/// Determines if there is an intersection between the current object and a .
///
/// 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.
bool Intersects(const BoundingSphere& sphere, float& distance) const
{
return CollisionsHelper::RayIntersectsSphere(*this, sphere, distance);
}
///
/// Determines if there is an intersection between the current object and a .
///
/// The sphere to test.
/// When the method completes, contains the point of intersection, or if there was no intersection.
/// Whether the two objects intersected.
bool Intersects(const BoundingSphere& sphere, Vector3& point) const
{
return CollisionsHelper::RayIntersectsSphere(*this, sphere, point);
}
public:
///
/// Calculates a world space ray from 2d screen coordinates.
///
/// The X coordinate on 2d screen.
/// The Y coordinate on 2d screen.
/// The screen viewport.
/// The View*Projection matrix.
/// The resulting ray.
static Ray GetPickRay(float x, float y, const Viewport& viewport, const Matrix& vp);
};
template<>
struct TIsPODType
{
enum { Value = true };
};
DEFINE_DEFAULT_FORMATTING(Ray, "Position:{0} Direction:{1}", v.Position, v.Direction);