Files
2026-02-21 16:45:37 +08:00

195 lines
4.9 KiB
C#

using System;
using UnityEngine;
namespace AmplifyImpostors
{
public static class Vector2Ex
{
public static float Cross(this Vector2 O, Vector2 A, Vector2 B)
{
return (A.x - O.x) * (B.y - O.y) - (A.y - O.y) * (B.x - O.x);
}
public static float TriangleArea(this Vector2 O, Vector2 A, Vector2 B)
{
return Mathf.Abs((A.x - B.x) * (O.y - A.y) - (A.x - O.x) * (B.y - A.y)) * 0.5f;
}
public static float TriangleArea(this Vector3 O, Vector3 A, Vector3 B)
{
return Mathf.Abs((A.x - B.x) * (O.y - A.y) - (A.x - O.x) * (B.y - A.y)) * 0.5f;
}
public static Vector2[] ConvexHull(Vector2[] P)
{
if (P.Length > 1)
{
int num = P.Length;
int num2 = 0;
Vector2[] array = new Vector2[2 * num];
Comparison<Vector2> comparison = (Vector2 a, Vector2 b) => (a.x == b.x) ? a.y.CompareTo(b.y) : a.x.CompareTo(b.x);
Array.Sort(P, comparison);
for (int num3 = 0; num3 < num; num3++)
{
while (num2 >= 2 && P[num3].Cross(array[num2 - 2], array[num2 - 1]) <= 0f)
{
num2--;
}
array[num2++] = P[num3];
}
int num4 = num - 2;
int num5 = num2 + 1;
while (num4 >= 0)
{
while (num2 >= num5 && P[num4].Cross(array[num2 - 2], array[num2 - 1]) <= 0f)
{
num2--;
}
array[num2++] = P[num4];
num4--;
}
if (num2 > 1)
{
Array.Resize(ref array, num2 - 1);
}
return array;
}
if (P.Length <= 1)
{
return P;
}
return null;
}
public static Vector2[] ScaleAlongNormals(Vector2[] P, float scaleAmount)
{
Vector2[] array = new Vector2[P.Length];
for (int i = 0; i < array.Length; i++)
{
int num = i - 1;
int num2 = i + 1;
if (i == 0)
{
num = P.Length - 1;
}
if (i == P.Length - 1)
{
num2 = 0;
}
Vector2 vector = P[i] - P[num];
Vector2 vector2 = P[i] - P[num2];
Vector2 normalized = (vector.normalized + vector2.normalized).normalized;
array[i] = normalized;
}
for (int j = 0; j < array.Length; j++)
{
P[j] += array[j] * scaleAmount;
}
return P;
}
private static Vector2[] ReduceLeastSignificantVertice(Vector2[] P)
{
float num = 0f;
int smallestIndex = 0;
int num2 = 0;
Vector2 vector = Vector2.zero;
for (int i = 0; i < P.Length; i++)
{
int num3 = i + 1;
int num4 = i + 2;
int num5 = i + 3;
if (num3 >= P.Length)
{
num3 -= P.Length;
}
if (num4 >= P.Length)
{
num4 -= P.Length;
}
if (num5 >= P.Length)
{
num5 -= P.Length;
}
Vector2 intersectionPointCoordinates = GetIntersectionPointCoordinates(P[i], P[num3], P[num4], P[num5]);
if (i == 0)
{
num = intersectionPointCoordinates.TriangleArea(P[num3], P[num4]);
if (OutsideBounds(intersectionPointCoordinates) > 0f)
{
num += OutsideBounds(intersectionPointCoordinates) * 1f;
}
smallestIndex = num3;
num2 = num4;
vector = intersectionPointCoordinates;
continue;
}
float num6 = intersectionPointCoordinates.TriangleArea(P[num3], P[num4]);
if (OutsideBounds(intersectionPointCoordinates) > 0f)
{
num6 += OutsideBounds(intersectionPointCoordinates) * 1f;
}
if (num6 < num && OutsideBounds(intersectionPointCoordinates) <= 0f)
{
num = num6;
smallestIndex = num3;
num2 = num4;
vector = intersectionPointCoordinates;
}
}
P[num2] = vector;
return Array.FindAll(P, (Vector2 x) => Array.IndexOf(P, x) != smallestIndex);
}
public static Vector2[] ReduceVertices(Vector2[] P, int maxVertices)
{
if (maxVertices == 4)
{
Rect rect = new Rect(P[0].x, P[0].y, 0f, 0f);
for (int i = 0; i < P.Length; i++)
{
rect.xMin = Mathf.Min(rect.xMin, P[i].x);
rect.xMax = Mathf.Max(rect.xMax, P[i].x);
rect.yMin = Mathf.Min(rect.yMin, P[i].y);
rect.yMax = Mathf.Max(rect.yMax, P[i].y);
}
P = new Vector2[4]
{
new Vector2(rect.xMin, rect.yMin),
new Vector2(rect.xMax, rect.yMin),
new Vector2(rect.xMax, rect.yMax),
new Vector2(rect.xMin, rect.yMax)
};
}
else
{
int num = Math.Max(0, P.Length - maxVertices);
for (int j = 0; j < num; j++)
{
P = ReduceLeastSignificantVertice(P);
}
}
return P;
}
private static Vector2 GetIntersectionPointCoordinates(Vector2 A1, Vector2 A2, Vector2 B1, Vector2 B2)
{
float num = (B2.x - B1.x) * (A2.y - A1.y) - (B2.y - B1.y) * (A2.x - A1.x);
if (num == 0f)
{
return (Vector2.Lerp(A2, B1, 0.5f) - Vector2.one * 0.5f) * 1000f + Vector2.one * 500f;
}
float num2 = ((A1.x - B1.x) * (A2.y - A1.y) - (A1.y - B1.y) * (A2.x - A1.x)) / num;
return new Vector2(B1.x + (B2.x - B1.x) * num2, B1.y + (B2.y - B1.y) * num2);
}
private static float OutsideBounds(Vector2 P)
{
P -= Vector2.one * 0.5f;
float num = Mathf.Clamp01(Mathf.Abs(P.y) - 0.5f);
float num2 = Mathf.Clamp01(Mathf.Abs(P.x) - 0.5f);
return num2 + num;
}
}
}