195 lines
4.9 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|