232 lines
8.0 KiB
C#
232 lines
8.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using ProBuilder2.Common;
|
|
using UnityEngine;
|
|
|
|
namespace ProBuilder2.MeshOperations
|
|
{
|
|
// Token: 0x02000008 RID: 8
|
|
public static class pb_AppendPolygon
|
|
{
|
|
// Token: 0x0600005A RID: 90 RVA: 0x0000873C File Offset: 0x00006B3C
|
|
public static pb_ActionResult CreatePolygon(this pb_Object pb, IList<int> indices, bool unordered, out pb_Face face)
|
|
{
|
|
pb_IntArray[] sharedIndices = pb.sharedIndices;
|
|
Dictionary<int, int> dictionary = sharedIndices.ToDictionary();
|
|
HashSet<int> commonIndices = pb_IntArrayUtility.GetCommonIndices(dictionary, indices);
|
|
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
|
|
List<pb_Vertex> list2 = new List<pb_Vertex>();
|
|
foreach (int num in commonIndices)
|
|
{
|
|
int num2 = sharedIndices[num][0];
|
|
list2.Add(new pb_Vertex(list[num2]));
|
|
}
|
|
pb_FaceRebuildData pb_FaceRebuildData = pb_AppendPolygon.FaceWithVertices(list2, unordered);
|
|
if (pb_FaceRebuildData != null)
|
|
{
|
|
pb_FaceRebuildData.sharedIndices = commonIndices.ToList<int>();
|
|
List<pb_Face> list3 = new List<pb_Face>(pb.faces);
|
|
pb_FaceRebuildData.Apply(new pb_FaceRebuildData[] { pb_FaceRebuildData }, list, list3, dictionary, null);
|
|
pb.SetVertices(list, false);
|
|
pb.SetFaces(list3.ToArray());
|
|
pb.SetSharedIndices(dictionary);
|
|
face = pb_FaceRebuildData.face;
|
|
return new pb_ActionResult(Status.Success, "Create Polygon");
|
|
}
|
|
face = null;
|
|
return new pb_ActionResult(Status.Failure, (!unordered) ? "Points not ordered correctly" : "Too Few Unique Points Selected");
|
|
}
|
|
|
|
// Token: 0x0600005B RID: 91 RVA: 0x00008868 File Offset: 0x00006C68
|
|
public static pb_ActionResult CreateShapeFromPolygon(this pb_PolyShape poly)
|
|
{
|
|
return poly.mesh.CreateShapeFromPolygon(poly.points, poly.extrude, poly.flipNormals);
|
|
}
|
|
|
|
// Token: 0x0600005C RID: 92 RVA: 0x00008888 File Offset: 0x00006C88
|
|
public static pb_ActionResult CreateShapeFromPolygon(this pb_Object pb, IList<Vector3> points, float extrude, bool flipNormals)
|
|
{
|
|
if (points.Count < 3)
|
|
{
|
|
pb.SetVertices(new Vector3[0]);
|
|
pb.SetFaces(new pb_Face[0]);
|
|
pb.SetSharedIndices(new pb_IntArray[0]);
|
|
return new pb_ActionResult(Status.NoChange, "Too Few Points");
|
|
}
|
|
Vector3[] array = points.ToArray<Vector3>();
|
|
pb_Log.PushLogLevel(pb_LogLevel.Error);
|
|
List<int> list;
|
|
if (!pb_Triangulation.TriangulateVertices(array, out list, false, false))
|
|
{
|
|
pb_Log.PopLogLevel();
|
|
return new pb_ActionResult(Status.Failure, "Failed Triangulating Points");
|
|
}
|
|
int[] array2 = list.ToArray();
|
|
if (pb_Math.PolygonArea(array, array2) < Mathf.Epsilon)
|
|
{
|
|
pb.SetVertices(new Vector3[0]);
|
|
pb.SetFaces(new pb_Face[0]);
|
|
pb.SetSharedIndices(new pb_IntArray[0]);
|
|
pb_Log.PopLogLevel();
|
|
return new pb_ActionResult(Status.Failure, "Polygon Area < Epsilon");
|
|
}
|
|
pb.GeometryWithVerticesFaces(array, new pb_Face[]
|
|
{
|
|
new pb_Face(array2)
|
|
});
|
|
Vector3 vector = pb_Math.Normal(pb, pb.faces[0]);
|
|
if (Vector3.Dot(Vector3.up, vector) > 0f)
|
|
{
|
|
pb.faces[0].ReverseIndices();
|
|
}
|
|
pb.DuplicateAndFlip(pb.faces);
|
|
pb.Extrude(new pb_Face[] { pb.faces[1] }, ExtrudeMethod.IndividualFaces, extrude);
|
|
if ((extrude < 0f && !flipNormals) || (extrude > 0f && flipNormals))
|
|
{
|
|
pb.ReverseWindingOrder(pb.faces);
|
|
}
|
|
pb_Log.PopLogLevel();
|
|
pb.ToMesh();
|
|
pb.Refresh(RefreshMask.All);
|
|
return new pb_ActionResult(Status.Success, "Create Polygon Shape");
|
|
}
|
|
|
|
// Token: 0x0600005D RID: 93 RVA: 0x00008A0C File Offset: 0x00006E0C
|
|
public static pb_FaceRebuildData FaceWithVertices(List<pb_Vertex> vertices, bool unordered = true)
|
|
{
|
|
List<int> list;
|
|
if (pb_Triangulation.TriangulateVertices(vertices, out list, unordered, false))
|
|
{
|
|
return new pb_FaceRebuildData
|
|
{
|
|
vertices = vertices,
|
|
face = new pb_Face(list.ToArray())
|
|
};
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// Token: 0x0600005E RID: 94 RVA: 0x00008A4C File Offset: 0x00006E4C
|
|
public static List<pb_FaceRebuildData> TentCapWithVertices(List<pb_Vertex> path)
|
|
{
|
|
int count = path.Count;
|
|
pb_Vertex pb_Vertex = pb_Vertex.Average(path, null);
|
|
List<pb_FaceRebuildData> list = new List<pb_FaceRebuildData>();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
List<pb_Vertex> list2 = new List<pb_Vertex>
|
|
{
|
|
path[i],
|
|
pb_Vertex,
|
|
path[(i + 1) % count]
|
|
};
|
|
list.Add(new pb_FaceRebuildData
|
|
{
|
|
vertices = list2,
|
|
face = new pb_Face(new int[] { 0, 1, 2 })
|
|
});
|
|
}
|
|
return list;
|
|
}
|
|
|
|
// Token: 0x0600005F RID: 95 RVA: 0x00008AE8 File Offset: 0x00006EE8
|
|
public static List<List<pb_Edge>> FindHoles(pb_Object pb, IList<int> indices)
|
|
{
|
|
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
|
HashSet<int> commonIndices = pb_IntArrayUtility.GetCommonIndices(dictionary, indices);
|
|
List<List<pb_Edge>> list = new List<List<pb_Edge>>();
|
|
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, false);
|
|
foreach (List<pb_WingedEdge> list2 in pb_AppendPolygon.FindHoles(wingedEdges, commonIndices))
|
|
{
|
|
list.Add(list2.Select((pb_WingedEdge x) => x.edge.local).ToList<pb_Edge>());
|
|
}
|
|
return list;
|
|
}
|
|
|
|
// Token: 0x06000060 RID: 96 RVA: 0x00008B94 File Offset: 0x00006F94
|
|
public static List<List<pb_WingedEdge>> FindHoles(List<pb_WingedEdge> wings, HashSet<int> common)
|
|
{
|
|
HashSet<pb_WingedEdge> hashSet = new HashSet<pb_WingedEdge>();
|
|
List<List<pb_WingedEdge>> list = new List<List<pb_WingedEdge>>();
|
|
for (int i = 0; i < wings.Count; i++)
|
|
{
|
|
pb_WingedEdge pb_WingedEdge = wings[i];
|
|
if (pb_WingedEdge.opposite == null && !hashSet.Contains(pb_WingedEdge) && (common.Contains(pb_WingedEdge.edge.common.x) || common.Contains(pb_WingedEdge.edge.common.y)))
|
|
{
|
|
List<pb_WingedEdge> list2 = new List<pb_WingedEdge>();
|
|
pb_WingedEdge pb_WingedEdge2 = pb_WingedEdge;
|
|
int num = pb_WingedEdge2.edge.common.x;
|
|
int num2 = 0;
|
|
while (pb_WingedEdge2 != null && num2++ < 2048)
|
|
{
|
|
hashSet.Add(pb_WingedEdge2);
|
|
list2.Add(pb_WingedEdge2);
|
|
num = ((pb_WingedEdge2.edge.common.x != num) ? pb_WingedEdge2.edge.common.x : pb_WingedEdge2.edge.common.y);
|
|
pb_WingedEdge2 = pb_AppendPolygon.FindNextEdgeInHole(pb_WingedEdge2, num);
|
|
if (pb_WingedEdge2 == pb_WingedEdge)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
List<pb_Tuple<int, int>> list3 = new List<pb_Tuple<int, int>>();
|
|
for (int j = 0; j < list2.Count; j++)
|
|
{
|
|
pb_WingedEdge pb_WingedEdge3 = list2[j];
|
|
for (int k = j - 1; k > -1; k--)
|
|
{
|
|
if (pb_WingedEdge3.edge.common.y == list2[k].edge.common.x)
|
|
{
|
|
list3.Add(new pb_Tuple<int, int>(k, j));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
int count = list3.Count;
|
|
list3.Sort((pb_Tuple<int, int> x, pb_Tuple<int, int> y) => x.Item1.CompareTo(y.Item1));
|
|
int[] array = new int[count];
|
|
for (int l = count - 1; l > -1; l--)
|
|
{
|
|
int item = list3[l].Item1;
|
|
int num3 = list3[l].Item2 - array[l];
|
|
int num4 = num3 - item + 1;
|
|
List<pb_WingedEdge> range = list2.GetRange(item, num4);
|
|
list2.RemoveRange(item, num4);
|
|
for (int m = l - 1; m > -1; m--)
|
|
{
|
|
if (list3[m].Item2 > list3[l].Item2)
|
|
{
|
|
array[m] += num4;
|
|
}
|
|
}
|
|
if (count < 2 || range.Any((pb_WingedEdge w) => common.Contains(w.edge.common.x)) || range.Any((pb_WingedEdge w) => common.Contains(w.edge.common.y)))
|
|
{
|
|
list.Add(range);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
// Token: 0x06000061 RID: 97 RVA: 0x00008E90 File Offset: 0x00007290
|
|
private static pb_WingedEdge FindNextEdgeInHole(pb_WingedEdge wing, int common)
|
|
{
|
|
pb_WingedEdge pb_WingedEdge = wing.GetAdjacentEdgeWithCommonIndex(common);
|
|
int num = 0;
|
|
while (pb_WingedEdge != null && pb_WingedEdge != wing && num++ < 2048)
|
|
{
|
|
if (pb_WingedEdge.opposite == null)
|
|
{
|
|
return pb_WingedEdge;
|
|
}
|
|
pb_WingedEdge = pb_WingedEdge.opposite.GetAdjacentEdgeWithCommonIndex(common);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// Token: 0x04000014 RID: 20
|
|
private const int MAX_HOLE_ITERATIONS = 2048;
|
|
}
|
|
}
|