Files
2026-06-04 11:42:34 +02:00

571 lines
17 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using ProBuilder2.Common;
namespace ProBuilder2.MeshOperations
{
// Token: 0x02000003 RID: 3
public class pbMeshUtils
{
// Token: 0x06000017 RID: 23 RVA: 0x00004A30 File Offset: 0x00002E30
public static List<pb_Face> GetNeighborFaces(pb_Object pb, pb_Face originFace, Dictionary<int, int> lookup = null, IEnumerable<pb_Face> mask = null)
{
if (lookup == null)
{
lookup = pb.sharedIndices.ToDictionary();
}
List<pb_Face> list = new List<pb_Face>();
HashSet<pb_Edge> hashSet = new HashSet<pb_Edge>();
for (int i = 0; i < originFace.edges.Length; i++)
{
hashSet.Add(new pb_Edge(lookup[originFace.edges[i].x], lookup[originFace.edges[i].y]));
}
pb_Edge pb_Edge = new pb_Edge(-1, -1);
for (int j = 0; j < pb.faces.Length; j++)
{
foreach (pb_Edge pb_Edge2 in pb.faces[j].edges)
{
pb_Edge.x = lookup[pb_Edge2.x];
pb_Edge.y = lookup[pb_Edge2.y];
bool flag = hashSet.Contains(pb_Edge);
if (flag && (mask == null || !mask.Contains(pb.faces[j])))
{
list.Add(pb.faces[j]);
break;
}
}
}
return list;
}
// Token: 0x06000018 RID: 24 RVA: 0x00004B64 File Offset: 0x00002F64
public static Dictionary<pb_Face, List<pb_Face>> GenerateNeighborLookup(pb_Object pb, IList<pb_Face> InFaces)
{
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
Dictionary<pb_Face, List<pb_Face>> dictionary2 = new Dictionary<pb_Face, List<pb_Face>>();
int num = InFaces.Count<pb_Face>();
HashSet<pb_Edge>[] array = new HashSet<pb_Edge>[num];
for (int i = 0; i < num; i++)
{
array[i] = new HashSet<pb_Edge>(pb_Edge.GetUniversalEdges(InFaces[i].edges, dictionary));
}
for (int j = 0; j < num - 1; j++)
{
if (!dictionary2.ContainsKey(InFaces[j]))
{
dictionary2.Add(InFaces[j], new List<pb_Face>());
}
for (int k = j + 1; k < num; k++)
{
bool flag = array[j].Overlaps(array[k]);
if (flag)
{
dictionary2[InFaces[j]].Add(InFaces[k]);
List<pb_Face> list;
if (dictionary2.TryGetValue(InFaces[k], out list))
{
list.Add(InFaces[j]);
}
else
{
dictionary2.Add(InFaces[k], new List<pb_Face> { InFaces[j] });
}
}
}
}
return dictionary2;
}
// Token: 0x06000019 RID: 25 RVA: 0x00004CA4 File Offset: 0x000030A4
public static pb_Face[] GetNeighborFaces(pb_Object pb, Dictionary<int, int> sharedIndicesLookup, pb_Face[] selFaces)
{
List<pb_Face> list = new List<pb_Face>();
pb_Edge[] array = pbMeshUtils.GetPerimeterEdges(sharedIndicesLookup, selFaces).ToArray<pb_Edge>();
pb_Edge[] array2 = new pb_Edge[array.Length];
for (int i = 0; i < array.Length; i++)
{
array2[i] = new pb_Edge(sharedIndicesLookup[array[i].x], sharedIndicesLookup[array[i].y]);
}
pb_Edge pb_Edge = new pb_Edge(-1, -1);
HashSet<pb_Face> hashSet = new HashSet<pb_Face>(selFaces);
foreach (pb_Face pb_Face in pb.faces)
{
if (hashSet.Contains(pb_Face))
{
hashSet.Remove(pb_Face);
}
else
{
foreach (pb_Edge pb_Edge2 in pb_Face.edges)
{
pb_Edge.x = sharedIndicesLookup[pb_Edge2.x];
pb_Edge.y = sharedIndicesLookup[pb_Edge2.y];
if (array2.Contains(pb_Edge))
{
list.Add(pb_Face);
break;
}
}
}
}
return list.ToArray();
}
// Token: 0x0600001A RID: 26 RVA: 0x00004DCC File Offset: 0x000031CC
public static List<pb_Tuple<pb_Face, pb_Edge>> GetNeighborFaces(pb_Object pb, pb_Edge edge, Dictionary<int, int> lookup = null)
{
if (lookup == null)
{
lookup = pb.sharedIndices.ToDictionary();
}
List<pb_Tuple<pb_Face, pb_Edge>> list = new List<pb_Tuple<pb_Face, pb_Edge>>();
pb_Edge pb_Edge = new pb_Edge(lookup[edge.x], lookup[edge.y]);
pb_Edge pb_Edge2 = new pb_Edge(0, 0);
for (int i = 0; i < pb.faces.Length; i++)
{
pb_Edge[] edges = pb.faces[i].edges;
for (int j = 0; j < edges.Length; j++)
{
pb_Edge2.x = edges[j].x;
pb_Edge2.y = edges[j].y;
if ((pb_Edge.x == lookup[pb_Edge2.x] && pb_Edge.y == lookup[pb_Edge2.y]) || (pb_Edge.x == lookup[pb_Edge2.y] && pb_Edge.y == lookup[pb_Edge2.x]))
{
list.Add(new pb_Tuple<pb_Face, pb_Edge>(pb.faces[i], new pb_Edge(edges[j])));
break;
}
}
}
return list;
}
// Token: 0x0600001B RID: 27 RVA: 0x00004EF8 File Offset: 0x000032F8
public static pb_Face[] GetNeighborFaces(pb_Object pb, pb_Edge[] edges)
{
List<pb_Face> list = new List<pb_Face>();
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
foreach (pb_Face pb_Face in pb.faces)
{
foreach (pb_Edge pb_Edge in edges)
{
if (pb_Face.edges.IndexOf(pb_Edge, dictionary) > -1)
{
list.Add(pb_Face);
}
}
}
return list.Distinct<pb_Face>().ToArray<pb_Face>();
}
// Token: 0x0600001C RID: 28 RVA: 0x00004F84 File Offset: 0x00003384
internal static List<pb_Face>[][] GetNeighborFacesJagged(pb_Object pb, pb_Edge[][] selEdges)
{
int num = selEdges.Length;
List<pb_Face>[][] array = new List<pb_Face>[num][];
for (int i = 0; i < num; i++)
{
array[i] = new List<pb_Face>[selEdges[i].Length];
for (int j = 0; j < selEdges[i].Length; j++)
{
array[i][j] = new List<pb_Face>();
}
}
pb_IntArray[] sharedIndices = pb.sharedIndices;
pb_Edge[][] array2 = new pb_Edge[num][];
for (int k = 0; k < num; k++)
{
array2[k] = pb_Edge.GetUniversalEdges(selEdges[k], sharedIndices).Distinct<pb_Edge>().ToArray<pb_Edge>();
}
for (int l = 0; l < pb.faces.Length; l++)
{
pb_Edge[] array3 = pb_Edge.GetUniversalEdges(pb.faces[l].edges, sharedIndices).Distinct<pb_Edge>().ToArray<pb_Edge>();
for (int m = 0; m < num; m++)
{
int num2 = -1;
for (int n = 0; n < array2[m].Length; n++)
{
if (array3.Contains(array2[m][n]))
{
num2 = n;
break;
}
}
if (num2 > -1)
{
array[m][num2].Add(pb.faces[l]);
}
}
}
return array;
}
// Token: 0x0600001D RID: 29 RVA: 0x000050CC File Offset: 0x000034CC
public static List<pb_Face> GetNeighborFaces(pb_Object pb, int index)
{
List<pb_Face> list = new List<pb_Face>();
pb_IntArray[] sharedIndices = pb.sharedIndices;
int num = sharedIndices.IndexOf(index);
foreach (pb_Face pb_Face in pb.faces)
{
if (pb_Face.distinctIndices.ContainsMatch(sharedIndices[num]))
{
list.Add(pb_Face);
}
}
return list;
}
// Token: 0x0600001E RID: 30 RVA: 0x00005138 File Offset: 0x00003538
public static IEnumerable<pb_Face> GetNeighborFaces(pb_Object pb, IEnumerable<int> indices)
{
List<pb_Face> list = new List<pb_Face>();
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
HashSet<int> hashSet = new HashSet<int>();
foreach (int num in indices)
{
hashSet.Add(dictionary[num]);
}
for (int i = 0; i < pb.faces.Length; i++)
{
int[] distinctIndices = pb.faces[i].distinctIndices;
for (int j = 0; j < distinctIndices.Length; j++)
{
if (hashSet.Contains(dictionary[distinctIndices[j]]))
{
list.Add(pb.faces[i]);
break;
}
}
}
return list;
}
// Token: 0x0600001F RID: 31 RVA: 0x00005224 File Offset: 0x00003624
public static pb_Edge[] GetConnectedEdges(pb_Object pb, int[] indices)
{
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
List<pb_Edge> list = new List<pb_Edge>();
HashSet<int> hashSet = new HashSet<int>();
for (int i = 0; i < indices.Length; i++)
{
hashSet.Add(dictionary[indices[i]]);
}
pb_Edge[] array = pb_Edge.AllEdges(pb.faces);
HashSet<pb_Edge> hashSet2 = new HashSet<pb_Edge>();
pb_Edge pb_Edge = new pb_Edge(0, 0);
for (int j = 0; j < array.Length; j++)
{
pb_Edge pb_Edge2 = new pb_Edge(dictionary[array[j].x], dictionary[array[j].y]);
if (hashSet.Contains(pb_Edge2.x) || (hashSet.Contains(pb_Edge2.y) && !hashSet2.Contains(pb_Edge)))
{
list.Add(array[j]);
hashSet2.Add(pb_Edge2);
}
}
return list.ToArray();
}
// Token: 0x06000020 RID: 32 RVA: 0x00005317 File Offset: 0x00003717
public static IEnumerable<pb_Edge> GetPerimeterEdges(pb_Object pb, IEnumerable<pb_Face> faces)
{
return pbMeshUtils.GetPerimeterEdges(pb.sharedIndices.ToDictionary(), faces);
}
// Token: 0x06000021 RID: 33 RVA: 0x0000532C File Offset: 0x0000372C
public static IEnumerable<pb_Edge> GetPerimeterEdges(Dictionary<int, int> sharedIndicesLookup, IEnumerable<pb_Face> faces)
{
List<pb_Edge> list = faces.SelectMany((pb_Face x) => x.edges).ToList<pb_Edge>();
int count = list.Count;
Dictionary<pb_Edge, List<pb_Edge>> dictionary = new Dictionary<pb_Edge, List<pb_Edge>>();
for (int i = 0; i < count; i++)
{
pb_Edge pb_Edge = new pb_Edge(sharedIndicesLookup[list[i].x], sharedIndicesLookup[list[i].y]);
List<pb_Edge> list2;
if (dictionary.TryGetValue(pb_Edge, out list2))
{
list2.Add(list[i]);
}
else
{
dictionary.Add(pb_Edge, new List<pb_Edge> { list[i] });
}
}
return from x in dictionary
where x.Value.Count < 2
select x.Value[0];
}
// Token: 0x06000022 RID: 34 RVA: 0x0000543C File Offset: 0x0000383C
public static int[] GetPerimeterEdges(pb_Object pb, pb_Edge[] edges)
{
if (edges.Length == pb_Edge.AllEdges(pb.faces).Length || edges.Length < 3)
{
return new int[0];
}
pb_Edge[] universalEdges = pb_Edge.GetUniversalEdges(edges, pb.sharedIndices.ToDictionary());
int[] array = new int[universalEdges.Length];
for (int i = 0; i < universalEdges.Length - 1; i++)
{
for (int j = i + 1; j < universalEdges.Length; j++)
{
if (universalEdges[i].x == universalEdges[j].x || universalEdges[i].x == universalEdges[j].y || universalEdges[i].y == universalEdges[j].x || universalEdges[i].y == universalEdges[j].y)
{
array[i]++;
array[j]++;
}
}
}
int num = pb_Math.Min<int>(array);
List<int> list = new List<int>();
for (int k = 0; k < array.Length; k++)
{
if (array[k] <= num)
{
list.Add(k);
}
}
return (list.Count == edges.Length) ? new int[0] : list.ToArray();
}
// Token: 0x06000023 RID: 35 RVA: 0x00005580 File Offset: 0x00003980
public static IEnumerable<pb_Face> GetPerimeterFaces(pb_Object pb, IEnumerable<pb_Face> faces)
{
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
Dictionary<pb_Edge, List<pb_Face>> dictionary2 = new Dictionary<pb_Edge, List<pb_Face>>();
foreach (pb_Face pb_Face in faces)
{
foreach (pb_Edge pb_Edge in pb_Face.edges)
{
pb_Edge pb_Edge2 = new pb_Edge(dictionary[pb_Edge.x], dictionary[pb_Edge.y]);
if (dictionary2.ContainsKey(pb_Edge2))
{
dictionary2[pb_Edge2].Add(pb_Face);
}
else
{
dictionary2.Add(pb_Edge2, new List<pb_Face> { pb_Face });
}
}
}
return (from x in dictionary2
where x.Value.Count < 2
select x.Value[0]).Distinct<pb_Face>();
}
// Token: 0x06000024 RID: 36 RVA: 0x000056AC File Offset: 0x00003AAC
public static int[] GetPerimeterVertices(pb_Object pb, int[] indices, pb_Edge[] universal_edges_all)
{
int num = indices.Length;
pb_IntArray[] sharedIndices = pb.sharedIndices;
int[] array = new int[num];
for (int i = 0; i < num; i++)
{
array[i] = sharedIndices.IndexOf(indices[i]);
}
int[] array2 = new int[indices.Length];
for (int j = 0; j < indices.Length - 1; j++)
{
for (int k = j + 1; k < indices.Length; k++)
{
if (universal_edges_all.Contains(array[j], array[k]))
{
array2[j]++;
array2[k]++;
}
}
}
int num2 = pb_Math.Min<int>(array2);
List<int> list = new List<int>();
for (int l = 0; l < num; l++)
{
if (array2[l] <= num2)
{
list.Add(l);
}
}
return (list.Count >= num) ? new int[0] : list.ToArray();
}
// Token: 0x06000025 RID: 37 RVA: 0x000057B4 File Offset: 0x00003BB4
private static pb_WingedEdge EdgeRingNext(pb_WingedEdge edge)
{
if (edge == null)
{
return null;
}
pb_WingedEdge pb_WingedEdge = edge.next;
pb_WingedEdge pb_WingedEdge2 = edge.previous;
int num = 0;
while (pb_WingedEdge != pb_WingedEdge2 && pb_WingedEdge != edge)
{
pb_WingedEdge = pb_WingedEdge.next;
if (pb_WingedEdge == pb_WingedEdge2)
{
return null;
}
pb_WingedEdge2 = pb_WingedEdge2.previous;
num++;
}
if (num % 2 == 0 || pb_WingedEdge == edge)
{
pb_WingedEdge = null;
}
return pb_WingedEdge;
}
// Token: 0x06000026 RID: 38 RVA: 0x0000581C File Offset: 0x00003C1C
public static IEnumerable<pb_Edge> GetEdgeRing(pb_Object pb, pb_Edge[] edges)
{
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, false);
List<pb_EdgeLookup> list = pb_EdgeLookup.GetEdgeLookup(edges, pb.sharedIndices.ToDictionary()).ToList<pb_EdgeLookup>();
list.Distinct<pb_EdgeLookup>();
Dictionary<pb_Edge, pb_WingedEdge> dictionary = new Dictionary<pb_Edge, pb_WingedEdge>();
for (int i = 0; i < wingedEdges.Count; i++)
{
if (!dictionary.ContainsKey(wingedEdges[i].edge.common))
{
dictionary.Add(wingedEdges[i].edge.common, wingedEdges[i]);
}
}
HashSet<pb_EdgeLookup> hashSet = new HashSet<pb_EdgeLookup>();
for (int j = 0; j < list.Count; j++)
{
pb_WingedEdge pb_WingedEdge;
if (dictionary.TryGetValue(list[j].common, out pb_WingedEdge) && !hashSet.Contains(pb_WingedEdge.edge))
{
pb_WingedEdge pb_WingedEdge2 = pb_WingedEdge;
while (pb_WingedEdge2 != null)
{
if (!hashSet.Add(pb_WingedEdge2.edge))
{
break;
}
pb_WingedEdge2 = pbMeshUtils.EdgeRingNext(pb_WingedEdge2);
if (pb_WingedEdge2 != null && pb_WingedEdge2.opposite != null)
{
pb_WingedEdge2 = pb_WingedEdge2.opposite;
}
}
pb_WingedEdge2 = pbMeshUtils.EdgeRingNext(pb_WingedEdge.opposite);
if (pb_WingedEdge2 != null && pb_WingedEdge2.opposite != null)
{
pb_WingedEdge2 = pb_WingedEdge2.opposite;
}
while (pb_WingedEdge2 != null)
{
if (!hashSet.Add(pb_WingedEdge2.edge))
{
break;
}
pb_WingedEdge2 = pbMeshUtils.EdgeRingNext(pb_WingedEdge2);
if (pb_WingedEdge2 != null && pb_WingedEdge2.opposite != null)
{
pb_WingedEdge2 = pb_WingedEdge2.opposite;
}
}
}
}
return hashSet.Select((pb_EdgeLookup x) => x.local);
}
// Token: 0x06000027 RID: 39 RVA: 0x000059E0 File Offset: 0x00003DE0
public static bool GetEdgeLoop(pb_Object pb, pb_Edge[] edges, out pb_Edge[] loop)
{
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, false);
IEnumerable<pb_EdgeLookup> edgeLookup = pb_EdgeLookup.GetEdgeLookup(edges, pb.sharedIndices.ToDictionary());
HashSet<pb_EdgeLookup> hashSet = new HashSet<pb_EdgeLookup>(edgeLookup);
HashSet<pb_EdgeLookup> hashSet2 = new HashSet<pb_EdgeLookup>();
for (int i = 0; i < wingedEdges.Count; i++)
{
if (!hashSet2.Contains(wingedEdges[i].edge) && hashSet.Contains(wingedEdges[i].edge))
{
if (!pbMeshUtils.GetEdgeLoopInternal(wingedEdges[i], wingedEdges[i].edge.common.y, hashSet2))
{
pbMeshUtils.GetEdgeLoopInternal(wingedEdges[i], wingedEdges[i].edge.common.x, hashSet2);
}
}
}
loop = hashSet2.Select((pb_EdgeLookup x) => x.local).ToArray<pb_Edge>();
return true;
}
// Token: 0x06000028 RID: 40 RVA: 0x00005AE4 File Offset: 0x00003EE4
private static bool GetEdgeLoopInternal(pb_WingedEdge start, int startIndex, HashSet<pb_EdgeLookup> used)
{
int num = startIndex;
pb_WingedEdge pb_WingedEdge = start;
do
{
used.Add(pb_WingedEdge.edge);
List<pb_WingedEdge> list = pbMeshUtils.GetSpokes(pb_WingedEdge, num, true).DistinctBy((pb_WingedEdge x) => x.edge.common).ToList<pb_WingedEdge>();
pb_WingedEdge = null;
if (list != null && list.Count == 4)
{
pb_WingedEdge = list[2];
num = ((pb_WingedEdge.edge.common.x != num) ? pb_WingedEdge.edge.common.x : pb_WingedEdge.edge.common.y);
}
}
while (pb_WingedEdge != null && !used.Contains(pb_WingedEdge.edge));
return pb_WingedEdge != null;
}
// Token: 0x06000029 RID: 41 RVA: 0x00005BA8 File Offset: 0x00003FA8
private static pb_WingedEdge NextSpoke(pb_WingedEdge wing, int pivot, bool opp)
{
if (opp)
{
return wing.opposite;
}
if (wing.next.edge.common.Contains(pivot))
{
return wing.next;
}
if (wing.previous.edge.common.Contains(pivot))
{
return wing.previous;
}
return null;
}
// Token: 0x0600002A RID: 42 RVA: 0x00005C08 File Offset: 0x00004008
public static List<pb_WingedEdge> GetSpokes(pb_WingedEdge wing, int sharedIndex, bool allowHoles = false)
{
List<pb_WingedEdge> list = new List<pb_WingedEdge>();
pb_WingedEdge pb_WingedEdge = wing;
bool flag = false;
for (;;)
{
list.Add(pb_WingedEdge);
pb_WingedEdge = pbMeshUtils.NextSpoke(pb_WingedEdge, sharedIndex, flag);
flag = !flag;
if (pb_WingedEdge != null && pb_WingedEdge.edge.common.Equals(wing.edge.common))
{
break;
}
if (pb_WingedEdge == null)
{
goto Block_3;
}
}
return list;
Block_3:
if (!allowHoles)
{
return null;
}
pb_WingedEdge = wing.opposite;
flag = false;
List<pb_WingedEdge> list2 = new List<pb_WingedEdge>();
while (pb_WingedEdge != null && !pb_WingedEdge.edge.common.Equals(wing.edge.common))
{
list2.Add(pb_WingedEdge);
pb_WingedEdge = pbMeshUtils.NextSpoke(pb_WingedEdge, sharedIndex, flag);
flag = !flag;
}
list2.Reverse();
list.AddRange(list2);
return list;
}
}
}