79 lines
2.7 KiB
C#
Raw Normal View History

2025-07-11 15:42:48 +05:00
using UnityEngine;
using static MenteBacata.ScivoloCharacterController.Internal.Math;
namespace MenteBacata.ScivoloCharacterController.Internal
{
/*
* Defines a bounding volume with rectangular section and which extends indefinitely both upward and downward.
*/
public struct BoundingRectangle
{
public Vector3 center;
public Vector3 forwardDirection;
public Vector3 rightDirection;
public float forwardExtent;
public float rightExtent;
public bool IsPointInside(Vector3 point)
{
Vector3 centerToPoint = point - center;
return Mathf.Abs(Dot(centerToPoint, forwardDirection)) - forwardExtent <= 0f &&
Mathf.Abs(Dot(centerToPoint, rightDirection)) - rightExtent <= 0f;
}
/// <summary>
/// Checks if a line, assuming it starts inside the bounding rectangle, intersects the bounding rectangle surface.
/// </summary>
/// <returns>True if it intersect, false otherwise.</returns>
public bool CheckLineIntersectionFromInsideToOutside(Vector3 lineStart, Vector3 lineEnd, out Vector3 intersectionPoint)
{
Vector3 centerToStart = lineStart - center;
Vector3 startToEnd = lineEnd - lineStart;
float startToEndDotForward = Dot(startToEnd, forwardDirection);
float startToEndDotRight = Dot(startToEnd, rightDirection);
float tMin = float.MaxValue;
if (startToEndDotForward > 0f)
{
float t = -(Dot(centerToStart, forwardDirection) - forwardExtent) / startToEndDotForward;
if (0f <= t && t <= 1f)
tMin = t;
}
else if (startToEndDotForward < 0f)
{
float t = (-Dot(centerToStart, forwardDirection) - forwardExtent) / startToEndDotForward;
if (0f <= t && t <= 1f)
tMin = t;
}
if (startToEndDotRight > 0f)
{
float t = -(Dot(centerToStart, rightDirection) - rightExtent) / startToEndDotRight;
if (0f <= t && t <= 1f && t < tMin)
tMin = t;
}
else if (startToEndDotRight < 0f)
{
float t = (-Dot(centerToStart, rightDirection) - rightExtent) / startToEndDotRight;
if (0f <= t && t <= 1f && t < tMin)
tMin = t;
}
if (tMin <= 1f)
{
intersectionPoint = lineStart + tMin * startToEnd;
return true;
}
intersectionPoint = default;
return false;
}
}
}