83 lines
2.8 KiB
C#
83 lines
2.8 KiB
C#
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;
|
||
|
|
}
|
||
|
|
}
|