SanAndreasUnity/Assets/Scripts/Facepunch/Utilities/MathEx.cs
2020-05-31 19:07:22 +02:00

159 lines
No EOL
4.8 KiB
C#

namespace UnityEngine
{
public static class MathExtension
{
public static float SnapToCenter(this float val, float snapValue)
{
if (snapValue == 0) return val;
return Mathf.Round((val / snapValue) + 0.5f) * snapValue - 0.5f;
}
public static float SnapToEdge(this float val, float snapValue)
{
if (snapValue == 0) return val;
return Mathf.Round(val / snapValue) * snapValue;
}
public static Vector3 SnapToCenter(this Vector2 val, float snapValue)
{
return new Vector2(val.x.SnapToCenter(snapValue), val.y.SnapToCenter(snapValue));
}
public static Vector3 SnapToEdge(this Vector2 val, float snapValue)
{
return new Vector2(val.x.SnapToEdge(snapValue), val.y.SnapToEdge(snapValue));
}
public static Vector3 SnapToCenter(this Vector3 val, float snapValue)
{
return new Vector3(val.x.SnapToCenter(snapValue), val.y.SnapToCenter(snapValue), val.z.SnapToCenter(snapValue));
}
public static Vector3 SnapToEdge(this Vector3 val, float snapValue)
{
return new Vector3(val.x.SnapToEdge(snapValue), val.y.SnapToEdge(snapValue), val.z.SnapToEdge(snapValue));
}
public static Vector3 ToVector3XZ(this Vector2 val)
{
return new Vector3(val.x, 0.0f, val.y);
}
public static float ClosestPointDistance(this Ray val, Vector3 point)
{
return Vector3.Dot(point - val.origin, val.direction);
}
public static Vector3 ClosestPoint(this Ray val, Vector3 point)
{
return val.GetPoint(val.ClosestPointDistance(point));
}
public static float ClosestRayPointDistance(this Ray val, Ray ray)
{
Vector3 v0 = val.origin;
Vector3 v1 = val.direction;
Vector3 v2 = ray.origin;
Vector3 v3 = ray.direction;
Vector3 v4 = v0 - v2;
float d0 = 0.0f;
float d1 = 0.0f;
float dv4v3 = Vector3.Dot(v4, v3);
float dv3v1 = Vector3.Dot(v3, v1);
float dv3v3 = Vector3.Dot(v3, v3);
float dv4v1 = Vector3.Dot(v4, v1);
float dv1v1 = Vector3.Dot(v1, v1);
float denom = dv1v1 * dv3v3 - dv3v1 * dv3v1;
if (Mathf.Abs(denom) > Mathf.Epsilon)
{
float numer = dv4v3 * dv3v1 - dv4v1 * dv3v3;
d0 = numer / denom;
}
else
{
d0 = 0.0f;
}
d1 = (dv4v3 + d0 * dv3v1) / dv3v3;
if (d1 >= 0.0f)
{
return d0;
}
else
{
d1 = 0.0f;
return val.ClosestPointDistance(ray.origin);
}
}
public static Vector3 ClosestRayPoint(this Ray val, Ray ray)
{
return val.GetPoint(val.ClosestRayPointDistance(ray));
}
public static int Mod(this int val, int mod)
{
int r = val % mod;
return r < 0 ? val + mod : r;
}
public static bool PlaneTest(this Ray ray, Vector3 planeCenter, Quaternion planeRot, Vector2 planeSize, out Vector3 hitPosition, float gridSize = 0.0f, bool edge = true)
{
Plane plane = new Plane(planeRot * Vector3.up, planeCenter);
hitPosition = Vector3.zero;
float hitDistance = 0.0f;
if (!plane.Raycast(ray, out hitDistance))
{
return false;
}
hitPosition = ray.origin + ray.direction * hitDistance;
Vector3 hitOffset = hitPosition - planeCenter;
float distanceLf = Vector3.Dot(hitOffset, planeRot * Vector3.left);
float distanceUp = Vector3.Dot(hitOffset, planeRot * Vector3.forward);
if (gridSize > 0.0f)
{
if (edge)
{
distanceLf = distanceLf.SnapToEdge(gridSize);
distanceUp = distanceUp.SnapToEdge(gridSize);
}
else
{
distanceLf = distanceLf.SnapToCenter(gridSize);
distanceUp = distanceUp.SnapToCenter(gridSize);
}
}
hitPosition = planeCenter;
hitPosition += (planeRot * Vector3.left) * distanceLf;
hitPosition += (planeRot * Vector3.forward) * distanceUp;
return true;
}
public static float NormalizeAngle(this float ang)
{
return ang - Mathf.Floor((ang + 180f) / 360f) * 360f;
}
public static float AngleDiff(this float ang, float other)
{
return (other - ang).NormalizeAngle();
}
}
}