using System.Collections; using System.Collections.Generic; using UnityEngine; using static OpticalSurface2D; public class RaycastMath { public struct RaycastResult2D { public Vector2 Point; public Vector2 Normal; } public static bool RaycastCircle(Ray2D ray, float radius, ref RaycastResult2D result) { var vToCircleCenter = Vector2.zero - ray.origin; bool isInsideCircle = vToCircleCenter.magnitude < radius; var d = Vector2.Dot(vToCircleCenter, ray.direction.normalized); if(d < 0 && ray.origin.magnitude > radius) { return false; } var p = ray.origin + ray.direction.normalized * d; var v = Vector2.zero - p; var rayCenterDistance = v.magnitude; if (rayCenterDistance > radius) { return false; } else if (rayCenterDistance == radius) { result.Point = p; result.Normal = p.normalized; } else { float m = Mathf.Sqrt(radius * radius - rayCenterDistance * rayCenterDistance); if (isInsideCircle) { result.Point = p + ray.direction.normalized * m; result.Normal = result.Point.normalized; } else { result.Point = p - ray.direction.normalized * m; result.Normal = result.Point.normalized; } } return true; } public static bool RayLineIntersection(Vector2 rayOrigin, Vector2 rayDirection, Vector2 lineOrigin, Vector2 lineDirection, ref Vector2 hitPoint) { Vector2 rayTangent = new Vector2(-rayDirection.y, rayDirection.x); float distanceToLine = Vector2.Dot(lineOrigin - rayOrigin, rayTangent); float origin2ExtensionDistance = distanceToLine / Vector2.Dot(-rayTangent, lineDirection); hitPoint = origin2ExtensionDistance * lineDirection + lineOrigin; return Vector2.Dot(hitPoint - rayOrigin, rayDirection) > 0.0f; } public static bool RayLineSegmentIntersection(Vector2 rayOrigin, Vector2 rayDirection, Vector2 lineOrigin, Vector2 lineP2, ref Vector2 hitPoint) { Vector2 rayTangent = new Vector2(-rayDirection.y, rayDirection.x); Vector2 lineDirection = lineP2 - lineOrigin; float distanceToLine = Vector2.Dot(lineOrigin - rayOrigin, rayTangent); float origin2ExtensionDistance = distanceToLine / Vector2.Dot(-rayTangent, lineDirection); hitPoint = origin2ExtensionDistance * lineDirection + lineOrigin; if (Vector2.Dot(hitPoint - rayOrigin, rayDirection) < 0.0f) { return false; } var d = Vector2.Dot(hitPoint - lineOrigin, lineDirection.normalized); if (d < 0.0f || d > lineDirection.magnitude) { return false; } return true; } }