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 GetNeighborFaces(pb_Object pb, pb_Face originFace, Dictionary lookup = null, IEnumerable mask = null) { if (lookup == null) { lookup = pb.sharedIndices.ToDictionary(); } List list = new List(); HashSet hashSet = new HashSet(); 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> GenerateNeighborLookup(pb_Object pb, IList InFaces) { Dictionary dictionary = pb.sharedIndices.ToDictionary(); Dictionary> dictionary2 = new Dictionary>(); int num = InFaces.Count(); HashSet[] array = new HashSet[num]; for (int i = 0; i < num; i++) { array[i] = new HashSet(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()); } for (int k = j + 1; k < num; k++) { bool flag = array[j].Overlaps(array[k]); if (flag) { dictionary2[InFaces[j]].Add(InFaces[k]); List list; if (dictionary2.TryGetValue(InFaces[k], out list)) { list.Add(InFaces[j]); } else { dictionary2.Add(InFaces[k], new List { InFaces[j] }); } } } } return dictionary2; } // Token: 0x06000019 RID: 25 RVA: 0x00004CA4 File Offset: 0x000030A4 public static pb_Face[] GetNeighborFaces(pb_Object pb, Dictionary sharedIndicesLookup, pb_Face[] selFaces) { List list = new List(); pb_Edge[] array = pbMeshUtils.GetPerimeterEdges(sharedIndicesLookup, selFaces).ToArray(); 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 hashSet = new HashSet(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> GetNeighborFaces(pb_Object pb, pb_Edge edge, Dictionary lookup = null) { if (lookup == null) { lookup = pb.sharedIndices.ToDictionary(); } List> list = new List>(); 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.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 list = new List(); Dictionary 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().ToArray(); } // Token: 0x0600001C RID: 28 RVA: 0x00004F84 File Offset: 0x00003384 internal static List[][] GetNeighborFacesJagged(pb_Object pb, pb_Edge[][] selEdges) { int num = selEdges.Length; List[][] array = new List[num][]; for (int i = 0; i < num; i++) { array[i] = new List[selEdges[i].Length]; for (int j = 0; j < selEdges[i].Length; j++) { array[i][j] = new List(); } } 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().ToArray(); } for (int l = 0; l < pb.faces.Length; l++) { pb_Edge[] array3 = pb_Edge.GetUniversalEdges(pb.faces[l].edges, sharedIndices).Distinct().ToArray(); 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 GetNeighborFaces(pb_Object pb, int index) { List list = new List(); 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 GetNeighborFaces(pb_Object pb, IEnumerable indices) { List list = new List(); Dictionary dictionary = pb.sharedIndices.ToDictionary(); HashSet hashSet = new HashSet(); 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 dictionary = pb.sharedIndices.ToDictionary(); List list = new List(); HashSet hashSet = new HashSet(); for (int i = 0; i < indices.Length; i++) { hashSet.Add(dictionary[indices[i]]); } pb_Edge[] array = pb_Edge.AllEdges(pb.faces); HashSet hashSet2 = new HashSet(); 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 GetPerimeterEdges(pb_Object pb, IEnumerable faces) { return pbMeshUtils.GetPerimeterEdges(pb.sharedIndices.ToDictionary(), faces); } // Token: 0x06000021 RID: 33 RVA: 0x0000532C File Offset: 0x0000372C public static IEnumerable GetPerimeterEdges(Dictionary sharedIndicesLookup, IEnumerable faces) { List list = faces.SelectMany((pb_Face x) => x.edges).ToList(); int count = list.Count; Dictionary> dictionary = new Dictionary>(); for (int i = 0; i < count; i++) { pb_Edge pb_Edge = new pb_Edge(sharedIndicesLookup[list[i].x], sharedIndicesLookup[list[i].y]); List list2; if (dictionary.TryGetValue(pb_Edge, out list2)) { list2.Add(list[i]); } else { dictionary.Add(pb_Edge, new List { 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(array); List list = new List(); 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 GetPerimeterFaces(pb_Object pb, IEnumerable faces) { Dictionary dictionary = pb.sharedIndices.ToDictionary(); Dictionary> dictionary2 = new Dictionary>(); 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 }); } } } return (from x in dictionary2 where x.Value.Count < 2 select x.Value[0]).Distinct(); } // 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(array2); List list = new List(); 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 GetEdgeRing(pb_Object pb, pb_Edge[] edges) { List wingedEdges = pb_WingedEdge.GetWingedEdges(pb, false); List list = pb_EdgeLookup.GetEdgeLookup(edges, pb.sharedIndices.ToDictionary()).ToList(); list.Distinct(); Dictionary dictionary = new Dictionary(); for (int i = 0; i < wingedEdges.Count; i++) { if (!dictionary.ContainsKey(wingedEdges[i].edge.common)) { dictionary.Add(wingedEdges[i].edge.common, wingedEdges[i]); } } HashSet hashSet = new HashSet(); 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 wingedEdges = pb_WingedEdge.GetWingedEdges(pb, false); IEnumerable edgeLookup = pb_EdgeLookup.GetEdgeLookup(edges, pb.sharedIndices.ToDictionary()); HashSet hashSet = new HashSet(edgeLookup); HashSet hashSet2 = new HashSet(); 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(); return true; } // Token: 0x06000028 RID: 40 RVA: 0x00005AE4 File Offset: 0x00003EE4 private static bool GetEdgeLoopInternal(pb_WingedEdge start, int startIndex, HashSet used) { int num = startIndex; pb_WingedEdge pb_WingedEdge = start; do { used.Add(pb_WingedEdge.edge); List list = pbMeshUtils.GetSpokes(pb_WingedEdge, num, true).DistinctBy((pb_WingedEdge x) => x.edge.common).ToList(); 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 GetSpokes(pb_WingedEdge wing, int sharedIndex, bool allowHoles = false) { List list = new List(); 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 list2 = new List(); 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; } } }