scripts
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ProBuilder2.Common;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x0200000B RID: 11
|
||||
internal class ConnectFaceRebuildData
|
||||
{
|
||||
// Token: 0x06000073 RID: 115 RVA: 0x0000A34D File Offset: 0x0000874D
|
||||
public ConnectFaceRebuildData(pb_FaceRebuildData faceRebuildData, List<int> newVertexIndices)
|
||||
{
|
||||
this.faceRebuildData = faceRebuildData;
|
||||
this.newVertexIndices = newVertexIndices;
|
||||
}
|
||||
|
||||
// Token: 0x0400001D RID: 29
|
||||
public pb_FaceRebuildData faceRebuildData;
|
||||
|
||||
// Token: 0x0400001E RID: 30
|
||||
public List<int> newVertexIndices;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,905 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ProBuilder2.Common;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x02000002 RID: 2
|
||||
public static class pbMeshOps
|
||||
{
|
||||
// Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000450
|
||||
public static void CenterPivot(this pb_Object pb, int[] indices)
|
||||
{
|
||||
Vector3 vector = Vector3.zero;
|
||||
if (indices != null && indices.Length > 0)
|
||||
{
|
||||
Vector3[] array = pb.VerticesInWorldSpace(indices);
|
||||
foreach (Vector3 vector2 in array)
|
||||
{
|
||||
vector += vector2;
|
||||
}
|
||||
vector /= (float)array.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
vector = pb.transform.TransformPoint(pb.msh.bounds.center);
|
||||
}
|
||||
Vector3 vector3 = pb.transform.position - vector;
|
||||
pb.transform.position = vector;
|
||||
pb.ToMesh();
|
||||
pb.TranslateVertices_World(pb.msh.triangles, vector3);
|
||||
pb.Refresh(RefreshMask.All);
|
||||
}
|
||||
|
||||
// Token: 0x06000002 RID: 2 RVA: 0x00002120 File Offset: 0x00000520
|
||||
public static void CenterPivot(this pb_Object pb, Vector3 worldPosition)
|
||||
{
|
||||
Vector3 vector = pb.transform.position - worldPosition;
|
||||
pb.transform.position = worldPosition;
|
||||
pb.ToMesh();
|
||||
pb.TranslateVertices_World(pb.msh.triangles, vector);
|
||||
pb.Refresh(RefreshMask.All);
|
||||
}
|
||||
|
||||
// Token: 0x06000003 RID: 3 RVA: 0x00002170 File Offset: 0x00000570
|
||||
public static void FreezeScaleTransform(this pb_Object pb)
|
||||
{
|
||||
Vector3[] vertices = pb.vertices;
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
vertices[i] = Vector3.Scale(vertices[i], pb.transform.localScale);
|
||||
}
|
||||
pb.SetVertices(vertices);
|
||||
pb.transform.localScale = new Vector3(1f, 1f, 1f);
|
||||
}
|
||||
|
||||
// Token: 0x06000004 RID: 4 RVA: 0x000021E8 File Offset: 0x000005E8
|
||||
[Obsolete("Please use `bool Extrude(this pb_Object pb, pb_Face[] faces, ExtrudeMethod method, float distance)`")]
|
||||
public static bool Extrude(this pb_Object pb, pb_Face[] faces, float extrudeDistance)
|
||||
{
|
||||
pb_Face[] array;
|
||||
return pb.Extrude(faces, extrudeDistance, true, out array);
|
||||
}
|
||||
|
||||
// Token: 0x06000005 RID: 5 RVA: 0x00002200 File Offset: 0x00000600
|
||||
[Obsolete("Please use `bool Extrude(this pb_Object pb, pb_Face[] faces, ExtrudeMethod method, float distance)`")]
|
||||
public static bool Extrude(this pb_Object pb, pb_Face[] faces, float extrudeDistance, bool extrudeAsGroup, out pb_Face[] appendedFaces)
|
||||
{
|
||||
return pb.Extrude(faces, (!extrudeAsGroup) ? ExtrudeMethod.IndividualFaces : ExtrudeMethod.VertexNormal, extrudeDistance, out appendedFaces);
|
||||
}
|
||||
|
||||
// Token: 0x06000006 RID: 6 RVA: 0x0000221C File Offset: 0x0000061C
|
||||
[Obsolete("Please use `bool Extrude(this pb_Object pb, pb_Face[] faces, ExtrudeMethod method, float distance)`")]
|
||||
public static bool Extrude(this pb_Object pb, pb_Face[] faces, ExtrudeMethod method, float extrudeDistance, out pb_Face[] appendedFaces)
|
||||
{
|
||||
appendedFaces = null;
|
||||
if (faces == null || faces.Length < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
pb_IntArray[] sharedIndices = pb.GetSharedIndices();
|
||||
Dictionary<int, int> dictionary = sharedIndices.ToDictionary();
|
||||
int vertexCount = pb.vertexCount;
|
||||
Vector3[] array = pb.vertices;
|
||||
bool flag = method != ExtrudeMethod.IndividualFaces;
|
||||
pb_Edge[][] array2;
|
||||
if (flag)
|
||||
{
|
||||
(array2 = new pb_Edge[1][])[0] = pbMeshUtils.GetPerimeterEdges(dictionary, faces).ToArray<pb_Edge>();
|
||||
}
|
||||
else
|
||||
{
|
||||
array2 = faces.Select((pb_Face x) => x.edges).ToArray<pb_Edge[]>();
|
||||
}
|
||||
pb_Edge[][] array3 = array2;
|
||||
if (array3 == null || array3.Length < 1 || (flag && array3[0].Length < 3))
|
||||
{
|
||||
Debug.LogWarning("No perimeter edges found. Try deselecting and reselecting this object and trying again.");
|
||||
return false;
|
||||
}
|
||||
pb_Face[][] array4 = new pb_Face[array3.Length][];
|
||||
int[][] array5 = new int[array3.Length][];
|
||||
for (int i = 0; i < array3.Length; i++)
|
||||
{
|
||||
int num = 0;
|
||||
array5[i] = new int[array3[i].Length * 2];
|
||||
array4[i] = new pb_Face[array3[i].Length];
|
||||
for (int j = 0; j < array3[i].Length; j++)
|
||||
{
|
||||
foreach (pb_Face pb_Face in faces)
|
||||
{
|
||||
if (pb_Face.edges.Contains(array3[i][j]))
|
||||
{
|
||||
array4[i][j] = pb_Face;
|
||||
break;
|
||||
}
|
||||
}
|
||||
array5[i][num++] = array3[i][j].x;
|
||||
array5[i][num++] = array3[i][j].y;
|
||||
}
|
||||
}
|
||||
List<pb_Edge>[] array6 = new List<pb_Edge>[array3.Length];
|
||||
Vector3[] normals = pb.msh.normals;
|
||||
Vector3[] array7 = new Vector3[vertexCount];
|
||||
List<Vector3[]> list = new List<Vector3[]>();
|
||||
List<Color[]> list2 = new List<Color[]>();
|
||||
List<Vector2[]> list3 = new List<Vector2[]>();
|
||||
List<pb_Face> list4 = new List<pb_Face>();
|
||||
List<int[]> list5 = new List<int[]>();
|
||||
for (int l = 0; l < array3.Length; l++)
|
||||
{
|
||||
array6[l] = new List<pb_Edge>();
|
||||
for (int m = 0; m < array3[l].Length; m++)
|
||||
{
|
||||
pb_Edge pb_Edge = array3[l][m];
|
||||
pb_Face pb_Face2 = array4[l][m];
|
||||
Vector3 vector = pb_Math.Normal(pb, pb_Face2);
|
||||
Vector3 vector2 = Vector3.zero;
|
||||
Vector3 vector3 = Vector3.zero;
|
||||
if (Mathf.Abs(extrudeDistance) > Mathf.Epsilon)
|
||||
{
|
||||
if (!flag)
|
||||
{
|
||||
vector2 = vector;
|
||||
vector3 = vector;
|
||||
}
|
||||
else
|
||||
{
|
||||
vector2 = pbMeshOps.Norm(sharedIndices[dictionary[pb_Edge.x]], array5[l], normals);
|
||||
vector3 = pbMeshOps.Norm(sharedIndices[dictionary[pb_Edge.y]], array5[l], normals);
|
||||
}
|
||||
}
|
||||
int num2 = dictionary[pb_Edge.x];
|
||||
int num3 = dictionary[pb_Edge.y];
|
||||
float num4 = extrudeDistance;
|
||||
float num5 = extrudeDistance;
|
||||
if (method == ExtrudeMethod.FaceNormal)
|
||||
{
|
||||
num4 = pb_Math.Secant(Vector3.Angle(vector, vector2) * 0.017453292f) * extrudeDistance;
|
||||
num5 = pb_Math.Secant(Vector3.Angle(vector, vector3) * 0.017453292f) * extrudeDistance;
|
||||
}
|
||||
array7[pb_Edge.x] = vector2.normalized * num4;
|
||||
array7[pb_Edge.y] = vector3.normalized * num5;
|
||||
list.Add(new Vector3[]
|
||||
{
|
||||
array[pb_Edge.x],
|
||||
array[pb_Edge.y],
|
||||
array[pb_Edge.x] + array7[pb_Edge.x],
|
||||
array[pb_Edge.y] + array7[pb_Edge.y]
|
||||
});
|
||||
list2.Add(new Color[]
|
||||
{
|
||||
pb.colors[pb_Edge.x],
|
||||
pb.colors[pb_Edge.y],
|
||||
pb.colors[pb_Edge.x],
|
||||
pb.colors[pb_Edge.y]
|
||||
});
|
||||
list3.Add(new Vector2[4]);
|
||||
list4.Add(new pb_Face(new int[] { 0, 1, 2, 1, 3, 2 }, pb_Face2.material, new pb_UV(pb_Face2.uv), pb_Face2.smoothingGroup, -1, -1, false));
|
||||
list5.Add(new int[] { num2, num3, -1, -1 });
|
||||
array6[l].Add(new pb_Edge(num2, -1));
|
||||
array6[l].Add(new pb_Edge(num3, -1));
|
||||
}
|
||||
}
|
||||
appendedFaces = pb.AppendFaces(list.ToArray(), list2.ToArray(), list3.ToArray(), list4.ToArray(), list5.ToArray());
|
||||
int n = 0;
|
||||
int num6 = 0;
|
||||
while (n < array6.Length)
|
||||
{
|
||||
for (int num7 = 0; num7 < array6[n].Count; num7 += 2)
|
||||
{
|
||||
array6[n][num7].y = appendedFaces[num6].indices[2];
|
||||
array6[n][num7 + 1].y = appendedFaces[num6++].indices[4];
|
||||
}
|
||||
n++;
|
||||
}
|
||||
pb_IntArray[] array8 = pb.sharedIndices;
|
||||
Dictionary<int, int> dictionary2 = array8.ToDictionary();
|
||||
for (int num8 = 0; num8 < array6.Length; num8++)
|
||||
{
|
||||
for (int num9 = 0; num9 < array6[num8].Count - 1; num9++)
|
||||
{
|
||||
int x2 = array6[num8][num9].x;
|
||||
for (int num10 = num9 + 1; num10 < array6[num8].Count; num10++)
|
||||
{
|
||||
if (array6[num8][num10].x == x2)
|
||||
{
|
||||
dictionary2[array6[num8][num9].y] = dictionary2[array6[num8][num10].y];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
array = pb.vertices;
|
||||
foreach (pb_Face pb_Face3 in faces)
|
||||
{
|
||||
pb_Face3.smoothingGroup = -1;
|
||||
pb_Face3.textureGroup = -1;
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
foreach (pb_Face pb_Face4 in faces)
|
||||
{
|
||||
int[] distinctIndices = pb_Face4.distinctIndices;
|
||||
foreach (int num14 in distinctIndices)
|
||||
{
|
||||
int num15 = array8.IndexOf(num14);
|
||||
for (int num16 = 0; num16 < array5.Length; num16++)
|
||||
{
|
||||
for (int num17 = 0; num17 < array6[num16].Count; num17++)
|
||||
{
|
||||
if (num15 == array6[num16][num17].x)
|
||||
{
|
||||
dictionary2[num14] = dictionary2[array6[num16][num17].y];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int num18 = 0; num18 < array4.Length; num18++)
|
||||
{
|
||||
int[] array10 = pb_Face.AllTrianglesDistinct(array4[num18]);
|
||||
for (int num19 = 0; num19 < array10.Length; num19++)
|
||||
{
|
||||
int num20 = array10[num19];
|
||||
int old_si_index = dictionary[num20];
|
||||
int num21 = array6[num18].FindIndex((pb_Edge x) => x.x == old_si_index);
|
||||
if (num21 >= 0)
|
||||
{
|
||||
int y = array6[num18][num21].y;
|
||||
if (dictionary2.ContainsKey(y))
|
||||
{
|
||||
dictionary2[num20] = dictionary2[y];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
array8 = dictionary2.ToSharedIndices();
|
||||
pb.SplitUVs(pb_Face.AllTriangles(faces));
|
||||
int[] array11 = pb_Face.AllTrianglesDistinct(faces);
|
||||
float num22 = extrudeDistance;
|
||||
foreach (pb_Face pb_Face5 in faces)
|
||||
{
|
||||
Vector3 vector4 = pb_Math.Normal(array[pb_Face5.indices[0]], array[pb_Face5.indices[1]], array[pb_Face5.indices[2]]);
|
||||
Vector3 vector5 = ((!flag) ? vector4 : Vector3.zero);
|
||||
foreach (int num25 in pb_Face5.distinctIndices)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
vector5 = pbMeshOps.Norm(sharedIndices[dictionary[num25]], array11, normals);
|
||||
if (method == ExtrudeMethod.FaceNormal)
|
||||
{
|
||||
num22 = pb_Math.Secant(Vector3.Angle(vector4, vector5) * 0.017453292f) * extrudeDistance;
|
||||
}
|
||||
}
|
||||
array[num25] += vector5.normalized * num22;
|
||||
}
|
||||
}
|
||||
pb.SetSharedIndices(array8);
|
||||
pb.SetVertices(array);
|
||||
List<pb_Face> list6 = new List<pb_Face>(appendedFaces);
|
||||
list6.AddRange(faces);
|
||||
HashSet<pb_Face> hashSet = new HashSet<pb_Face>(faces);
|
||||
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, list6, false, null);
|
||||
foreach (pb_WingedEdge pb_WingedEdge in wingedEdges)
|
||||
{
|
||||
if (hashSet.Contains(pb_WingedEdge.face))
|
||||
{
|
||||
hashSet.Remove(pb_WingedEdge.face);
|
||||
pb_WingedEdgeEnumerator enumerator2 = pb_WingedEdge.GetEnumerator();
|
||||
try
|
||||
{
|
||||
while (enumerator2.MoveNext())
|
||||
{
|
||||
pb_WingedEdge pb_WingedEdge2 = enumerator2.Current;
|
||||
pb_ConformNormals.ConformOppositeNormal(pb_WingedEdge2);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
IDisposable disposable;
|
||||
if ((disposable = enumerator2 as IDisposable) != null)
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Token: 0x06000007 RID: 7 RVA: 0x00002CBC File Offset: 0x000010BC
|
||||
private static Vector3 Norm(int[] shared, int[] all, Vector3[] norm)
|
||||
{
|
||||
Vector3 vector = Vector3.zero;
|
||||
int num = 0;
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
if (Array.IndexOf<int>(shared, all[i]) > -1)
|
||||
{
|
||||
vector += norm[all[i]];
|
||||
num++;
|
||||
}
|
||||
}
|
||||
return vector / (float)num;
|
||||
}
|
||||
|
||||
// Token: 0x06000008 RID: 8 RVA: 0x00002D18 File Offset: 0x00001118
|
||||
public static bool Extrude(this pb_Object pb, pb_Edge[] edges, float extrudeDistance, bool extrudeAsGroup, bool enableManifoldExtrude, out pb_Edge[] extrudedEdges)
|
||||
{
|
||||
pb_IntArray[] array = pb.sharedIndices;
|
||||
Dictionary<int, int> dictionary = array.ToDictionary();
|
||||
List<pb_Edge> list = new List<pb_Edge>();
|
||||
List<pb_Face> list2 = new List<pb_Face>();
|
||||
foreach (pb_Edge pb_Edge in edges)
|
||||
{
|
||||
int num = 0;
|
||||
pb_Face pb_Face = null;
|
||||
foreach (pb_Face pb_Face2 in pb.faces)
|
||||
{
|
||||
if (pb_Face2.edges.IndexOf(pb_Edge, dictionary) > -1)
|
||||
{
|
||||
pb_Face = pb_Face2;
|
||||
if (++num > 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (enableManifoldExtrude || num < 2)
|
||||
{
|
||||
list.Add(pb_Edge);
|
||||
list2.Add(pb_Face);
|
||||
}
|
||||
}
|
||||
if (list.Count < 1)
|
||||
{
|
||||
extrudedEdges = null;
|
||||
return false;
|
||||
}
|
||||
Vector3[] vertices = pb.vertices;
|
||||
Vector3[] normals = pb.msh.normals;
|
||||
int[] array2 = new int[list.Count * 2];
|
||||
int num2 = 0;
|
||||
for (int k = 0; k < list.Count; k++)
|
||||
{
|
||||
array2[num2++] = list[k].x;
|
||||
array2[num2++] = list[k].y;
|
||||
}
|
||||
List<pb_Edge> list3 = new List<pb_Edge>();
|
||||
List<pb_Edge> list4 = new List<pb_Edge>();
|
||||
for (int l = 0; l < list.Count; l++)
|
||||
{
|
||||
pb_Edge pb_Edge2 = list[l];
|
||||
pb_Face pb_Face3 = list2[l];
|
||||
Vector3 vector = ((!extrudeAsGroup) ? pb_Math.Normal(pb, pb_Face3) : pbMeshOps.Norm(array[dictionary[pb_Edge2.x]], array2, normals));
|
||||
Vector3 vector2 = ((!extrudeAsGroup) ? pb_Math.Normal(pb, pb_Face3) : pbMeshOps.Norm(array[dictionary[pb_Edge2.y]], array2, normals));
|
||||
int num3 = dictionary[pb_Edge2.x];
|
||||
int num4 = dictionary[pb_Edge2.y];
|
||||
pb_Face pb_Face4 = pb.AppendFace(new Vector3[]
|
||||
{
|
||||
vertices[pb_Edge2.x],
|
||||
vertices[pb_Edge2.y],
|
||||
vertices[pb_Edge2.x] + vector.normalized * extrudeDistance,
|
||||
vertices[pb_Edge2.y] + vector2.normalized * extrudeDistance
|
||||
}, new Color[]
|
||||
{
|
||||
pb.colors[pb_Edge2.x],
|
||||
pb.colors[pb_Edge2.y],
|
||||
pb.colors[pb_Edge2.x],
|
||||
pb.colors[pb_Edge2.y]
|
||||
}, new Vector2[4], new pb_Face(new int[] { 2, 1, 0, 2, 3, 1 }, pb_Face3.material, new pb_UV(), 0, -1, -1, false), new int[] { num3, num4, -1, -1 });
|
||||
list4.Add(new pb_Edge(pb_Face4.indices[3], pb_Face4.indices[4]));
|
||||
list3.Add(new pb_Edge(num3, pb_Face4.indices[3]));
|
||||
list3.Add(new pb_Edge(num4, pb_Face4.indices[4]));
|
||||
}
|
||||
array = pb.sharedIndices;
|
||||
if (extrudeAsGroup)
|
||||
{
|
||||
for (int m = 0; m < list3.Count; m++)
|
||||
{
|
||||
int x = list3[m].x;
|
||||
for (int n = 0; n < list3.Count; n++)
|
||||
{
|
||||
if (n != m)
|
||||
{
|
||||
if (list3[n].x == x)
|
||||
{
|
||||
pb_IntArrayUtility.MergeSharedIndices(ref array, list3[n].y, list3[m].y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pb.SetSharedIndices(array);
|
||||
foreach (pb_Face pb_Face5 in pb.faces)
|
||||
{
|
||||
pb_Face5.RebuildCaches();
|
||||
}
|
||||
extrudedEdges = list4.ToArray();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Token: 0x06000009 RID: 9 RVA: 0x000031CC File Offset: 0x000015CC
|
||||
public static List<pb_Face> DetachFaces(this pb_Object pb, IEnumerable<pb_Face> faces)
|
||||
{
|
||||
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
|
||||
int num = pb.sharedIndices.Length;
|
||||
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
||||
List<pb_FaceRebuildData> list2 = new List<pb_FaceRebuildData>();
|
||||
foreach (pb_Face pb_Face in faces)
|
||||
{
|
||||
pb_FaceRebuildData pb_FaceRebuildData = new pb_FaceRebuildData();
|
||||
pb_FaceRebuildData.vertices = new List<pb_Vertex>();
|
||||
pb_FaceRebuildData.sharedIndices = new List<int>();
|
||||
pb_FaceRebuildData.face = new pb_Face(pb_Face);
|
||||
Dictionary<int, int> dictionary2 = new Dictionary<int, int>();
|
||||
int[] array = new int[pb_Face.indices.Length];
|
||||
for (int i = 0; i < pb_Face.indices.Length; i++)
|
||||
{
|
||||
int count;
|
||||
if (dictionary2.TryGetValue(pb_Face.indices[i], out count))
|
||||
{
|
||||
array[i] = count;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = pb_FaceRebuildData.vertices.Count;
|
||||
array[i] = count;
|
||||
dictionary2.Add(pb_Face.indices[i], count);
|
||||
pb_FaceRebuildData.vertices.Add(list[pb_Face.indices[i]]);
|
||||
pb_FaceRebuildData.sharedIndices.Add(dictionary[pb_Face.indices[i]] + num);
|
||||
}
|
||||
}
|
||||
pb_FaceRebuildData.face.SetIndices(array.ToArray<int>());
|
||||
list2.Add(pb_FaceRebuildData);
|
||||
}
|
||||
pb_FaceRebuildData.Apply(list2, pb, list, null, dictionary, null);
|
||||
pb.DeleteFaces(faces);
|
||||
pb.ToMesh();
|
||||
return list2.Select((pb_FaceRebuildData x) => x.face).ToList<pb_Face>();
|
||||
}
|
||||
|
||||
// Token: 0x0600000A RID: 10 RVA: 0x00003398 File Offset: 0x00001798
|
||||
public static bool Bridge(this pb_Object pb, pb_Edge a, pb_Edge b, bool enforcePerimiterEdgesOnly = false)
|
||||
{
|
||||
pb_IntArray[] sharedIndices = pb.GetSharedIndices();
|
||||
Dictionary<int, int> dictionary = sharedIndices.ToDictionary();
|
||||
if (enforcePerimiterEdgesOnly && (pbMeshUtils.GetNeighborFaces(pb, a, null).Count > 1 || pbMeshUtils.GetNeighborFaces(pb, b, null).Count > 1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
foreach (pb_Face pb_Face in pb.faces)
|
||||
{
|
||||
if (pb_Face.edges.IndexOf(a, dictionary) >= 0 && pb_Face.edges.IndexOf(b, dictionary) >= 0)
|
||||
{
|
||||
Debug.LogWarning("Face already exists between these two edges!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Vector3[] vertices = pb.vertices;
|
||||
pb_UV pb_UV = new pb_UV();
|
||||
Material material = pb_Constant.DefaultMaterial;
|
||||
pb_Tuple<pb_Face, pb_Edge> pb_Tuple = null;
|
||||
if (!pb_Edge.ValidateEdge(pb, a, out pb_Tuple))
|
||||
{
|
||||
pb_Edge.ValidateEdge(pb, b, out pb_Tuple);
|
||||
}
|
||||
if (pb_Tuple != null)
|
||||
{
|
||||
pb_UV = new pb_UV(pb_Tuple.Item1.uv);
|
||||
material = pb_Tuple.Item1.material;
|
||||
}
|
||||
Vector3[] array;
|
||||
Color[] array2;
|
||||
int[] array3;
|
||||
if (a.Contains(b.x, sharedIndices) || a.Contains(b.y, sharedIndices))
|
||||
{
|
||||
array = new Vector3[3];
|
||||
array2 = new Color[3];
|
||||
array3 = new int[3];
|
||||
bool flag = Array.IndexOf<int>(sharedIndices[sharedIndices.IndexOf(a.x)], b.x) > -1;
|
||||
bool flag2 = Array.IndexOf<int>(sharedIndices[sharedIndices.IndexOf(a.x)], b.y) > -1;
|
||||
bool flag3 = Array.IndexOf<int>(sharedIndices[sharedIndices.IndexOf(a.y)], b.x) > -1;
|
||||
bool flag4 = Array.IndexOf<int>(sharedIndices[sharedIndices.IndexOf(a.y)], b.y) > -1;
|
||||
if (flag)
|
||||
{
|
||||
array[0] = vertices[a.x];
|
||||
array2[0] = pb.colors[a.x];
|
||||
array3[0] = sharedIndices.IndexOf(a.x);
|
||||
array[1] = vertices[a.y];
|
||||
array2[1] = pb.colors[a.y];
|
||||
array3[1] = sharedIndices.IndexOf(a.y);
|
||||
array[2] = vertices[b.y];
|
||||
array2[2] = pb.colors[b.y];
|
||||
array3[2] = sharedIndices.IndexOf(b.y);
|
||||
}
|
||||
else if (flag2)
|
||||
{
|
||||
array[0] = vertices[a.x];
|
||||
array2[0] = pb.colors[a.x];
|
||||
array3[0] = sharedIndices.IndexOf(a.x);
|
||||
array[1] = vertices[a.y];
|
||||
array2[1] = pb.colors[a.y];
|
||||
array3[1] = sharedIndices.IndexOf(a.y);
|
||||
array[2] = vertices[b.x];
|
||||
array2[2] = pb.colors[b.x];
|
||||
array3[2] = sharedIndices.IndexOf(b.x);
|
||||
}
|
||||
else if (flag3)
|
||||
{
|
||||
array[0] = vertices[a.y];
|
||||
array2[0] = pb.colors[a.y];
|
||||
array3[0] = sharedIndices.IndexOf(a.y);
|
||||
array[1] = vertices[a.x];
|
||||
array2[1] = pb.colors[a.x];
|
||||
array3[1] = sharedIndices.IndexOf(a.x);
|
||||
array[2] = vertices[b.y];
|
||||
array2[2] = pb.colors[b.y];
|
||||
array3[2] = sharedIndices.IndexOf(b.y);
|
||||
}
|
||||
else if (flag4)
|
||||
{
|
||||
array[0] = vertices[a.y];
|
||||
array2[0] = pb.colors[a.y];
|
||||
array3[0] = sharedIndices.IndexOf(a.y);
|
||||
array[1] = vertices[a.x];
|
||||
array2[1] = pb.colors[a.x];
|
||||
array3[1] = sharedIndices.IndexOf(a.x);
|
||||
array[2] = vertices[b.x];
|
||||
array2[2] = pb.colors[b.x];
|
||||
array3[2] = sharedIndices.IndexOf(b.x);
|
||||
}
|
||||
Vector3[] array4 = array;
|
||||
Color[] array5 = array2;
|
||||
Vector2[] array6 = new Vector2[array.Length];
|
||||
int[] array8;
|
||||
if (flag || flag2)
|
||||
{
|
||||
int[] array7 = new int[3];
|
||||
array7[0] = 2;
|
||||
array8 = array7;
|
||||
array7[1] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int[] array9 = new int[3];
|
||||
array9[1] = 1;
|
||||
array8 = array9;
|
||||
array9[2] = 2;
|
||||
}
|
||||
pb.AppendFace(array4, array5, array6, new pb_Face(array8, material, pb_UV, 0, -1, -1, false), array3);
|
||||
return true;
|
||||
}
|
||||
array = new Vector3[4];
|
||||
array2 = new Color[4];
|
||||
array3 = new int[4];
|
||||
array[0] = vertices[a.x];
|
||||
array2[0] = pb.colors[a.x];
|
||||
array3[0] = sharedIndices.IndexOf(a.x);
|
||||
array[1] = vertices[a.y];
|
||||
array2[1] = pb.colors[a.y];
|
||||
array3[1] = sharedIndices.IndexOf(a.y);
|
||||
Vector3 normalized = Vector3.Cross(vertices[b.x] - vertices[a.x], vertices[a.y] - vertices[a.x]).normalized;
|
||||
Vector2[] array10 = pb_Projection.PlanarProject(new Vector3[]
|
||||
{
|
||||
vertices[a.x],
|
||||
vertices[a.y],
|
||||
vertices[b.x],
|
||||
vertices[b.y]
|
||||
}, normalized);
|
||||
Vector2 zero = Vector2.zero;
|
||||
if (!pb_Math.GetLineSegmentIntersect(array10[0], array10[2], array10[1], array10[3], ref zero))
|
||||
{
|
||||
array[2] = vertices[b.x];
|
||||
array2[2] = pb.colors[b.x];
|
||||
array3[2] = sharedIndices.IndexOf(b.x);
|
||||
array[3] = vertices[b.y];
|
||||
array2[3] = pb.colors[b.y];
|
||||
array3[3] = sharedIndices.IndexOf(b.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
array[2] = vertices[b.y];
|
||||
array2[2] = pb.colors[b.y];
|
||||
array3[2] = sharedIndices.IndexOf(b.y);
|
||||
array[3] = vertices[b.x];
|
||||
array2[3] = pb.colors[b.x];
|
||||
array3[3] = sharedIndices.IndexOf(b.x);
|
||||
}
|
||||
pb.AppendFace(array, array2, new Vector2[array.Length], new pb_Face(new int[] { 2, 1, 0, 2, 3, 1 }, material, pb_UV, 0, -1, -1, false), array3);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Token: 0x0600000B RID: 11 RVA: 0x00003D24 File Offset: 0x00002124
|
||||
public static bool CombineObjects(pb_Object[] pbs, out pb_Object combined)
|
||||
{
|
||||
combined = null;
|
||||
if (pbs.Length < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
List<Vector3> list = new List<Vector3>();
|
||||
List<Vector2> list2 = new List<Vector2>();
|
||||
List<Color> list3 = new List<Color>();
|
||||
List<pb_Face> list4 = new List<pb_Face>();
|
||||
List<pb_IntArray> list5 = new List<pb_IntArray>();
|
||||
List<pb_IntArray> list6 = new List<pb_IntArray>();
|
||||
foreach (pb_Object pb_Object in pbs)
|
||||
{
|
||||
int count = list.Count;
|
||||
list.AddRange(pb_Object.VerticesInWorldSpace());
|
||||
list2.AddRange(pb_Object.uv);
|
||||
list3.AddRange(pb_Object.colors);
|
||||
pb_Face[] array = new pb_Face[pb_Object.faces.Length];
|
||||
for (int j = 0; j < array.Length; j++)
|
||||
{
|
||||
array[j] = new pb_Face(pb_Object.faces[j]);
|
||||
array[j].manualUV = true;
|
||||
array[j].ShiftIndices(count);
|
||||
array[j].RebuildCaches();
|
||||
}
|
||||
list4.AddRange(array);
|
||||
pb_IntArray[] sharedIndices = pb_Object.GetSharedIndices();
|
||||
for (int k = 0; k < sharedIndices.Length; k++)
|
||||
{
|
||||
for (int l = 0; l < sharedIndices[k].Length; l++)
|
||||
{
|
||||
pb_IntArray pb_IntArray;
|
||||
int num;
|
||||
(pb_IntArray = sharedIndices[k])[num = l] = pb_IntArray[num] + count;
|
||||
}
|
||||
}
|
||||
list5.AddRange(sharedIndices);
|
||||
pb_IntArray[] sharedIndicesUV = pb_Object.GetSharedIndicesUV();
|
||||
for (int m = 0; m < sharedIndicesUV.Length; m++)
|
||||
{
|
||||
for (int n = 0; n < sharedIndicesUV[m].Length; n++)
|
||||
{
|
||||
pb_IntArray pb_IntArray;
|
||||
int num2;
|
||||
(pb_IntArray = sharedIndicesUV[m])[num2 = n] = pb_IntArray[num2] + count;
|
||||
}
|
||||
}
|
||||
list6.AddRange(sharedIndicesUV);
|
||||
}
|
||||
GameObject gameObject = global::UnityEngine.Object.Instantiate<GameObject>(pbs[0].gameObject);
|
||||
gameObject.transform.position = Vector3.zero;
|
||||
gameObject.transform.localRotation = Quaternion.identity;
|
||||
gameObject.transform.localScale = Vector3.one;
|
||||
IEnumerator enumerator = gameObject.transform.GetEnumerator();
|
||||
try
|
||||
{
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
object obj = enumerator.Current;
|
||||
Transform transform = (Transform)obj;
|
||||
global::UnityEngine.Object.DestroyImmediate(transform.gameObject);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
IDisposable disposable;
|
||||
if ((disposable = enumerator as IDisposable) != null)
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
}
|
||||
if (gameObject.GetComponent<pb_Object>())
|
||||
{
|
||||
global::UnityEngine.Object.DestroyImmediate(gameObject.GetComponent<pb_Object>());
|
||||
}
|
||||
if (gameObject.GetComponent<pb_Entity>())
|
||||
{
|
||||
global::UnityEngine.Object.DestroyImmediate(gameObject.GetComponent<pb_Entity>());
|
||||
}
|
||||
combined = gameObject.AddComponent<pb_Object>();
|
||||
combined.SetVertices(list.ToArray());
|
||||
combined.SetUV(list2.ToArray());
|
||||
combined.SetColors(list3.ToArray());
|
||||
combined.SetFaces(list4.ToArray());
|
||||
combined.SetSharedIndices(list5.ToArray() ?? pb_IntArrayUtility.ExtractSharedIndices(list.ToArray()));
|
||||
combined.SetSharedIndicesUV(list6.ToArray() ?? new pb_IntArray[0]);
|
||||
combined.ToMesh();
|
||||
combined.GetComponent<pb_Entity>().SetEntity(pbs[0].GetComponent<pb_Entity>().entityType);
|
||||
combined.CenterPivot(pbs[0].transform.position);
|
||||
combined.Refresh(RefreshMask.All);
|
||||
foreach (pb_Object pb_Object2 in pbs)
|
||||
{
|
||||
pb_Object2.Verify();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Token: 0x0600000C RID: 12 RVA: 0x000040B4 File Offset: 0x000024B4
|
||||
public static pb_Object CreatePbObjectWithTransform(Transform t, bool preserveFaces)
|
||||
{
|
||||
Mesh sharedMesh = t.GetComponent<MeshFilter>().sharedMesh;
|
||||
Vector3[] meshAttribute = pb_MeshUtility.GetMeshAttribute<Vector3[]>(t.gameObject, (Mesh x) => x.vertices);
|
||||
Color[] meshAttribute2 = pb_MeshUtility.GetMeshAttribute<Color[]>(t.gameObject, (Mesh x) => x.colors);
|
||||
Vector2[] meshAttribute3 = pb_MeshUtility.GetMeshAttribute<Vector2[]>(t.gameObject, (Mesh x) => x.uv);
|
||||
List<Vector3> list = ((!preserveFaces) ? new List<Vector3>() : new List<Vector3>(sharedMesh.vertices));
|
||||
List<Color> list2 = ((!preserveFaces) ? new List<Color>() : new List<Color>(sharedMesh.colors));
|
||||
List<Vector2> list3 = ((!preserveFaces) ? new List<Vector2>() : new List<Vector2>(sharedMesh.uv));
|
||||
List<pb_Face> list4 = new List<pb_Face>();
|
||||
for (int i = 0; i < sharedMesh.subMeshCount; i++)
|
||||
{
|
||||
int[] triangles = sharedMesh.GetTriangles(i);
|
||||
for (int j = 0; j < triangles.Length; j += 3)
|
||||
{
|
||||
int num = -1;
|
||||
if (preserveFaces)
|
||||
{
|
||||
for (int k = 0; k < list4.Count; k++)
|
||||
{
|
||||
if (list4[k].distinctIndices.Contains(triangles[j]) || list4[k].distinctIndices.Contains(triangles[j + 1]) || list4[k].distinctIndices.Contains(triangles[j + 2]))
|
||||
{
|
||||
num = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num > -1 && preserveFaces)
|
||||
{
|
||||
int num2 = list4[num].indices.Length;
|
||||
int[] array = new int[num2 + 3];
|
||||
Array.Copy(list4[num].indices, 0, array, 0, num2);
|
||||
array[num2] = triangles[j];
|
||||
array[num2 + 1] = triangles[j + 1];
|
||||
array[num2 + 2] = triangles[j + 2];
|
||||
list4[num].SetIndices(array);
|
||||
list4[num].RebuildCaches();
|
||||
}
|
||||
else
|
||||
{
|
||||
int[] array2;
|
||||
if (preserveFaces)
|
||||
{
|
||||
array2 = new int[]
|
||||
{
|
||||
triangles[j],
|
||||
triangles[j + 1],
|
||||
triangles[j + 2]
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(meshAttribute[triangles[j]]);
|
||||
list.Add(meshAttribute[triangles[j + 1]]);
|
||||
list.Add(meshAttribute[triangles[j + 2]]);
|
||||
list2.Add((meshAttribute2 == null) ? Color.white : meshAttribute2[triangles[j]]);
|
||||
list2.Add((meshAttribute2 == null) ? Color.white : meshAttribute2[triangles[j + 1]]);
|
||||
list2.Add((meshAttribute2 == null) ? Color.white : meshAttribute2[triangles[j + 2]]);
|
||||
list3.Add(meshAttribute3[triangles[j]]);
|
||||
list3.Add(meshAttribute3[triangles[j + 1]]);
|
||||
list3.Add(meshAttribute3[triangles[j + 2]]);
|
||||
array2 = new int[]
|
||||
{
|
||||
j,
|
||||
j + 1,
|
||||
j + 2
|
||||
};
|
||||
}
|
||||
list4.Add(new pb_Face(array2, t.GetComponent<MeshRenderer>().sharedMaterials[i], new pb_UV(), 0, -1, -1, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
GameObject gameObject = global::UnityEngine.Object.Instantiate<GameObject>(t.gameObject);
|
||||
gameObject.GetComponent<MeshFilter>().sharedMesh = null;
|
||||
pb_Object pb_Object = gameObject.AddComponent<pb_Object>();
|
||||
pb_Object.GeometryWithVerticesFaces(list.ToArray(), list4.ToArray());
|
||||
pb_Object.SetColors(list2.ToArray());
|
||||
pb_Object.SetUV(list3.ToArray());
|
||||
pb_Object.gameObject.name = t.name;
|
||||
gameObject.transform.position = t.position;
|
||||
gameObject.transform.localRotation = t.localRotation;
|
||||
gameObject.transform.localScale = t.localScale;
|
||||
pb_Object.CenterPivot(null);
|
||||
return pb_Object;
|
||||
}
|
||||
|
||||
// Token: 0x0600000D RID: 13 RVA: 0x0000451C File Offset: 0x0000291C
|
||||
public static bool ResetPbObjectWithMeshFilter(pb_Object pb, bool preserveFaces)
|
||||
{
|
||||
MeshFilter component = pb.gameObject.GetComponent<MeshFilter>();
|
||||
if (component == null || component.sharedMesh == null)
|
||||
{
|
||||
pb_Log.Error(pb.name + " does not have a mesh or Mesh Filter component.");
|
||||
return false;
|
||||
}
|
||||
Mesh sharedMesh = component.sharedMesh;
|
||||
int vertexCount = sharedMesh.vertexCount;
|
||||
Vector3[] meshAttribute = pb_MeshUtility.GetMeshAttribute<Vector3[]>(pb.gameObject, (Mesh x) => x.vertices);
|
||||
Color[] meshAttribute2 = pb_MeshUtility.GetMeshAttribute<Color[]>(pb.gameObject, (Mesh x) => x.colors);
|
||||
Vector2[] meshAttribute3 = pb_MeshUtility.GetMeshAttribute<Vector2[]>(pb.gameObject, (Mesh x) => x.uv);
|
||||
List<Vector3> list = ((!preserveFaces) ? new List<Vector3>() : new List<Vector3>(sharedMesh.vertices));
|
||||
List<Color> list2 = ((!preserveFaces) ? new List<Color>() : new List<Color>(sharedMesh.colors));
|
||||
List<Vector2> list3 = ((!preserveFaces) ? new List<Vector2>() : new List<Vector2>(sharedMesh.uv));
|
||||
List<pb_Face> list4 = new List<pb_Face>();
|
||||
MeshRenderer meshRenderer = pb.gameObject.GetComponent<MeshRenderer>();
|
||||
if (meshRenderer == null)
|
||||
{
|
||||
meshRenderer = pb.gameObject.AddComponent<MeshRenderer>();
|
||||
}
|
||||
Material[] sharedMaterials = meshRenderer.sharedMaterials;
|
||||
int num = sharedMaterials.Length;
|
||||
for (int i = 0; i < sharedMesh.subMeshCount; i++)
|
||||
{
|
||||
int[] triangles = sharedMesh.GetTriangles(i);
|
||||
for (int j = 0; j < triangles.Length; j += 3)
|
||||
{
|
||||
int num2 = -1;
|
||||
if (preserveFaces)
|
||||
{
|
||||
for (int k = 0; k < list4.Count; k++)
|
||||
{
|
||||
if (list4[k].distinctIndices.Contains(triangles[j]) || list4[k].distinctIndices.Contains(triangles[j + 1]) || list4[k].distinctIndices.Contains(triangles[j + 2]))
|
||||
{
|
||||
num2 = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num2 > -1 && preserveFaces)
|
||||
{
|
||||
int num3 = list4[num2].indices.Length;
|
||||
int[] array = new int[num3 + 3];
|
||||
Array.Copy(list4[num2].indices, 0, array, 0, num3);
|
||||
array[num3] = triangles[j];
|
||||
array[num3 + 1] = triangles[j + 1];
|
||||
array[num3 + 2] = triangles[j + 2];
|
||||
list4[num2].SetIndices(array);
|
||||
list4[num2].RebuildCaches();
|
||||
}
|
||||
else
|
||||
{
|
||||
int[] array2;
|
||||
if (preserveFaces)
|
||||
{
|
||||
array2 = new int[]
|
||||
{
|
||||
triangles[j],
|
||||
triangles[j + 1],
|
||||
triangles[j + 2]
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(meshAttribute[triangles[j]]);
|
||||
list.Add(meshAttribute[triangles[j + 1]]);
|
||||
list.Add(meshAttribute[triangles[j + 2]]);
|
||||
list2.Add((meshAttribute2 == null || meshAttribute2.Length != vertexCount) ? Color.white : meshAttribute2[triangles[j]]);
|
||||
list2.Add((meshAttribute2 == null || meshAttribute2.Length != vertexCount) ? Color.white : meshAttribute2[triangles[j + 1]]);
|
||||
list2.Add((meshAttribute2 == null || meshAttribute2.Length != vertexCount) ? Color.white : meshAttribute2[triangles[j + 2]]);
|
||||
list3.Add(meshAttribute3[triangles[j]]);
|
||||
list3.Add(meshAttribute3[triangles[j + 1]]);
|
||||
list3.Add(meshAttribute3[triangles[j + 2]]);
|
||||
array2 = new int[]
|
||||
{
|
||||
j,
|
||||
j + 1,
|
||||
j + 2
|
||||
};
|
||||
}
|
||||
list4.Add(new pb_Face(array2, sharedMaterials[(i < num) ? i : (num - 1)], new pb_UV(), 0, -1, -1, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
pb.SetVertices(list.ToArray());
|
||||
pb.SetUV(list3.ToArray());
|
||||
pb.SetFaces(list4.ToArray());
|
||||
pb.SetSharedIndices(pb_IntArrayUtility.ExtractSharedIndices(list.ToArray()));
|
||||
pb.SetColors(list2.ToArray());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,570 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ProBuilder2.Common;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x02000004 RID: 4
|
||||
public static class pbTriangleOps
|
||||
{
|
||||
// Token: 0x06000033 RID: 51 RVA: 0x00005D2C File Offset: 0x0000412C
|
||||
public static void ReverseWindingOrder(this pb_Object pb, pb_Face[] faces)
|
||||
{
|
||||
for (int i = 0; i < faces.Length; i++)
|
||||
{
|
||||
faces[i].ReverseIndices();
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x06000034 RID: 52 RVA: 0x00005D58 File Offset: 0x00004158
|
||||
public static WindingOrder GetWindingOrder(this pb_Object pb, pb_Face face)
|
||||
{
|
||||
Vector2[] array = pb_Projection.PlanarProject(pb, face);
|
||||
return pbTriangleOps.GetWindingOrder(array);
|
||||
}
|
||||
|
||||
// Token: 0x06000035 RID: 53 RVA: 0x00005D74 File Offset: 0x00004174
|
||||
public static WindingOrder GetWindingOrder(IList<pb_Vertex> vertices, IList<int> indices)
|
||||
{
|
||||
Vector2[] array = pb_Projection.PlanarProject(vertices, indices);
|
||||
return pbTriangleOps.GetWindingOrder(array);
|
||||
}
|
||||
|
||||
// Token: 0x06000036 RID: 54 RVA: 0x00005D90 File Offset: 0x00004190
|
||||
public static WindingOrder GetWindingOrder(IList<Vector2> points)
|
||||
{
|
||||
float num = 0f;
|
||||
int count = points.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Vector2 vector = points[i];
|
||||
Vector2 vector2 = ((i >= count - 1) ? points[0] : points[i + 1]);
|
||||
num += (vector2.x - vector.x) * (vector2.y + vector.y);
|
||||
}
|
||||
return (num != 0f) ? ((num <= 0f) ? WindingOrder.CounterClockwise : WindingOrder.Clockwise) : WindingOrder.Unknown;
|
||||
}
|
||||
|
||||
// Token: 0x06000037 RID: 55 RVA: 0x00005E2C File Offset: 0x0000422C
|
||||
public static bool FlipEdge(this pb_Object pb, pb_Face face)
|
||||
{
|
||||
int[] indices = face.indices;
|
||||
if (indices.Length != 6)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int[] array = pbUtil.FilledArray<int>(1, indices.Length);
|
||||
for (int i = 0; i < indices.Length - 1; i++)
|
||||
{
|
||||
for (int j = i + 1; j < indices.Length; j++)
|
||||
{
|
||||
if (indices[i] == indices[j])
|
||||
{
|
||||
array[i]++;
|
||||
array[j]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (array[0] + array[1] + array[2] != 5 || array[3] + array[4] + array[5] != 5)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int num = indices[(array[0] != 1) ? ((array[1] != 1) ? 2 : 1) : 0];
|
||||
int num2 = indices[(array[3] != 1) ? ((array[4] != 1) ? 5 : 4) : 3];
|
||||
int num3 = -1;
|
||||
if (array[0] == 2)
|
||||
{
|
||||
num3 = indices[0];
|
||||
indices[0] = num2;
|
||||
}
|
||||
else if (array[1] == 2)
|
||||
{
|
||||
num3 = indices[1];
|
||||
indices[1] = num2;
|
||||
}
|
||||
else if (array[2] == 2)
|
||||
{
|
||||
num3 = indices[2];
|
||||
indices[2] = num2;
|
||||
}
|
||||
if (array[3] == 2 && indices[3] != num3)
|
||||
{
|
||||
indices[3] = num;
|
||||
}
|
||||
else if (array[4] == 2 && indices[4] != num3)
|
||||
{
|
||||
indices[4] = num;
|
||||
}
|
||||
else if (array[5] == 2 && indices[5] != num3)
|
||||
{
|
||||
indices[5] = num;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Token: 0x06000038 RID: 56 RVA: 0x00005FA8 File Offset: 0x000043A8
|
||||
public static bool RemoveDegenerateTriangles(this pb_Object pb, out int[] removed)
|
||||
{
|
||||
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
||||
Dictionary<int, int> dictionary2 = ((pb.sharedIndicesUV == null) ? new Dictionary<int, int>() : pb.sharedIndicesUV.ToDictionary());
|
||||
Vector3[] vertices = pb.vertices;
|
||||
Dictionary<int, int> dictionary3 = new Dictionary<int, int>();
|
||||
Dictionary<int, int> dictionary4 = new Dictionary<int, int>();
|
||||
List<pb_Face> list = new List<pb_Face>();
|
||||
foreach (pb_Face pb_Face in pb.faces)
|
||||
{
|
||||
List<int> list2 = new List<int>();
|
||||
int[] indices = pb_Face.indices;
|
||||
for (int j = 0; j < indices.Length; j += 3)
|
||||
{
|
||||
float num = pb_Math.TriangleArea(vertices[indices[j]], vertices[indices[j + 1]], vertices[indices[j + 2]]);
|
||||
if (num > Mathf.Epsilon)
|
||||
{
|
||||
int num2 = dictionary[indices[j]];
|
||||
int num3 = dictionary[indices[j + 1]];
|
||||
int num4 = dictionary[indices[j + 2]];
|
||||
if (num2 != num3 && num2 != num4 && num3 != num4)
|
||||
{
|
||||
list2.Add(indices[j]);
|
||||
list2.Add(indices[j + 1]);
|
||||
list2.Add(indices[j + 2]);
|
||||
if (!dictionary3.ContainsKey(indices[j]))
|
||||
{
|
||||
dictionary3.Add(indices[j], num2);
|
||||
}
|
||||
if (!dictionary3.ContainsKey(indices[j + 1]))
|
||||
{
|
||||
dictionary3.Add(indices[j + 1], num3);
|
||||
}
|
||||
if (!dictionary3.ContainsKey(indices[j + 2]))
|
||||
{
|
||||
dictionary3.Add(indices[j + 2], num4);
|
||||
}
|
||||
if (dictionary2.ContainsKey(indices[j]) && !dictionary4.ContainsKey(indices[j]))
|
||||
{
|
||||
dictionary4.Add(indices[j], dictionary2[indices[j]]);
|
||||
}
|
||||
if (dictionary2.ContainsKey(indices[j + 1]) && !dictionary4.ContainsKey(indices[j + 1]))
|
||||
{
|
||||
dictionary4.Add(indices[j + 1], dictionary2[indices[j + 1]]);
|
||||
}
|
||||
if (dictionary2.ContainsKey(indices[j + 2]) && !dictionary4.ContainsKey(indices[j + 2]))
|
||||
{
|
||||
dictionary4.Add(indices[j + 2], dictionary2[indices[j + 2]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (list2.Count > 0)
|
||||
{
|
||||
pb_Face.SetIndices(list2.ToArray());
|
||||
pb_Face.RebuildCaches();
|
||||
list.Add(pb_Face);
|
||||
}
|
||||
}
|
||||
pb.SetFaces(list.ToArray());
|
||||
pb.SetSharedIndices(dictionary3);
|
||||
pb.SetSharedIndicesUV(dictionary4);
|
||||
removed = pb.RemoveUnusedVertices();
|
||||
return removed.Length > 0;
|
||||
}
|
||||
|
||||
// Token: 0x06000039 RID: 57 RVA: 0x00006270 File Offset: 0x00004670
|
||||
public static pb_Face MergeFaces(this pb_Object pb, pb_Face[] faces)
|
||||
{
|
||||
List<int> list = new List<int>(faces[0].indices);
|
||||
for (int i = 1; i < faces.Length; i++)
|
||||
{
|
||||
list.AddRange(faces[i].indices);
|
||||
}
|
||||
pb_Face pb_Face = new pb_Face(list.ToArray(), faces[0].material, faces[0].uv, faces[0].smoothingGroup, faces[0].textureGroup, faces[0].elementGroup, faces[0].manualUV);
|
||||
pb_Face[] array = new pb_Face[pb.faces.Length - faces.Length + 1];
|
||||
int num = 0;
|
||||
foreach (pb_Face pb_Face2 in pb.faces)
|
||||
{
|
||||
if (Array.IndexOf<pb_Face>(faces, pb_Face2) < 0)
|
||||
{
|
||||
array[num++] = pb_Face2;
|
||||
}
|
||||
}
|
||||
array[num] = pb_Face;
|
||||
pb.SetFaces(array);
|
||||
Dictionary<int, int> dictionary = new Dictionary<int, int>();
|
||||
for (int k = 0; k < pb_Face.indices.Length; k++)
|
||||
{
|
||||
int num2 = pb.sharedIndices.IndexOf(pb_Face.indices[k]);
|
||||
if (dictionary.ContainsKey(num2))
|
||||
{
|
||||
pb_Face.indices[k] = dictionary[num2];
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary.Add(num2, pb_Face.indices[k]);
|
||||
}
|
||||
}
|
||||
pb.RemoveUnusedVertices();
|
||||
return pb_Face;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ProBuilder2.Common;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x02000005 RID: 5
|
||||
public static class pbUVOps
|
||||
{
|
||||
// Token: 0x0600003A RID: 58 RVA: 0x000063C8 File Offset: 0x000047C8
|
||||
public static bool SewUVs(this pb_Object pb, int[] indices, float delta)
|
||||
{
|
||||
int[] array = new int[indices.Length];
|
||||
Vector2[] array2 = pb.uv;
|
||||
if (array2 == null || array2.Length != pb.vertexCount)
|
||||
{
|
||||
array2 = new Vector2[pb.vertexCount];
|
||||
}
|
||||
for (int i = 0; i < indices.Length; i++)
|
||||
{
|
||||
array[i] = -(i + 1);
|
||||
}
|
||||
pb_IntArray[] sharedIndicesUV = pb.sharedIndicesUV;
|
||||
for (int j = 0; j < indices.Length - 1; j++)
|
||||
{
|
||||
for (int k = j + 1; k < indices.Length; k++)
|
||||
{
|
||||
if (array[j] != array[k])
|
||||
{
|
||||
if (Vector2.Distance(array2[indices[j]], array2[indices[k]]) < delta)
|
||||
{
|
||||
Vector3 vector = (array2[indices[j]] + array2[indices[k]]) / 2f;
|
||||
array2[indices[j]] = vector;
|
||||
array2[indices[k]] = vector;
|
||||
int num = pb_IntArrayUtility.MergeSharedIndices(ref sharedIndicesUV, new int[]
|
||||
{
|
||||
indices[j],
|
||||
indices[k]
|
||||
});
|
||||
array[j] = num;
|
||||
array[k] = num;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pb.SetUV(array2);
|
||||
pb.SetSharedIndicesUV(sharedIndicesUV);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Token: 0x0600003B RID: 59 RVA: 0x00006530 File Offset: 0x00004930
|
||||
public static void CollapseUVs(this pb_Object pb, int[] indices)
|
||||
{
|
||||
Vector2[] uv = pb.uv;
|
||||
Vector2 vector = pb_Math.Average(uv.ValuesWithIndices(indices), null);
|
||||
foreach (int num in indices)
|
||||
{
|
||||
uv[num] = vector;
|
||||
}
|
||||
pb_IntArray[] sharedIndicesUV = pb.sharedIndicesUV;
|
||||
pb_IntArrayUtility.MergeSharedIndices(ref sharedIndicesUV, indices);
|
||||
pb.SetUV(uv);
|
||||
pb.SetSharedIndicesUV(sharedIndicesUV);
|
||||
}
|
||||
|
||||
// Token: 0x0600003C RID: 60 RVA: 0x000065A0 File Offset: 0x000049A0
|
||||
public static bool SplitUVs(this pb_Object pb, int[] indices)
|
||||
{
|
||||
pb_IntArray[] sharedIndicesUV = pb.sharedIndicesUV;
|
||||
if (sharedIndicesUV == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
List<int> list = indices.Distinct<int>().ToList<int>();
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
int num = sharedIndicesUV.IndexOf(list[i]);
|
||||
if (num >= 0)
|
||||
{
|
||||
sharedIndicesUV[num].array = sharedIndicesUV[num].array.Remove(list[i]);
|
||||
}
|
||||
}
|
||||
foreach (int num2 in list)
|
||||
{
|
||||
pb_IntArrayUtility.AddValueAtIndex(ref sharedIndicesUV, -1, num2);
|
||||
}
|
||||
pb.SetSharedIndicesUV(sharedIndicesUV);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Token: 0x0600003D RID: 61 RVA: 0x00006670 File Offset: 0x00004A70
|
||||
public static void ProjectFacesAuto(pb_Object pb, pb_Face[] faces)
|
||||
{
|
||||
int[] array = pb_Face.AllTrianglesDistinct(faces);
|
||||
Vector3 vector = Vector3.zero;
|
||||
foreach (pb_Face pb_Face in faces)
|
||||
{
|
||||
vector += pb_Math.Normal(pb, pb_Face);
|
||||
}
|
||||
vector /= (float)faces.Length;
|
||||
Vector2[] array2 = pb_Projection.PlanarProject(pb.vertices.ValuesWithIndices(array), vector);
|
||||
Vector2[] uv = pb.uv;
|
||||
for (int j = 0; j < array.Length; j++)
|
||||
{
|
||||
uv[array[j]] = array2[j];
|
||||
}
|
||||
pb.SetUV(uv);
|
||||
pb.msh.uv = uv;
|
||||
foreach (pb_Face pb_Face2 in faces)
|
||||
{
|
||||
pb_Face2.elementGroup = -1;
|
||||
pb.SplitUVs(pb_Face2.distinctIndices);
|
||||
}
|
||||
pb.SewUVs(pb_Face.AllTrianglesDistinct(faces), 0.001f);
|
||||
}
|
||||
|
||||
// Token: 0x0600003E RID: 62 RVA: 0x00006774 File Offset: 0x00004B74
|
||||
public static void ProjectFacesBox(pb_Object pb, pb_Face[] faces)
|
||||
{
|
||||
Vector2[] uv = pb.uv;
|
||||
Dictionary<ProjectionAxis, List<pb_Face>> dictionary = new Dictionary<ProjectionAxis, List<pb_Face>>();
|
||||
for (int i = 0; i < faces.Length; i++)
|
||||
{
|
||||
Vector3 vector = pb_Math.Normal(pb, faces[i]);
|
||||
ProjectionAxis projectionAxis = pb_Projection.VectorToProjectionAxis(vector);
|
||||
if (dictionary.ContainsKey(projectionAxis))
|
||||
{
|
||||
dictionary[projectionAxis].Add(faces[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary.Add(projectionAxis, new List<pb_Face> { faces[i] });
|
||||
}
|
||||
faces[i].elementGroup = -1;
|
||||
faces[i].manualUV = true;
|
||||
}
|
||||
foreach (KeyValuePair<ProjectionAxis, List<pb_Face>> keyValuePair in dictionary)
|
||||
{
|
||||
int[] array = pb_Face.AllTrianglesDistinct(keyValuePair.Value.ToArray());
|
||||
Vector2[] array2 = pb_Projection.PlanarProject(pb.vertices.ValuesWithIndices(array), pb_Projection.ProjectionAxisToVector(keyValuePair.Key), keyValuePair.Key, null);
|
||||
for (int j = 0; j < array.Length; j++)
|
||||
{
|
||||
uv[array[j]] = array2[j];
|
||||
}
|
||||
pb.SplitUVs(array);
|
||||
}
|
||||
pb.SetUV(uv);
|
||||
}
|
||||
|
||||
// Token: 0x0600003F RID: 63 RVA: 0x000068CC File Offset: 0x00004CCC
|
||||
public static void ProjectFacesSphere(pb_Object pb, int[] indices)
|
||||
{
|
||||
foreach (pb_Face pb_Face in pb.faces)
|
||||
{
|
||||
if (pb_Face.distinctIndices.ContainsMatch(indices))
|
||||
{
|
||||
pb_Face.elementGroup = -1;
|
||||
pb_Face.manualUV = true;
|
||||
}
|
||||
}
|
||||
pb.SplitUVs(indices);
|
||||
Vector2[] array = pb_Projection.SphericalProject(pb.vertices, indices);
|
||||
Vector2[] uv = pb.uv;
|
||||
for (int j = 0; j < indices.Length; j++)
|
||||
{
|
||||
uv[indices[j]] = array[j];
|
||||
}
|
||||
pb.SetUV(uv);
|
||||
}
|
||||
|
||||
// Token: 0x06000040 RID: 64 RVA: 0x00006974 File Offset: 0x00004D74
|
||||
public static Vector2[] FitUVs(Vector2[] uvs)
|
||||
{
|
||||
Vector2 vector = pb_Math.SmallestVector2(uvs);
|
||||
for (int i = 0; i < uvs.Length; i++)
|
||||
{
|
||||
uvs[i] -= vector;
|
||||
}
|
||||
float num = pb_Math.LargestValue(pb_Math.LargestVector2(uvs));
|
||||
for (int i = 0; i < uvs.Length; i++)
|
||||
{
|
||||
uvs[i] /= num;
|
||||
}
|
||||
return uvs;
|
||||
}
|
||||
|
||||
// Token: 0x06000041 RID: 65 RVA: 0x000069F0 File Offset: 0x00004DF0
|
||||
public static bool AutoStitch(pb_Object pb, pb_Face f1, pb_Face f2)
|
||||
{
|
||||
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
||||
for (int i = 0; i < f1.edges.Length; i++)
|
||||
{
|
||||
int num = f2.edges.IndexOf(f1.edges[i], dictionary);
|
||||
if (num > -1)
|
||||
{
|
||||
pbUVOps.ProjectFacesAuto(pb, new pb_Face[] { f2 });
|
||||
f1.manualUV = true;
|
||||
f2.manualUV = true;
|
||||
f1.textureGroup = -1;
|
||||
f2.textureGroup = -1;
|
||||
pbUVOps.AlignEdges(pb, f1, f2, f1.edges[i], f2.edges[num]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Token: 0x06000042 RID: 66 RVA: 0x00006A88 File Offset: 0x00004E88
|
||||
private static bool AlignEdges(pb_Object pb, pb_Face f1, pb_Face f2, pb_Edge edge1, pb_Edge edge2)
|
||||
{
|
||||
Vector2[] uv = pb.uv;
|
||||
pb_IntArray[] sharedIndices = pb.sharedIndices;
|
||||
pb_IntArray[] sharedIndicesUV = pb.sharedIndicesUV;
|
||||
int[] array = new int[] { edge1.x, -1 };
|
||||
int[] array2 = new int[] { edge1.y, -1 };
|
||||
int num = sharedIndices.IndexOf(edge1.x);
|
||||
if (num < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (sharedIndices[num].array.Contains(edge2.x))
|
||||
{
|
||||
array[1] = edge2.x;
|
||||
array2[1] = edge2.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
array[1] = edge2.y;
|
||||
array2[1] = edge2.x;
|
||||
}
|
||||
float num2 = Vector2.Distance(uv[edge1.x], uv[edge1.y]);
|
||||
float num3 = Vector2.Distance(uv[edge2.x], uv[edge2.y]);
|
||||
float num4 = num2 / num3;
|
||||
foreach (int num5 in f2.distinctIndices)
|
||||
{
|
||||
uv[num5] = uv[num5].ScaleAroundPoint(Vector2.zero, Vector2.one * num4);
|
||||
}
|
||||
Vector2 vector = (uv[edge1.x] + uv[edge1.y]) / 2f;
|
||||
Vector2 vector2 = (uv[edge2.x] + uv[edge2.y]) / 2f;
|
||||
Vector2 vector3 = vector - vector2;
|
||||
foreach (int num6 in f2.distinctIndices)
|
||||
{
|
||||
uv[num6] += vector3;
|
||||
}
|
||||
Vector2 vector4 = uv[array2[0]] - uv[array[0]];
|
||||
Vector2 vector5 = uv[array2[1]] - uv[array[1]];
|
||||
float num7 = Vector2.Angle(vector4, vector5);
|
||||
if (Vector3.Cross(vector4, vector5).z < 0f)
|
||||
{
|
||||
num7 = 360f - num7;
|
||||
}
|
||||
foreach (int num8 in f2.distinctIndices)
|
||||
{
|
||||
uv[num8] = uv[num8].RotateAroundPoint(vector, num7);
|
||||
}
|
||||
float num9 = Mathf.Abs(Vector2.Distance(uv[array[0]], uv[array[1]])) + Mathf.Abs(Vector2.Distance(uv[array2[0]], uv[array2[1]]));
|
||||
if (num9 > 0.02f)
|
||||
{
|
||||
foreach (int num10 in f2.distinctIndices)
|
||||
{
|
||||
uv[num10] = uv[num10].RotateAroundPoint(vector, 180f);
|
||||
}
|
||||
float num11 = Mathf.Abs(Vector2.Distance(uv[array[0]], uv[array[1]])) + Mathf.Abs(Vector2.Distance(uv[array2[0]], uv[array2[1]]));
|
||||
if (num11 >= num9)
|
||||
{
|
||||
foreach (int num12 in f2.distinctIndices)
|
||||
{
|
||||
uv[num12] = uv[num12].RotateAroundPoint(vector, 180f);
|
||||
}
|
||||
}
|
||||
}
|
||||
pb.SplitUVs(f2.distinctIndices);
|
||||
pb_IntArrayUtility.MergeSharedIndices(ref sharedIndicesUV, array);
|
||||
pb_IntArrayUtility.MergeSharedIndices(ref sharedIndicesUV, array2);
|
||||
pb_IntArray.RemoveEmptyOrNull(ref sharedIndicesUV);
|
||||
pb.SetSharedIndicesUV(sharedIndicesUV);
|
||||
pb.SetUV(uv);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Token: 0x06000043 RID: 67 RVA: 0x00006EFC File Offset: 0x000052FC
|
||||
public static pb_Transform2D MatchCoordinates(Vector2[] points, Vector2[] target)
|
||||
{
|
||||
int num = ((points.Length >= target.Length) ? target.Length : points.Length);
|
||||
pb_Bounds2D pb_Bounds2D = new pb_Bounds2D(target, num);
|
||||
Vector2 vector = pb_Bounds2D.center - pb_Bounds2D.Center(points, num);
|
||||
Vector2[] array = new Vector2[points.Length];
|
||||
for (int i = 0; i < points.Length; i++)
|
||||
{
|
||||
array[i] = points[i] + vector;
|
||||
}
|
||||
Vector2 vector2 = target[1] - target[0];
|
||||
Vector2 vector3 = array[1] - array[0];
|
||||
float num2 = Vector2.Angle(vector2, vector3);
|
||||
float num3 = Vector2.Dot(pb_Math.Perpendicular(vector2), vector3);
|
||||
if (num3 < 0f)
|
||||
{
|
||||
num2 = 360f - num2;
|
||||
}
|
||||
for (int j = 0; j < points.Length; j++)
|
||||
{
|
||||
array[j] = array[j].RotateAroundPoint(pb_Bounds2D.center, num2);
|
||||
}
|
||||
pb_Bounds2D pb_Bounds2D2 = new pb_Bounds2D(array, num);
|
||||
Vector2 vector4 = pb_Bounds2D.size.DivideBy(pb_Bounds2D2.size);
|
||||
return new pb_Transform2D(vector, num2, vector4);
|
||||
}
|
||||
|
||||
// Token: 0x06000044 RID: 68 RVA: 0x00007054 File Offset: 0x00005454
|
||||
public static void SetAutoUV(pb_Object pb, pb_Face[] faces, bool auto)
|
||||
{
|
||||
if (auto)
|
||||
{
|
||||
faces = Array.FindAll<pb_Face>(faces, (pb_Face x) => x.manualUV).ToArray<pb_Face>();
|
||||
pb.SplitUVs(pb_Face.AllTriangles(faces));
|
||||
Vector2[][] array = new Vector2[faces.Length][];
|
||||
for (int i = 0; i < faces.Length; i++)
|
||||
{
|
||||
array[i] = pb.uv.ValuesWithIndices(faces[i].distinctIndices);
|
||||
}
|
||||
for (int j = 0; j < faces.Length; j++)
|
||||
{
|
||||
faces[j].uv.Reset();
|
||||
faces[j].manualUV = !auto;
|
||||
faces[j].elementGroup = -1;
|
||||
}
|
||||
pb.RefreshUV(faces);
|
||||
for (int k = 0; k < faces.Length; k++)
|
||||
{
|
||||
pb_Transform2D pb_Transform2D = pbUVOps.MatchCoordinates(pb.uv.ValuesWithIndices(faces[k].distinctIndices), array[k]);
|
||||
faces[k].uv.offset = -pb_Transform2D.position;
|
||||
faces[k].uv.rotation = pb_Transform2D.rotation;
|
||||
if (Mathf.Abs(pb_Transform2D.scale.sqrMagnitude - 2f) > 0.1f)
|
||||
{
|
||||
faces[k].uv.scale = pb_Transform2D.scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (pb_Face pb_Face in faces)
|
||||
{
|
||||
pb_Face.textureGroup = -1;
|
||||
pb_Face.manualUV = !auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x06000045 RID: 69 RVA: 0x000071DC File Offset: 0x000055DC
|
||||
public static Vector2 NearestVector2(Vector2 pos, Vector2[] uvs)
|
||||
{
|
||||
if (uvs.Length < 1)
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
Vector2 vector = uvs[0];
|
||||
float num = Vector2.Distance(pos, vector);
|
||||
for (int i = 1; i < uvs.Length; i++)
|
||||
{
|
||||
float num2 = Vector2.Distance(pos, uvs[i]);
|
||||
if (num2 < num)
|
||||
{
|
||||
num = num2;
|
||||
vector = uvs[i];
|
||||
}
|
||||
}
|
||||
return vector;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ProBuilder2.Common;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x02000006 RID: 6
|
||||
public static class pbVertexOps
|
||||
{
|
||||
// Token: 0x06000047 RID: 71 RVA: 0x00007250 File Offset: 0x00005650
|
||||
public static bool MergeVertices(this pb_Object pb, int[] indices, out int collapsedIndex, bool collapseToFirst = false)
|
||||
{
|
||||
pb_Vertex[] vertices = pb_Vertex.GetVertices(pb, null);
|
||||
pb_Vertex pb_Vertex = ((!collapseToFirst) ? pb_Vertex.Average(vertices, indices) : vertices[indices[0]]);
|
||||
pb_IntArray[] sharedIndices = pb.sharedIndices;
|
||||
pb_IntArray[] sharedIndicesUV = pb.sharedIndicesUV;
|
||||
int num = pb_IntArrayUtility.MergeSharedIndices(ref sharedIndices, indices);
|
||||
pb_IntArrayUtility.MergeSharedIndices(ref sharedIndicesUV, indices);
|
||||
pb.SetSharedIndices(sharedIndices);
|
||||
pb.SetSharedIndicesUV(sharedIndicesUV);
|
||||
pb.SetSharedVertexValues(num, pb_Vertex);
|
||||
int[] array = pb.GetSharedIndices()[num].array;
|
||||
int[] array2;
|
||||
pb.RemoveDegenerateTriangles(out array2);
|
||||
int num2 = -1;
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
if (!array2.Contains(array[i]))
|
||||
{
|
||||
num2 = array[i];
|
||||
}
|
||||
}
|
||||
int num3 = num2;
|
||||
for (int j = 0; j < array2.Length; j++)
|
||||
{
|
||||
if (num2 > array2[j])
|
||||
{
|
||||
num3--;
|
||||
}
|
||||
}
|
||||
if (num3 > -1)
|
||||
{
|
||||
collapsedIndex = num3;
|
||||
return true;
|
||||
}
|
||||
collapsedIndex = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Token: 0x06000048 RID: 72 RVA: 0x00007344 File Offset: 0x00005744
|
||||
public static bool SplitCommonVertices(this pb_Object pb, int[] indices)
|
||||
{
|
||||
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
||||
pb_IntArray[] sharedIndices = pb.sharedIndices;
|
||||
List<int> list = new List<int>();
|
||||
List<int> list2 = new List<int>();
|
||||
for (int i = 0; i < indices.Length; i++)
|
||||
{
|
||||
int num = dictionary[indices[i]];
|
||||
if (!list.Contains(num))
|
||||
{
|
||||
list.Add(num);
|
||||
list2.AddRange(sharedIndices[num].array);
|
||||
}
|
||||
}
|
||||
pb_IntArrayUtility.RemoveValues(ref sharedIndices, list2.ToArray());
|
||||
foreach (int num2 in list2)
|
||||
{
|
||||
pb_IntArrayUtility.AddValueAtIndex(ref sharedIndices, -1, num2);
|
||||
}
|
||||
pb.SetSharedIndices(sharedIndices);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Token: 0x06000049 RID: 73 RVA: 0x00007420 File Offset: 0x00005820
|
||||
public static void SplitVertices(this pb_Object pb, pb_Edge edge)
|
||||
{
|
||||
pb.SplitVertices(new int[] { edge.x, edge.y });
|
||||
}
|
||||
|
||||
// Token: 0x0600004A RID: 74 RVA: 0x00007440 File Offset: 0x00005840
|
||||
public static void SplitVertices(this pb_Object pb, IEnumerable<int> indices)
|
||||
{
|
||||
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
||||
int num = dictionary.Count<KeyValuePair<int, int>>();
|
||||
foreach (int num2 in indices)
|
||||
{
|
||||
num = (dictionary[num2] = num + 1);
|
||||
}
|
||||
pb.SetSharedIndices(dictionary);
|
||||
}
|
||||
|
||||
// Token: 0x0600004B RID: 75 RVA: 0x000074B4 File Offset: 0x000058B4
|
||||
public static bool AppendVerticesToFace(this pb_Object pb, pb_Face face, Vector3[] points, Color[] addColors, out pb_Face newFace)
|
||||
{
|
||||
if (!face.IsValid())
|
||||
{
|
||||
newFace = face;
|
||||
return false;
|
||||
}
|
||||
List<pb_Vertex> list = pb_Vertex.GetVertices(pb, null).ToList<pb_Vertex>();
|
||||
List<pb_Face> list2 = new List<pb_Face>(pb.faces);
|
||||
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
||||
Dictionary<int, int> dictionary2 = ((pb.sharedIndicesUV != null) ? pb.sharedIndicesUV.ToDictionary() : null);
|
||||
List<pb_Edge> list3 = pb_WingedEdge.SortEdgesByAdjacency(face);
|
||||
List<pb_Vertex> list4 = new List<pb_Vertex>();
|
||||
List<int> list5 = new List<int>();
|
||||
List<int> list6 = ((dictionary2 == null) ? null : new List<int>());
|
||||
for (int i = 0; i < list3.Count; i++)
|
||||
{
|
||||
list4.Add(list[list3[i].x]);
|
||||
list5.Add(dictionary[list3[i].x]);
|
||||
if (dictionary2 != null)
|
||||
{
|
||||
int num;
|
||||
if (dictionary2.TryGetValue(list3[i].x, out num))
|
||||
{
|
||||
list6.Add(num);
|
||||
}
|
||||
else
|
||||
{
|
||||
list6.Add(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < points.Length; j++)
|
||||
{
|
||||
int num2 = -1;
|
||||
float num3 = float.PositiveInfinity;
|
||||
Vector3 vector = points[j];
|
||||
int count = list4.Count;
|
||||
for (int k = 0; k < count; k++)
|
||||
{
|
||||
Vector3 position = list4[k].position;
|
||||
Vector3 position2 = list4[(k + 1) % count].position;
|
||||
float num4 = pb_Math.DistancePointLineSegment(vector, position, position2);
|
||||
if (num4 < num3)
|
||||
{
|
||||
num3 = num4;
|
||||
num2 = k;
|
||||
}
|
||||
}
|
||||
pb_Vertex pb_Vertex = list4[num2];
|
||||
pb_Vertex pb_Vertex2 = list4[(num2 + 1) % count];
|
||||
float sqrMagnitude = (vector - pb_Vertex.position).sqrMagnitude;
|
||||
float sqrMagnitude2 = (vector - pb_Vertex2.position).sqrMagnitude;
|
||||
pb_Vertex pb_Vertex3 = pb_Vertex.Mix(pb_Vertex, pb_Vertex2, sqrMagnitude / (sqrMagnitude + sqrMagnitude2));
|
||||
list4.Insert((num2 + 1) % count, pb_Vertex3);
|
||||
list5.Insert((num2 + 1) % count, -1);
|
||||
if (list6 != null)
|
||||
{
|
||||
list6.Insert((num2 + 1) % count, -1);
|
||||
}
|
||||
}
|
||||
List<int> list7;
|
||||
try
|
||||
{
|
||||
pb_Triangulation.TriangulateVertices(list4, out list7, false, false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Debug.Log("Failed triangulating face after appending vertices.");
|
||||
newFace = null;
|
||||
return false;
|
||||
}
|
||||
pb_FaceRebuildData pb_FaceRebuildData = new pb_FaceRebuildData();
|
||||
pb_FaceRebuildData.face = new pb_Face(list7.ToArray(), face.material, new pb_UV(face.uv), face.smoothingGroup, face.textureGroup, -1, face.manualUV);
|
||||
pb_FaceRebuildData.vertices = list4;
|
||||
pb_FaceRebuildData.sharedIndices = list5;
|
||||
pb_FaceRebuildData.sharedIndicesUV = list6;
|
||||
pb_FaceRebuildData.Apply(new List<pb_FaceRebuildData> { pb_FaceRebuildData }, list, list2, dictionary, dictionary2);
|
||||
newFace = pb_FaceRebuildData.face;
|
||||
pb.SetVertices(list, false);
|
||||
pb.SetFaces(list2.ToArray());
|
||||
pb.SetSharedIndices(dictionary);
|
||||
pb.SetSharedIndicesUV(dictionary2);
|
||||
Vector3 vector2 = pb_Math.Normal(pb, face);
|
||||
Vector3 vector3 = pb_Math.Normal(pb, newFace);
|
||||
if (Vector3.Dot(vector2, vector3) < 0f)
|
||||
{
|
||||
newFace.ReverseIndices();
|
||||
}
|
||||
pb.DeleteFace(face);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Token: 0x0600004C RID: 76 RVA: 0x00007804 File Offset: 0x00005C04
|
||||
public static pb_ActionResult AppendVerticesToEdge(this pb_Object pb, pb_Edge edge, int count, out List<pb_Edge> newEdges)
|
||||
{
|
||||
return pb.AppendVerticesToEdge(new pb_Edge[] { edge }, count, out newEdges);
|
||||
}
|
||||
|
||||
// Token: 0x0600004D RID: 77 RVA: 0x00007818 File Offset: 0x00005C18
|
||||
public static pb_ActionResult AppendVerticesToEdge(this pb_Object pb, IList<pb_Edge> edges, int count, out List<pb_Edge> newEdges)
|
||||
{
|
||||
newEdges = new List<pb_Edge>();
|
||||
if (count < 1 || count > 512)
|
||||
{
|
||||
return new pb_ActionResult(Status.Failure, "New edge vertex count is less than 1 or greater than 512.");
|
||||
}
|
||||
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
|
||||
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
||||
Dictionary<int, int> dictionary2 = pb.sharedIndicesUV.ToDictionary();
|
||||
List<int> list2 = new List<int>();
|
||||
pb_Edge[] universalEdges = pb_Edge.GetUniversalEdges(edges.ToArray<pb_Edge>(), dictionary);
|
||||
List<pb_Edge> list3 = universalEdges.Distinct<pb_Edge>().ToList<pb_Edge>();
|
||||
Dictionary<pb_Face, pb_FaceRebuildData> dictionary3 = new Dictionary<pb_Face, pb_FaceRebuildData>();
|
||||
int num = dictionary.Count<KeyValuePair<int, int>>();
|
||||
int num2 = num;
|
||||
foreach (pb_Edge pb_Edge in list3)
|
||||
{
|
||||
pb_Edge localEdgeFast = pb_Edge.GetLocalEdgeFast(pb_Edge, pb.sharedIndices);
|
||||
List<pb_Vertex> list4 = new List<pb_Vertex>(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
list4.Add(pb_Vertex.Mix(list[localEdgeFast.x], list[localEdgeFast.y], (float)(i + 1) / ((float)count + 1f)));
|
||||
}
|
||||
List<pb_Tuple<pb_Face, pb_Edge>> neighborFaces = pbMeshUtils.GetNeighborFaces(pb, localEdgeFast, null);
|
||||
foreach (pb_Tuple<pb_Face, pb_Edge> pb_Tuple in neighborFaces)
|
||||
{
|
||||
pb_Face item = pb_Tuple.Item1;
|
||||
pb_FaceRebuildData pb_FaceRebuildData;
|
||||
if (!dictionary3.TryGetValue(item, out pb_FaceRebuildData))
|
||||
{
|
||||
pb_FaceRebuildData = new pb_FaceRebuildData();
|
||||
pb_FaceRebuildData.face = new pb_Face(null, item.material, new pb_UV(item.uv), item.smoothingGroup, item.textureGroup, -1, item.manualUV);
|
||||
pb_FaceRebuildData.vertices = new List<pb_Vertex>(list.ValuesWithIndices(item.distinctIndices));
|
||||
pb_FaceRebuildData.sharedIndices = new List<int>();
|
||||
pb_FaceRebuildData.sharedIndicesUV = new List<int>();
|
||||
foreach (int num3 in item.distinctIndices)
|
||||
{
|
||||
int num4;
|
||||
if (dictionary.TryGetValue(num3, out num4))
|
||||
{
|
||||
pb_FaceRebuildData.sharedIndices.Add(num4);
|
||||
}
|
||||
if (dictionary2.TryGetValue(num3, out num4))
|
||||
{
|
||||
pb_FaceRebuildData.sharedIndicesUV.Add(num4);
|
||||
}
|
||||
}
|
||||
list2.AddRange(item.distinctIndices);
|
||||
dictionary3.Add(item, pb_FaceRebuildData);
|
||||
}
|
||||
pb_FaceRebuildData.vertices.AddRange(list4);
|
||||
for (int k = 0; k < count; k++)
|
||||
{
|
||||
pb_FaceRebuildData.sharedIndices.Add(num2 + k);
|
||||
pb_FaceRebuildData.sharedIndicesUV.Add(-1);
|
||||
}
|
||||
}
|
||||
num2 += count;
|
||||
}
|
||||
List<pb_Face> list5 = dictionary3.Keys.ToList<pb_Face>();
|
||||
List<pb_FaceRebuildData> list6 = dictionary3.Values.ToList<pb_FaceRebuildData>();
|
||||
List<pb_EdgeLookup> list7 = new List<pb_EdgeLookup>();
|
||||
for (int l = 0; l < list5.Count; l++)
|
||||
{
|
||||
pb_Face pb_Face = list5[l];
|
||||
pb_FaceRebuildData pb_FaceRebuildData2 = list6[l];
|
||||
Vector3 vector = pb_Math.Normal(pb, pb_Face);
|
||||
Vector2[] array = pb_Projection.PlanarProject(pb_FaceRebuildData2.vertices.Select((pb_Vertex x) => x.position).ToArray<Vector3>(), vector);
|
||||
int count2 = list.Count;
|
||||
List<int> list8;
|
||||
if (pb_Triangulation.SortAndTriangulate(array, out list8, false))
|
||||
{
|
||||
pb_FaceRebuildData2.face.SetIndices(list8.ToArray());
|
||||
pb_FaceRebuildData2.face.ShiftIndices(count2);
|
||||
pb_Face.CopyFrom(pb_FaceRebuildData2.face);
|
||||
for (int m = 0; m < pb_FaceRebuildData2.vertices.Count; m++)
|
||||
{
|
||||
dictionary.Add(count2 + m, pb_FaceRebuildData2.sharedIndices[m]);
|
||||
}
|
||||
if (pb_FaceRebuildData2.sharedIndicesUV.Count == pb_FaceRebuildData2.vertices.Count)
|
||||
{
|
||||
for (int n = 0; n < pb_FaceRebuildData2.vertices.Count; n++)
|
||||
{
|
||||
dictionary2.Add(count2 + n, pb_FaceRebuildData2.sharedIndicesUV[n]);
|
||||
}
|
||||
}
|
||||
list.AddRange(pb_FaceRebuildData2.vertices);
|
||||
foreach (pb_Edge pb_Edge2 in pb_Face.edges)
|
||||
{
|
||||
pb_EdgeLookup pb_EdgeLookup = new pb_EdgeLookup(new pb_Edge(dictionary[pb_Edge2.x], dictionary[pb_Edge2.y]), pb_Edge2);
|
||||
if (pb_EdgeLookup.common.x >= num || pb_EdgeLookup.common.y >= num)
|
||||
{
|
||||
list7.Add(pb_EdgeLookup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
list2 = list2.Distinct<int>().ToList<int>();
|
||||
int delCount = list2.Count;
|
||||
newEdges = (from x in list7.Distinct<pb_EdgeLookup>()
|
||||
select x.local - delCount).ToList<pb_Edge>();
|
||||
pb.SetVertices(list, false);
|
||||
pb.SetSharedIndices(dictionary.ToSharedIndices());
|
||||
pb.SetSharedIndicesUV(dictionary2.ToSharedIndices());
|
||||
pb.DeleteVerticesWithIndices(list2);
|
||||
return new pb_ActionResult(Status.Success, "Subdivide Edges");
|
||||
}
|
||||
|
||||
// Token: 0x0600004E RID: 78 RVA: 0x00007D74 File Offset: 0x00006174
|
||||
public static pb_FaceRebuildData ExplodeVertex(IList<pb_Vertex> vertices, IList<pb_Tuple<pb_WingedEdge, int>> edgeAndCommonIndex, float distance, out Dictionary<int, List<int>> appendedVertices)
|
||||
{
|
||||
pb_Face face = edgeAndCommonIndex.FirstOrDefault<pb_Tuple<pb_WingedEdge, int>>().Item1.face;
|
||||
List<pb_Edge> list = pb_WingedEdge.SortEdgesByAdjacency(face);
|
||||
appendedVertices = new Dictionary<int, List<int>>();
|
||||
Vector3 vector = pb_Math.Normal(vertices, face.indices);
|
||||
Dictionary<int, int> dictionary = new Dictionary<int, int>();
|
||||
foreach (pb_Tuple<pb_WingedEdge, int> pb_Tuple in edgeAndCommonIndex)
|
||||
{
|
||||
if (pb_Tuple.Item2 == pb_Tuple.Item1.edge.common.x)
|
||||
{
|
||||
dictionary.Add(pb_Tuple.Item1.edge.local.x, pb_Tuple.Item2);
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary.Add(pb_Tuple.Item1.edge.local.y, pb_Tuple.Item2);
|
||||
}
|
||||
}
|
||||
int count = list.Count;
|
||||
List<pb_Vertex> list2 = new List<pb_Vertex>();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int y = list[i].y;
|
||||
if (dictionary.ContainsKey(y))
|
||||
{
|
||||
pb_Vertex pb_Vertex = vertices[list[i].x];
|
||||
pb_Vertex pb_Vertex2 = vertices[list[i].y];
|
||||
pb_Vertex pb_Vertex3 = vertices[list[(i + 1) % count].y];
|
||||
pb_Vertex pb_Vertex4 = pb_Vertex - pb_Vertex2;
|
||||
pb_Vertex pb_Vertex5 = pb_Vertex3 - pb_Vertex2;
|
||||
pb_Vertex4.Normalize();
|
||||
pb_Vertex5.Normalize();
|
||||
pb_Vertex pb_Vertex6 = vertices[y] + pb_Vertex4 * distance;
|
||||
pb_Vertex pb_Vertex7 = vertices[y] + pb_Vertex5 * distance;
|
||||
appendedVertices.AddOrAppend(dictionary[y], list2.Count);
|
||||
list2.Add(pb_Vertex6);
|
||||
appendedVertices.AddOrAppend(dictionary[y], list2.Count);
|
||||
list2.Add(pb_Vertex7);
|
||||
}
|
||||
else
|
||||
{
|
||||
list2.Add(vertices[y]);
|
||||
}
|
||||
}
|
||||
List<int> list3;
|
||||
if (pb_Triangulation.TriangulateVertices(list2, out list3, false, false))
|
||||
{
|
||||
pb_FaceRebuildData pb_FaceRebuildData = new pb_FaceRebuildData();
|
||||
pb_FaceRebuildData.vertices = list2;
|
||||
pb_FaceRebuildData.face = new pb_Face(face);
|
||||
Vector3 vector2 = pb_Math.Normal(list2, list3);
|
||||
if (Vector3.Dot(vector, vector2) < 0f)
|
||||
{
|
||||
list3.Reverse();
|
||||
}
|
||||
pb_FaceRebuildData.face.SetIndices(list3.ToArray());
|
||||
return pb_FaceRebuildData;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Token: 0x0600004F RID: 79 RVA: 0x00007FF8 File Offset: 0x000063F8
|
||||
private static pb_Edge AlignEdgeWithDirection(pb_EdgeLookup edge, int commonIndex)
|
||||
{
|
||||
if (edge.common.x == commonIndex)
|
||||
{
|
||||
return new pb_Edge(edge.local.x, edge.local.y);
|
||||
}
|
||||
return new pb_Edge(edge.local.y, edge.local.x);
|
||||
}
|
||||
|
||||
// Token: 0x06000050 RID: 80 RVA: 0x00008050 File Offset: 0x00006450
|
||||
public static void Quantize(pb_Object pb, IList<int> indices, Vector3 snap)
|
||||
{
|
||||
Vector3[] vertices = pb.vertices;
|
||||
for (int i = 0; i < indices.Count; i++)
|
||||
{
|
||||
vertices[indices[i]] = pb.transform.InverseTransformPoint(pb_Snap.SnapValue(pb.transform.TransformPoint(vertices[indices[i]]), snap));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ProBuilder2.Common;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x02000007 RID: 7
|
||||
public static class pb_AppendDelete
|
||||
{
|
||||
// Token: 0x06000052 RID: 82 RVA: 0x000080E0 File Offset: 0x000064E0
|
||||
public static pb_Face AppendFace(this pb_Object pb, Vector3[] v, Color[] c, Vector2[] u, pb_Face face)
|
||||
{
|
||||
int[] array = new int[v.Length];
|
||||
for (int i = 0; i < v.Length; i++)
|
||||
{
|
||||
array[i] = -1;
|
||||
}
|
||||
return pb.AppendFace(v, c, u, face, array);
|
||||
}
|
||||
|
||||
// Token: 0x06000053 RID: 83 RVA: 0x0000811C File Offset: 0x0000651C
|
||||
public static pb_Face AppendFace(this pb_Object pb, Vector3[] v, Color[] c, Vector2[] u, pb_Face face, int[] sharedIndex)
|
||||
{
|
||||
int vertexCount = pb.vertexCount;
|
||||
Vector3[] array = new Vector3[vertexCount + v.Length];
|
||||
Color[] array2 = new Color[vertexCount + c.Length];
|
||||
Vector2[] array3 = new Vector2[pb.uv.Length + u.Length];
|
||||
List<pb_Face> list = new List<pb_Face>(pb.faces);
|
||||
pb_IntArray[] sharedIndices = pb.sharedIndices;
|
||||
Array.Copy(pb.vertices, 0, array, 0, vertexCount);
|
||||
Array.Copy(v, 0, array, vertexCount, v.Length);
|
||||
Array.Copy(pb.colors, 0, array2, 0, vertexCount);
|
||||
Array.Copy(c, 0, array2, vertexCount, c.Length);
|
||||
Array.Copy(pb.uv, 0, array3, 0, pb.uv.Length);
|
||||
Array.Copy(u, 0, array3, pb.uv.Length, u.Length);
|
||||
face.ShiftIndicesToZero();
|
||||
face.ShiftIndices(vertexCount);
|
||||
face.RebuildCaches();
|
||||
list.Add(face);
|
||||
for (int i = 0; i < sharedIndex.Length; i++)
|
||||
{
|
||||
pb_IntArrayUtility.AddValueAtIndex(ref sharedIndices, sharedIndex[i], i + vertexCount);
|
||||
}
|
||||
pb.SetVertices(array);
|
||||
pb.SetColors(array2);
|
||||
pb.SetUV(array3);
|
||||
pb.SetSharedIndices(sharedIndices);
|
||||
pb.SetFaces(list.ToArray());
|
||||
return face;
|
||||
}
|
||||
|
||||
// Token: 0x06000054 RID: 84 RVA: 0x00008244 File Offset: 0x00006644
|
||||
public static pb_Face[] AppendFaces(this pb_Object pb, Vector3[][] new_Vertices, Color[][] new_Colors, Vector2[][] new_uvs, pb_Face[] new_Faces, int[][] new_SharedIndices)
|
||||
{
|
||||
List<Vector3> list = new List<Vector3>(pb.vertices);
|
||||
List<Color> list2 = new List<Color>(pb.colors);
|
||||
List<Vector2> list3 = new List<Vector2>(pb.uv);
|
||||
List<pb_Face> list4 = new List<pb_Face>(pb.faces);
|
||||
pb_IntArray[] sharedIndices = pb.sharedIndices;
|
||||
int num = pb.vertexCount;
|
||||
for (int i = 0; i < new_Faces.Length; i++)
|
||||
{
|
||||
list.AddRange(new_Vertices[i]);
|
||||
list2.AddRange(new_Colors[i]);
|
||||
list3.AddRange(new_uvs[i]);
|
||||
new_Faces[i].ShiftIndicesToZero();
|
||||
new_Faces[i].ShiftIndices(num);
|
||||
new_Faces[i].RebuildCaches();
|
||||
list4.Add(new_Faces[i]);
|
||||
if (new_SharedIndices != null && new_Vertices[i].Length != new_SharedIndices[i].Length)
|
||||
{
|
||||
Debug.LogError("Append Face failed because sharedIndex array does not match new vertex array.");
|
||||
return null;
|
||||
}
|
||||
if (new_SharedIndices != null)
|
||||
{
|
||||
for (int j = 0; j < new_SharedIndices[i].Length; j++)
|
||||
{
|
||||
pb_IntArrayUtility.AddValueAtIndex(ref sharedIndices, new_SharedIndices[i][j], j + num);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int k = 0; k < new_Vertices[i].Length; k++)
|
||||
{
|
||||
pb_IntArrayUtility.AddValueAtIndex(ref sharedIndices, -1, k + num);
|
||||
}
|
||||
}
|
||||
num = list.Count;
|
||||
}
|
||||
pb.SetSharedIndices(sharedIndices);
|
||||
pb.SetVertices(list.ToArray());
|
||||
pb.SetColors(list2.ToArray());
|
||||
pb.SetUV(list3.ToArray());
|
||||
pb.SetFaces(list4.ToArray());
|
||||
return new_Faces;
|
||||
}
|
||||
|
||||
// Token: 0x06000055 RID: 85 RVA: 0x000083C0 File Offset: 0x000067C0
|
||||
public static void DuplicateAndFlip(this pb_Object pb, pb_Face[] faces)
|
||||
{
|
||||
List<pb_FaceRebuildData> list = new List<pb_FaceRebuildData>();
|
||||
List<pb_Vertex> list2 = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
|
||||
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
||||
foreach (pb_Face pb_Face in faces)
|
||||
{
|
||||
pb_FaceRebuildData pb_FaceRebuildData = new pb_FaceRebuildData();
|
||||
pb_FaceRebuildData.vertices = new List<pb_Vertex>();
|
||||
pb_FaceRebuildData.face = new pb_Face(pb_Face);
|
||||
pb_FaceRebuildData.sharedIndices = new List<int>();
|
||||
Dictionary<int, int> dictionary2 = new Dictionary<int, int>();
|
||||
int num = pb_FaceRebuildData.face.indices.Length;
|
||||
for (int j = 0; j < num; j++)
|
||||
{
|
||||
if (!dictionary2.ContainsKey(pb_Face.indices[j]))
|
||||
{
|
||||
dictionary2.Add(pb_Face.indices[j], dictionary2.Count);
|
||||
pb_FaceRebuildData.vertices.Add(list2[pb_Face.indices[j]]);
|
||||
pb_FaceRebuildData.sharedIndices.Add(dictionary[pb_Face.indices[j]]);
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < num; k++)
|
||||
{
|
||||
pb_FaceRebuildData.face.indices[k] = dictionary2[pb_FaceRebuildData.face.indices[k]];
|
||||
}
|
||||
pb_FaceRebuildData.face.ReverseIndices();
|
||||
list.Add(pb_FaceRebuildData);
|
||||
}
|
||||
pb_FaceRebuildData.Apply(list, pb, list2, null, dictionary, null);
|
||||
}
|
||||
|
||||
// Token: 0x06000056 RID: 86 RVA: 0x0000852A File Offset: 0x0000692A
|
||||
public static int[] DeleteFace(this pb_Object pb, pb_Face face)
|
||||
{
|
||||
return pb.DeleteFaces(new pb_Face[] { face });
|
||||
}
|
||||
|
||||
// Token: 0x06000057 RID: 87 RVA: 0x0000853C File Offset: 0x0000693C
|
||||
public static int[] DeleteFaces(this pb_Object pb, IEnumerable<pb_Face> faces)
|
||||
{
|
||||
return pb.DeleteFaces(faces.Select((pb_Face x) => Array.IndexOf<pb_Face>(pb.faces, x)).ToList<int>());
|
||||
}
|
||||
|
||||
// Token: 0x06000058 RID: 88 RVA: 0x00008578 File Offset: 0x00006978
|
||||
public static int[] DeleteFaces(this pb_Object pb, IList<int> faceIndices)
|
||||
{
|
||||
pb_Face[] array = new pb_Face[faceIndices.Count];
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array[i] = pb.faces[faceIndices[i]];
|
||||
}
|
||||
List<int> list = array.SelectMany((pb_Face x) => x.distinctIndices).Distinct<int>().ToList<int>();
|
||||
list.Sort();
|
||||
int num = pb.vertices.Length;
|
||||
Vector3[] array2 = pb.vertices.SortedRemoveAt(list);
|
||||
Color[] array3 = pb.colors.SortedRemoveAt(list);
|
||||
Vector2[] array4 = pb.uv.SortedRemoveAt(list);
|
||||
pb_Face[] array5 = pb.faces.RemoveAt(faceIndices);
|
||||
Dictionary<int, int> dictionary = new Dictionary<int, int>();
|
||||
for (int j = 0; j < num; j++)
|
||||
{
|
||||
dictionary.Add(j, pbUtil.NearestIndexPriorToValue<int>(list, j) + 1);
|
||||
}
|
||||
for (int k = 0; k < array5.Length; k++)
|
||||
{
|
||||
int[] indices = array5[k].indices;
|
||||
for (int l = 0; l < indices.Length; l++)
|
||||
{
|
||||
indices[l] -= dictionary[indices[l]];
|
||||
}
|
||||
array5[k].SetIndices(indices);
|
||||
}
|
||||
pb_IntArray[] sharedIndices = pb.sharedIndices;
|
||||
pb_IntArray[] sharedIndicesUV = pb.sharedIndicesUV;
|
||||
pb_IntArrayUtility.RemoveValuesAndShift(ref sharedIndices, list);
|
||||
pb_IntArrayUtility.RemoveValuesAndShift(ref sharedIndicesUV, list);
|
||||
pb.SetSharedIndices(sharedIndices);
|
||||
pb.SetSharedIndicesUV(sharedIndicesUV);
|
||||
pb.SetVertices(array2);
|
||||
pb.SetColors(array3);
|
||||
pb.SetUV(array4);
|
||||
pb.SetFaces(array5);
|
||||
return list.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ProBuilder2.Common;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x02000009 RID: 9
|
||||
public static class pb_Bevel
|
||||
{
|
||||
// Token: 0x06000064 RID: 100 RVA: 0x00008F48 File Offset: 0x00007348
|
||||
public static pb_ActionResult BevelEdges(pb_Object pb, IList<pb_Edge> edges, float amount, out List<pb_Face> createdFaces)
|
||||
{
|
||||
createdFaces = null;
|
||||
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
||||
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
|
||||
List<pb_EdgeLookup> list2 = pb_EdgeLookup.GetEdgeLookup(edges, dictionary).Distinct<pb_EdgeLookup>().ToList<pb_EdgeLookup>();
|
||||
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, false);
|
||||
List<pb_FaceRebuildData> list3 = new List<pb_FaceRebuildData>();
|
||||
Dictionary<pb_Face, List<int>> ignore = new Dictionary<pb_Face, List<int>>();
|
||||
HashSet<int> hashSet = new HashSet<int>();
|
||||
int num = 0;
|
||||
Dictionary<int, List<pb_Tuple<pb_FaceRebuildData, List<int>>>> dictionary2 = new Dictionary<int, List<pb_Tuple<pb_FaceRebuildData, List<int>>>>();
|
||||
Dictionary<int, List<pb_WingedEdge>> spokes = pb_WingedEdge.GetSpokes(wingedEdges);
|
||||
HashSet<int> hashSet2 = new HashSet<int>();
|
||||
foreach (pb_EdgeLookup pb_EdgeLookup in list2)
|
||||
{
|
||||
if (hashSet2.Add(pb_EdgeLookup.common.x))
|
||||
{
|
||||
foreach (pb_WingedEdge pb_WingedEdge in spokes[pb_EdgeLookup.common.x])
|
||||
{
|
||||
pb_Edge local = pb_WingedEdge.edge.local;
|
||||
amount = Mathf.Min(Vector3.Distance(list[local.x].position, list[local.y].position) - 0.001f, amount);
|
||||
}
|
||||
}
|
||||
if (hashSet2.Add(pb_EdgeLookup.common.y))
|
||||
{
|
||||
foreach (pb_WingedEdge pb_WingedEdge2 in spokes[pb_EdgeLookup.common.y])
|
||||
{
|
||||
pb_Edge local2 = pb_WingedEdge2.edge.local;
|
||||
amount = Mathf.Min(Vector3.Distance(list[local2.x].position, list[local2.y].position) - 0.001f, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (amount < 0.001f)
|
||||
{
|
||||
return new pb_ActionResult(Status.Canceled, "Bevel Distance > Available Surface");
|
||||
}
|
||||
using (List<pb_EdgeLookup>.Enumerator enumerator4 = list2.GetEnumerator())
|
||||
{
|
||||
while (enumerator4.MoveNext())
|
||||
{
|
||||
pb_EdgeLookup lup = enumerator4.Current;
|
||||
pb_WingedEdge pb_WingedEdge3 = wingedEdges.FirstOrDefault((pb_WingedEdge x) => x.edge.Equals(lup));
|
||||
if (pb_WingedEdge3 != null && pb_WingedEdge3.opposite != null)
|
||||
{
|
||||
num++;
|
||||
ignore.AddOrAppend(pb_WingedEdge3.face, pb_WingedEdge3.edge.common.x);
|
||||
ignore.AddOrAppend(pb_WingedEdge3.face, pb_WingedEdge3.edge.common.y);
|
||||
ignore.AddOrAppend(pb_WingedEdge3.opposite.face, pb_WingedEdge3.edge.common.x);
|
||||
ignore.AddOrAppend(pb_WingedEdge3.opposite.face, pb_WingedEdge3.edge.common.y);
|
||||
hashSet.Add(pb_WingedEdge3.edge.common.x);
|
||||
hashSet.Add(pb_WingedEdge3.edge.common.y);
|
||||
pb_Bevel.SlideEdge(list, pb_WingedEdge3, amount);
|
||||
pb_Bevel.SlideEdge(list, pb_WingedEdge3.opposite, amount);
|
||||
list3.AddRange(pb_Bevel.GetBridgeFaces(list, pb_WingedEdge3, pb_WingedEdge3.opposite, dictionary2));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num < 1)
|
||||
{
|
||||
createdFaces = null;
|
||||
return new pb_ActionResult(Status.Canceled, "Cannot Bevel Open Edges");
|
||||
}
|
||||
createdFaces = new List<pb_Face>(list3.Select((pb_FaceRebuildData x) => x.face));
|
||||
Dictionary<pb_Face, List<pb_Tuple<pb_WingedEdge, int>>> dictionary3 = new Dictionary<pb_Face, List<pb_Tuple<pb_WingedEdge, int>>>();
|
||||
using (HashSet<int>.Enumerator enumerator5 = hashSet.GetEnumerator())
|
||||
{
|
||||
while (enumerator5.MoveNext())
|
||||
{
|
||||
int c = enumerator5.Current;
|
||||
IEnumerable<pb_WingedEdge> enumerable = wingedEdges.Where((pb_WingedEdge x) => x.edge.common.Contains(c) && (!ignore.ContainsKey(x.face) || !ignore[x.face].Contains(c)));
|
||||
HashSet<pb_Face> hashSet3 = new HashSet<pb_Face>();
|
||||
foreach (pb_WingedEdge pb_WingedEdge4 in enumerable)
|
||||
{
|
||||
if (hashSet3.Add(pb_WingedEdge4.face))
|
||||
{
|
||||
dictionary3.AddOrAppend(pb_WingedEdge4.face, new pb_Tuple<pb_WingedEdge, int>(pb_WingedEdge4, c));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (KeyValuePair<pb_Face, List<pb_Tuple<pb_WingedEdge, int>>> keyValuePair in dictionary3)
|
||||
{
|
||||
Dictionary<int, List<int>> dictionary4;
|
||||
pb_FaceRebuildData pb_FaceRebuildData = pbVertexOps.ExplodeVertex(list, keyValuePair.Value, amount, out dictionary4);
|
||||
if (pb_FaceRebuildData != null)
|
||||
{
|
||||
list3.Add(pb_FaceRebuildData);
|
||||
foreach (KeyValuePair<int, List<int>> keyValuePair2 in dictionary4)
|
||||
{
|
||||
dictionary2.AddOrAppend(keyValuePair2.Key, new pb_Tuple<pb_FaceRebuildData, List<int>>(pb_FaceRebuildData, keyValuePair2.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
pb_FaceRebuildData.Apply(list3, pb, list, null, null, null);
|
||||
int num2 = pb.DeleteFaces(dictionary3.Keys).Length;
|
||||
pb.SetSharedIndicesUV(new pb_IntArray[0]);
|
||||
pb.SetSharedIndices(pb_IntArrayUtility.ExtractSharedIndices(pb.vertices));
|
||||
pb_IntArray[] sharedIndices = pb.sharedIndices;
|
||||
dictionary = sharedIndices.ToDictionary();
|
||||
List<HashSet<int>> list4 = new List<HashSet<int>>();
|
||||
foreach (KeyValuePair<int, List<pb_Tuple<pb_FaceRebuildData, List<int>>>> keyValuePair3 in dictionary2)
|
||||
{
|
||||
if (keyValuePair3.Value.Sum((pb_Tuple<pb_FaceRebuildData, List<int>> x) => x.Item2.Count) >= 3)
|
||||
{
|
||||
HashSet<int> hashSet4 = new HashSet<int>();
|
||||
foreach (pb_Tuple<pb_FaceRebuildData, List<int>> pb_Tuple in keyValuePair3.Value)
|
||||
{
|
||||
int num3 = pb_Tuple.Item1.Offset() - num2;
|
||||
for (int i = 0; i < pb_Tuple.Item2.Count; i++)
|
||||
{
|
||||
hashSet4.Add(dictionary[pb_Tuple.Item2[i] + num3]);
|
||||
}
|
||||
}
|
||||
list4.Add(hashSet4);
|
||||
}
|
||||
}
|
||||
List<pb_WingedEdge> wingedEdges2 = pb_WingedEdge.GetWingedEdges(pb, list3.Select((pb_FaceRebuildData x) => x.face), false, null);
|
||||
list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
|
||||
List<pb_FaceRebuildData> list5 = new List<pb_FaceRebuildData>();
|
||||
foreach (HashSet<int> hashSet5 in list4)
|
||||
{
|
||||
if (hashSet5.Count >= 3)
|
||||
{
|
||||
if (hashSet5.Count < 4)
|
||||
{
|
||||
List<pb_Vertex> list6 = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, hashSet5.Select((int x) => sharedIndices[x][0]).ToList<int>()));
|
||||
list5.Add(pb_AppendPolygon.FaceWithVertices(list6, true));
|
||||
}
|
||||
else
|
||||
{
|
||||
List<int> list7 = pb_WingedEdge.SortCommonIndicesByAdjacency(wingedEdges2, hashSet5);
|
||||
List<pb_Vertex> list8 = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, list7.Select((int x) => sharedIndices[x][0]).ToList<int>()));
|
||||
list5.AddRange(pb_AppendPolygon.TentCapWithVertices(list8));
|
||||
}
|
||||
}
|
||||
}
|
||||
pb_FaceRebuildData.Apply(list5, pb, list, null, null, null);
|
||||
pb.SetSharedIndices(pb_IntArrayUtility.ExtractSharedIndices(pb.vertices));
|
||||
HashSet<pb_Face> hashSet6 = new HashSet<pb_Face>(list5.Select((pb_FaceRebuildData x) => x.face));
|
||||
list3.AddRange(list5);
|
||||
List<pb_WingedEdge> wingedEdges3 = pb_WingedEdge.GetWingedEdges(pb, list3.Select((pb_FaceRebuildData x) => x.face), false, null);
|
||||
int num4 = 0;
|
||||
while (num4 < wingedEdges3.Count && hashSet6.Count > 0)
|
||||
{
|
||||
pb_WingedEdge pb_WingedEdge5 = wingedEdges3[num4];
|
||||
if (hashSet6.Contains(pb_WingedEdge5.face))
|
||||
{
|
||||
hashSet6.Remove(pb_WingedEdge5.face);
|
||||
pb_WingedEdgeEnumerator enumerator12 = pb_WingedEdge5.GetEnumerator();
|
||||
try
|
||||
{
|
||||
while (enumerator12.MoveNext())
|
||||
{
|
||||
pb_WingedEdge pb_WingedEdge6 = enumerator12.Current;
|
||||
if (!hashSet6.Contains(pb_WingedEdge6.opposite.face))
|
||||
{
|
||||
pb_WingedEdge6.face.material = pb_WingedEdge6.opposite.face.material;
|
||||
pb_WingedEdge6.face.uv = new pb_UV(pb_WingedEdge6.opposite.face.uv);
|
||||
pb_ConformNormals.ConformOppositeNormal(pb_WingedEdge6.opposite);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
IDisposable disposable;
|
||||
if ((disposable = enumerator12 as IDisposable) != null)
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
num4++;
|
||||
}
|
||||
pb.ToMesh();
|
||||
return new pb_ActionResult(Status.Success, "Bevel Edges");
|
||||
}
|
||||
|
||||
// Token: 0x06000065 RID: 101 RVA: 0x000099B0 File Offset: 0x00007DB0
|
||||
private static List<pb_FaceRebuildData> GetBridgeFaces(IList<pb_Vertex> vertices, pb_WingedEdge left, pb_WingedEdge right, Dictionary<int, List<pb_Tuple<pb_FaceRebuildData, List<int>>>> holes)
|
||||
{
|
||||
List<pb_FaceRebuildData> list = new List<pb_FaceRebuildData>();
|
||||
pb_FaceRebuildData pb_FaceRebuildData = new pb_FaceRebuildData();
|
||||
pb_EdgeLookup edge = left.edge;
|
||||
pb_EdgeLookup edge2 = right.edge;
|
||||
pb_FaceRebuildData.vertices = new List<pb_Vertex>
|
||||
{
|
||||
vertices[edge.local.x],
|
||||
vertices[edge.local.y],
|
||||
vertices[(edge.common.x != edge2.common.x) ? edge2.local.y : edge2.local.x],
|
||||
vertices[(edge.common.x != edge2.common.x) ? edge2.local.x : edge2.local.y]
|
||||
};
|
||||
Vector3 vector = pb_Math.Normal(vertices, left.face.indices);
|
||||
Vector3 vector2 = pb_Math.Normal(pb_FaceRebuildData.vertices, pb_Bevel.BRIDGE_INDICES_NRM);
|
||||
int[] array = new int[] { 2, 1, 0, 2, 3, 1 };
|
||||
if (Vector3.Dot(vector, vector2) < 0f)
|
||||
{
|
||||
Array.Reverse(array);
|
||||
}
|
||||
pb_FaceRebuildData.face = new pb_Face(array, left.face.material, new pb_UV(), -1, -1, -1, false);
|
||||
list.Add(pb_FaceRebuildData);
|
||||
holes.AddOrAppend(edge.common.x, new pb_Tuple<pb_FaceRebuildData, List<int>>(pb_FaceRebuildData, new List<int> { 0, 2 }));
|
||||
holes.AddOrAppend(edge.common.y, new pb_Tuple<pb_FaceRebuildData, List<int>>(pb_FaceRebuildData, new List<int> { 1, 3 }));
|
||||
return list;
|
||||
}
|
||||
|
||||
// Token: 0x06000066 RID: 102 RVA: 0x00009B78 File Offset: 0x00007F78
|
||||
private static void SlideEdge(IList<pb_Vertex> vertices, pb_WingedEdge we, float amount)
|
||||
{
|
||||
we.face.manualUV = true;
|
||||
we.face.textureGroup = -1;
|
||||
pb_Edge leadingEdge = pb_Bevel.GetLeadingEdge(we, we.edge.common.x);
|
||||
pb_Edge leadingEdge2 = pb_Bevel.GetLeadingEdge(we, we.edge.common.y);
|
||||
if (leadingEdge == null || leadingEdge2 == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pb_Vertex pb_Vertex = vertices[leadingEdge.x] - vertices[leadingEdge.y];
|
||||
pb_Vertex.Normalize();
|
||||
pb_Vertex pb_Vertex2 = vertices[leadingEdge2.x] - vertices[leadingEdge2.y];
|
||||
pb_Vertex2.Normalize();
|
||||
vertices[we.edge.local.x].Add(pb_Vertex * amount);
|
||||
vertices[we.edge.local.y].Add(pb_Vertex2 * amount);
|
||||
}
|
||||
|
||||
// Token: 0x06000067 RID: 103 RVA: 0x00009C64 File Offset: 0x00008064
|
||||
private static pb_Edge GetLeadingEdge(pb_WingedEdge wing, int common)
|
||||
{
|
||||
if (wing.previous.edge.common.x == common)
|
||||
{
|
||||
return new pb_Edge(wing.previous.edge.local.y, wing.previous.edge.local.x);
|
||||
}
|
||||
if (wing.previous.edge.common.y == common)
|
||||
{
|
||||
return new pb_Edge(wing.previous.edge.local.x, wing.previous.edge.local.y);
|
||||
}
|
||||
if (wing.next.edge.common.x == common)
|
||||
{
|
||||
return new pb_Edge(wing.next.edge.local.y, wing.next.edge.local.x);
|
||||
}
|
||||
if (wing.next.edge.common.y == common)
|
||||
{
|
||||
return new pb_Edge(wing.next.edge.local.x, wing.next.edge.local.y);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Token: 0x06000068 RID: 104 RVA: 0x00009D9E File Offset: 0x0000819E
|
||||
// Note: this type is marked as 'beforefieldinit'.
|
||||
static pb_Bevel()
|
||||
{
|
||||
int[] array = new int[3];
|
||||
array[0] = 2;
|
||||
array[1] = 1;
|
||||
pb_Bevel.BRIDGE_INDICES_NRM = array;
|
||||
}
|
||||
|
||||
// Token: 0x04000017 RID: 23
|
||||
private static readonly int[] BRIDGE_INDICES_NRM;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ProBuilder2.Common;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x0200000A RID: 10
|
||||
public static class pb_ConformNormals
|
||||
{
|
||||
// Token: 0x0600006E RID: 110 RVA: 0x00009E9C File Offset: 0x0000829C
|
||||
public static pb_ActionResult ConformNormals(this pb_Object pb, IList<pb_Face> faces)
|
||||
{
|
||||
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, faces, false, null);
|
||||
HashSet<pb_Face> hashSet = new HashSet<pb_Face>();
|
||||
int num = 0;
|
||||
for (int i = 0; i < wingedEdges.Count; i++)
|
||||
{
|
||||
if (!hashSet.Contains(wingedEdges[i].face))
|
||||
{
|
||||
Dictionary<pb_Face, bool> dictionary = new Dictionary<pb_Face, bool>();
|
||||
pb_ConformNormals.GetWindingFlags(wingedEdges[i], true, dictionary);
|
||||
int num2 = 0;
|
||||
foreach (KeyValuePair<pb_Face, bool> keyValuePair in dictionary)
|
||||
{
|
||||
num2 += ((!keyValuePair.Value) ? (-1) : 1);
|
||||
}
|
||||
bool flag = num2 > 0;
|
||||
foreach (KeyValuePair<pb_Face, bool> keyValuePair2 in dictionary)
|
||||
{
|
||||
if (flag != keyValuePair2.Value)
|
||||
{
|
||||
num++;
|
||||
keyValuePair2.Key.ReverseIndices();
|
||||
}
|
||||
}
|
||||
hashSet.UnionWith(dictionary.Keys);
|
||||
}
|
||||
}
|
||||
if (num > 0)
|
||||
{
|
||||
return new pb_ActionResult(Status.Success, (num <= 1) ? "Flipped 1 face" : string.Format("Flipped {0} faces", num));
|
||||
}
|
||||
return new pb_ActionResult(Status.NoChange, "Faces Uniform");
|
||||
}
|
||||
|
||||
// Token: 0x0600006F RID: 111 RVA: 0x0000A014 File Offset: 0x00008414
|
||||
private static void GetWindingFlags(pb_WingedEdge edge, bool flag, Dictionary<pb_Face, bool> flags)
|
||||
{
|
||||
flags.Add(edge.face, flag);
|
||||
pb_WingedEdge pb_WingedEdge = edge;
|
||||
do
|
||||
{
|
||||
pb_WingedEdge opposite = pb_WingedEdge.opposite;
|
||||
if (opposite != null && !flags.ContainsKey(opposite.face))
|
||||
{
|
||||
pb_Edge commonEdgeInWindingOrder = pb_ConformNormals.GetCommonEdgeInWindingOrder(pb_WingedEdge);
|
||||
pb_Edge commonEdgeInWindingOrder2 = pb_ConformNormals.GetCommonEdgeInWindingOrder(opposite);
|
||||
pb_ConformNormals.GetWindingFlags(opposite, (commonEdgeInWindingOrder.x != commonEdgeInWindingOrder2.x) ? flag : (!flag), flags);
|
||||
}
|
||||
pb_WingedEdge = pb_WingedEdge.next;
|
||||
}
|
||||
while (pb_WingedEdge != edge);
|
||||
}
|
||||
|
||||
// Token: 0x06000070 RID: 112 RVA: 0x0000A08C File Offset: 0x0000848C
|
||||
public static pb_ActionResult ConformOppositeNormal(pb_WingedEdge source)
|
||||
{
|
||||
if (source == null || source.opposite == null)
|
||||
{
|
||||
return new pb_ActionResult(Status.Failure, "Source edge does not share an edge with another face.");
|
||||
}
|
||||
pb_Edge commonEdgeInWindingOrder = pb_ConformNormals.GetCommonEdgeInWindingOrder(source);
|
||||
pb_Edge commonEdgeInWindingOrder2 = pb_ConformNormals.GetCommonEdgeInWindingOrder(source.opposite);
|
||||
if (commonEdgeInWindingOrder.x == commonEdgeInWindingOrder2.x)
|
||||
{
|
||||
source.opposite.face.ReverseIndices();
|
||||
return new pb_ActionResult(Status.Success, "Reversed target face winding order.");
|
||||
}
|
||||
return new pb_ActionResult(Status.NoChange, "Faces already unified.");
|
||||
}
|
||||
|
||||
// Token: 0x06000071 RID: 113 RVA: 0x0000A104 File Offset: 0x00008504
|
||||
private static pb_Edge GetCommonEdgeInWindingOrder(pb_WingedEdge wing)
|
||||
{
|
||||
int[] indices = wing.face.indices;
|
||||
int num = indices.Length;
|
||||
for (int i = 0; i < num; i += 3)
|
||||
{
|
||||
pb_Edge local = wing.edge.local;
|
||||
int num2 = indices[i];
|
||||
int num3 = indices[i + 1];
|
||||
int num4 = indices[i + 2];
|
||||
if (local.x == num2 && local.y == num3)
|
||||
{
|
||||
return new pb_Edge(wing.edge.common);
|
||||
}
|
||||
if (local.x == num3 && local.y == num2)
|
||||
{
|
||||
return new pb_Edge(wing.edge.common.y, wing.edge.common.x);
|
||||
}
|
||||
if (local.x == num3 && local.y == num4)
|
||||
{
|
||||
return new pb_Edge(wing.edge.common);
|
||||
}
|
||||
if (local.x == num4 && local.y == num3)
|
||||
{
|
||||
return new pb_Edge(wing.edge.common.y, wing.edge.common.x);
|
||||
}
|
||||
if (local.x == num4 && local.y == num2)
|
||||
{
|
||||
return new pb_Edge(wing.edge.common);
|
||||
}
|
||||
if (local.x == num2 && local.y == num4)
|
||||
{
|
||||
return new pb_Edge(wing.edge.common.y, wing.edge.common.x);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Token: 0x06000072 RID: 114 RVA: 0x0000A294 File Offset: 0x00008694
|
||||
public static void MatchNormal(pb_Face source, pb_Face target, Dictionary<int, int> lookup)
|
||||
{
|
||||
List<pb_EdgeLookup> list = pb_EdgeLookup.GetEdgeLookup(source.edges, lookup).ToList<pb_EdgeLookup>();
|
||||
List<pb_EdgeLookup> list2 = pb_EdgeLookup.GetEdgeLookup(target.edges, lookup).ToList<pb_EdgeLookup>();
|
||||
bool flag = false;
|
||||
int num = 0;
|
||||
while (!flag && num < list.Count)
|
||||
{
|
||||
pb_Edge common = list[num].common;
|
||||
int num2 = 0;
|
||||
while (!flag && num2 < list2.Count)
|
||||
{
|
||||
pb_Edge common2 = list2[num2].common;
|
||||
if (common.Equals(common2))
|
||||
{
|
||||
if (common.x == common2.x)
|
||||
{
|
||||
target.ReverseIndices();
|
||||
}
|
||||
flag = true;
|
||||
}
|
||||
num2++;
|
||||
}
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ProBuilder2.Common;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x0200000C RID: 12
|
||||
public static class pb_ConnectEdges
|
||||
{
|
||||
// Token: 0x06000074 RID: 116 RVA: 0x0000A364 File Offset: 0x00008764
|
||||
public static pb_ActionResult Connect(this pb_Object pb, IEnumerable<pb_Face> faces, out pb_Face[] subdividedFaces)
|
||||
{
|
||||
IEnumerable<pb_Edge> enumerable = faces.SelectMany((pb_Face x) => x.edges);
|
||||
HashSet<pb_Face> hashSet = new HashSet<pb_Face>(faces);
|
||||
pb_Edge[] array;
|
||||
return pb.Connect(enumerable, out subdividedFaces, out array, true, false, hashSet);
|
||||
}
|
||||
|
||||
// Token: 0x06000075 RID: 117 RVA: 0x0000A3AC File Offset: 0x000087AC
|
||||
public static pb_ActionResult Connect(this pb_Object pb, IEnumerable<pb_Edge> edges, out pb_Face[] faces)
|
||||
{
|
||||
pb_Edge[] array;
|
||||
return pb.Connect(edges, out faces, out array, true, false, null);
|
||||
}
|
||||
|
||||
// Token: 0x06000076 RID: 118 RVA: 0x0000A3C8 File Offset: 0x000087C8
|
||||
public static pb_ActionResult Connect(this pb_Object pb, IEnumerable<pb_Edge> edges, out pb_Edge[] connections)
|
||||
{
|
||||
pb_Face[] array;
|
||||
return pb.Connect(edges, out array, out connections, false, true, null);
|
||||
}
|
||||
|
||||
// Token: 0x06000077 RID: 119 RVA: 0x0000A3E4 File Offset: 0x000087E4
|
||||
private static pb_ActionResult Connect(this pb_Object pb, IEnumerable<pb_Edge> edges, out pb_Face[] addedFaces, out pb_Edge[] connections, bool returnFaces = false, bool returnEdges = false, HashSet<pb_Face> faceMask = null)
|
||||
{
|
||||
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
||||
Dictionary<int, int> dictionary2 = ((pb.sharedIndicesUV == null) ? null : pb.sharedIndicesUV.ToDictionary());
|
||||
HashSet<pb_EdgeLookup> hashSet = new HashSet<pb_EdgeLookup>(pb_EdgeLookup.GetEdgeLookup(edges, dictionary));
|
||||
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, false);
|
||||
Dictionary<pb_Face, List<pb_WingedEdge>> dictionary3 = new Dictionary<pb_Face, List<pb_WingedEdge>>();
|
||||
foreach (pb_WingedEdge pb_WingedEdge in wingedEdges)
|
||||
{
|
||||
if (hashSet.Contains(pb_WingedEdge.edge))
|
||||
{
|
||||
List<pb_WingedEdge> list;
|
||||
if (dictionary3.TryGetValue(pb_WingedEdge.face, out list))
|
||||
{
|
||||
list.Add(pb_WingedEdge);
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary3.Add(pb_WingedEdge.face, new List<pb_WingedEdge> { pb_WingedEdge });
|
||||
}
|
||||
}
|
||||
}
|
||||
Dictionary<pb_Face, List<pb_WingedEdge>> dictionary4 = new Dictionary<pb_Face, List<pb_WingedEdge>>();
|
||||
foreach (KeyValuePair<pb_Face, List<pb_WingedEdge>> keyValuePair in dictionary3)
|
||||
{
|
||||
if (keyValuePair.Value.Count <= 1)
|
||||
{
|
||||
pb_WingedEdge opposite = keyValuePair.Value[0].opposite;
|
||||
if (opposite == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
List<pb_WingedEdge> list2;
|
||||
if (!dictionary3.TryGetValue(opposite.face, out list2))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (list2.Count <= 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
dictionary4.Add(keyValuePair.Key, keyValuePair.Value);
|
||||
}
|
||||
List<pb_Vertex> list3 = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
|
||||
List<ConnectFaceRebuildData> list4 = new List<ConnectFaceRebuildData>();
|
||||
List<pb_Face> list5 = new List<pb_Face>();
|
||||
HashSet<int> hashSet2 = new HashSet<int>(pb.faces.Select((pb_Face x) => x.textureGroup));
|
||||
int num = 1;
|
||||
foreach (KeyValuePair<pb_Face, List<pb_WingedEdge>> keyValuePair2 in dictionary4)
|
||||
{
|
||||
pb_Face key = keyValuePair2.Key;
|
||||
List<pb_WingedEdge> value = keyValuePair2.Value;
|
||||
int count = value.Count;
|
||||
Vector3 vector = pb_Math.Normal(list3, key.indices);
|
||||
if (count == 1 || (faceMask != null && !faceMask.Contains(key)))
|
||||
{
|
||||
ConnectFaceRebuildData connectFaceRebuildData = pb_ConnectEdges.InsertVertices(key, value, list3);
|
||||
Vector3 vector2 = pb_Math.Normal(connectFaceRebuildData.faceRebuildData.vertices, connectFaceRebuildData.faceRebuildData.face.indices);
|
||||
if (Vector3.Dot(vector, vector2) < 0f)
|
||||
{
|
||||
connectFaceRebuildData.faceRebuildData.face.ReverseIndices();
|
||||
}
|
||||
list4.Add(connectFaceRebuildData);
|
||||
}
|
||||
else if (count > 1)
|
||||
{
|
||||
List<ConnectFaceRebuildData> list6 = ((count != 2) ? pb_ConnectEdges.ConnectEdgesInFace(key, value, list3) : pb_ConnectEdges.ConnectEdgesInFace(key, value[0], value[1], list3));
|
||||
if (key.textureGroup < 0)
|
||||
{
|
||||
while (hashSet2.Contains(num))
|
||||
{
|
||||
num++;
|
||||
}
|
||||
hashSet2.Add(num);
|
||||
}
|
||||
foreach (ConnectFaceRebuildData connectFaceRebuildData2 in list6)
|
||||
{
|
||||
list5.Add(connectFaceRebuildData2.faceRebuildData.face);
|
||||
Vector3 vector3 = pb_Math.Normal(connectFaceRebuildData2.faceRebuildData.vertices, connectFaceRebuildData2.faceRebuildData.face.indices);
|
||||
if (Vector3.Dot(vector, vector3) < 0f)
|
||||
{
|
||||
connectFaceRebuildData2.faceRebuildData.face.ReverseIndices();
|
||||
}
|
||||
connectFaceRebuildData2.faceRebuildData.face.textureGroup = ((key.textureGroup >= 0) ? key.textureGroup : num);
|
||||
connectFaceRebuildData2.faceRebuildData.face.uv = new pb_UV(key.uv);
|
||||
connectFaceRebuildData2.faceRebuildData.face.smoothingGroup = key.smoothingGroup;
|
||||
connectFaceRebuildData2.faceRebuildData.face.manualUV = key.manualUV;
|
||||
connectFaceRebuildData2.faceRebuildData.face.material = key.material;
|
||||
}
|
||||
list4.AddRange(list6);
|
||||
}
|
||||
}
|
||||
pb_FaceRebuildData.Apply(list4.Select((ConnectFaceRebuildData x) => x.faceRebuildData), pb, list3, null, dictionary, dictionary2);
|
||||
pb.SetSharedIndicesUV(new pb_IntArray[0]);
|
||||
int num2 = pb.DeleteFaces(dictionary4.Keys).Length;
|
||||
pb.SetSharedIndices(pb_IntArrayUtility.ExtractSharedIndices(pb.vertices));
|
||||
pb.ToMesh();
|
||||
if (returnEdges)
|
||||
{
|
||||
HashSet<int> appendedIndices = new HashSet<int>();
|
||||
for (int i = 0; i < list4.Count; i++)
|
||||
{
|
||||
for (int j = 0; j < list4[i].newVertexIndices.Count; j++)
|
||||
{
|
||||
appendedIndices.Add(list4[i].newVertexIndices[j] + list4[i].faceRebuildData.Offset() - num2);
|
||||
}
|
||||
}
|
||||
Dictionary<int, int> dictionary5 = pb.sharedIndices.ToDictionary();
|
||||
IEnumerable<pb_Edge> enumerable = from x in list4.SelectMany((ConnectFaceRebuildData x) => x.faceRebuildData.face.edges)
|
||||
where appendedIndices.Contains(x.x) && appendedIndices.Contains(x.y)
|
||||
select x;
|
||||
IEnumerable<pb_EdgeLookup> edgeLookup = pb_EdgeLookup.GetEdgeLookup(enumerable, dictionary5);
|
||||
connections = (from x in edgeLookup.Distinct<pb_EdgeLookup>()
|
||||
select x.local).ToArray<pb_Edge>();
|
||||
}
|
||||
else
|
||||
{
|
||||
connections = null;
|
||||
}
|
||||
if (returnFaces)
|
||||
{
|
||||
addedFaces = list5.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
addedFaces = null;
|
||||
}
|
||||
return new pb_ActionResult(Status.Success, string.Format("Connected {0} Edges", list4.Count));
|
||||
}
|
||||
|
||||
// Token: 0x06000078 RID: 120 RVA: 0x0000AA50 File Offset: 0x00008E50
|
||||
private static List<ConnectFaceRebuildData> ConnectEdgesInFace(pb_Face face, pb_WingedEdge a, pb_WingedEdge b, List<pb_Vertex> vertices)
|
||||
{
|
||||
List<pb_Edge> list = pb_WingedEdge.SortEdgesByAdjacency(face);
|
||||
List<pb_Vertex>[] array = new List<pb_Vertex>[]
|
||||
{
|
||||
new List<pb_Vertex>(),
|
||||
new List<pb_Vertex>()
|
||||
};
|
||||
List<int>[] array2 = new List<int>[]
|
||||
{
|
||||
new List<int>(),
|
||||
new List<int>()
|
||||
};
|
||||
int num = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
array[num % 2].Add(vertices[list[i].x]);
|
||||
if (list[i].Equals(a.edge.local) || list[i].Equals(b.edge.local))
|
||||
{
|
||||
pb_Vertex pb_Vertex = pb_Vertex.Mix(vertices[list[i].x], vertices[list[i].y], 0.5f);
|
||||
array2[num % 2].Add(array[num % 2].Count);
|
||||
array[num % 2].Add(pb_Vertex);
|
||||
num++;
|
||||
array2[num % 2].Add(array[num % 2].Count);
|
||||
array[num % 2].Add(pb_Vertex);
|
||||
}
|
||||
}
|
||||
List<ConnectFaceRebuildData> list2 = new List<ConnectFaceRebuildData>();
|
||||
for (int j = 0; j < array.Length; j++)
|
||||
{
|
||||
pb_FaceRebuildData pb_FaceRebuildData = pb_AppendPolygon.FaceWithVertices(array[j], false);
|
||||
list2.Add(new ConnectFaceRebuildData(pb_FaceRebuildData, array2[j]));
|
||||
}
|
||||
return list2;
|
||||
}
|
||||
|
||||
// Token: 0x06000079 RID: 121 RVA: 0x0000ABBC File Offset: 0x00008FBC
|
||||
private static List<ConnectFaceRebuildData> ConnectEdgesInFace(pb_Face face, List<pb_WingedEdge> edges, List<pb_Vertex> vertices)
|
||||
{
|
||||
List<pb_Edge> list = pb_WingedEdge.SortEdgesByAdjacency(face);
|
||||
int count = edges.Count;
|
||||
pb_Vertex pb_Vertex = pb_Vertex.Average(vertices, face.distinctIndices);
|
||||
List<List<pb_Vertex>> list2 = pbUtil.Fill<List<pb_Vertex>>((int x) => new List<pb_Vertex>(), count);
|
||||
List<List<int>> list3 = pbUtil.Fill<List<int>>((int x) => new List<int>(), count);
|
||||
HashSet<pb_Edge> hashSet = new HashSet<pb_Edge>(edges.Select((pb_WingedEdge x) => x.edge.local));
|
||||
int num = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
list2[num % count].Add(vertices[list[i].x]);
|
||||
if (hashSet.Contains(list[i]))
|
||||
{
|
||||
pb_Vertex pb_Vertex2 = pb_Vertex.Mix(vertices[list[i].x], vertices[list[i].y], 0.5f);
|
||||
list3[num].Add(list2[num].Count);
|
||||
list2[num].Add(pb_Vertex2);
|
||||
list3[num].Add(list2[num].Count);
|
||||
list2[num].Add(pb_Vertex);
|
||||
num = (num + 1) % count;
|
||||
list2[num].Add(pb_Vertex2);
|
||||
}
|
||||
}
|
||||
List<ConnectFaceRebuildData> list4 = new List<ConnectFaceRebuildData>();
|
||||
for (int j = 0; j < list2.Count; j++)
|
||||
{
|
||||
pb_FaceRebuildData pb_FaceRebuildData = pb_AppendPolygon.FaceWithVertices(list2[j], false);
|
||||
list4.Add(new ConnectFaceRebuildData(pb_FaceRebuildData, list3[j]));
|
||||
}
|
||||
return list4;
|
||||
}
|
||||
|
||||
// Token: 0x0600007A RID: 122 RVA: 0x0000AD94 File Offset: 0x00009194
|
||||
private static ConnectFaceRebuildData InsertVertices(pb_Face face, List<pb_WingedEdge> edges, List<pb_Vertex> vertices)
|
||||
{
|
||||
List<pb_Edge> list = pb_WingedEdge.SortEdgesByAdjacency(face);
|
||||
List<pb_Vertex> list2 = new List<pb_Vertex>();
|
||||
List<int> list3 = new List<int>();
|
||||
HashSet<pb_Edge> hashSet = new HashSet<pb_Edge>(edges.Select((pb_WingedEdge x) => x.edge.local));
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
list2.Add(vertices[list[i].x]);
|
||||
if (hashSet.Contains(list[i]))
|
||||
{
|
||||
list3.Add(list2.Count);
|
||||
list2.Add(pb_Vertex.Mix(vertices[list[i].x], vertices[list[i].y], 0.5f));
|
||||
}
|
||||
}
|
||||
pb_FaceRebuildData pb_FaceRebuildData = pb_AppendPolygon.FaceWithVertices(list2, false);
|
||||
pb_FaceRebuildData.face.textureGroup = face.textureGroup;
|
||||
pb_FaceRebuildData.face.uv = new pb_UV(face.uv);
|
||||
pb_FaceRebuildData.face.smoothingGroup = face.smoothingGroup;
|
||||
pb_FaceRebuildData.face.manualUV = face.manualUV;
|
||||
pb_FaceRebuildData.face.material = face.material;
|
||||
return new ConnectFaceRebuildData(pb_FaceRebuildData, list3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ProBuilder2.Common;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x0200000D RID: 13
|
||||
public static class pb_ConnectVertices
|
||||
{
|
||||
// Token: 0x06000084 RID: 132 RVA: 0x0000AF64 File Offset: 0x00009364
|
||||
public static pb_ActionResult Connect(this pb_Object pb, IList<int> indices, out int[] newVertices)
|
||||
{
|
||||
int num = pb.sharedIndices.Length;
|
||||
Dictionary<int, int> lookup = pb.sharedIndices.ToDictionary();
|
||||
HashSet<int> hashSet = new HashSet<int>(indices.Select((int x) => lookup[x]));
|
||||
HashSet<int> hashSet2 = new HashSet<int>();
|
||||
foreach (int num2 in hashSet)
|
||||
{
|
||||
hashSet2.UnionWith(pb.sharedIndices[num2].array);
|
||||
}
|
||||
Dictionary<pb_Face, List<int>> dictionary = new Dictionary<pb_Face, List<int>>();
|
||||
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
|
||||
foreach (pb_Face pb_Face in pb.faces)
|
||||
{
|
||||
int[] distinctIndices = pb_Face.distinctIndices;
|
||||
for (int j = 0; j < distinctIndices.Length; j++)
|
||||
{
|
||||
if (hashSet2.Contains(distinctIndices[j]))
|
||||
{
|
||||
dictionary.AddOrAppend(pb_Face, distinctIndices[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
List<ConnectFaceRebuildData> list2 = new List<ConnectFaceRebuildData>();
|
||||
List<pb_Face> list3 = new List<pb_Face>();
|
||||
HashSet<int> hashSet3 = new HashSet<int>(pb.faces.Select((pb_Face x) => x.textureGroup));
|
||||
int num3 = 1;
|
||||
foreach (KeyValuePair<pb_Face, List<int>> keyValuePair in dictionary)
|
||||
{
|
||||
pb_Face key = keyValuePair.Key;
|
||||
List<ConnectFaceRebuildData> list4 = ((keyValuePair.Value.Count != 2) ? pb_ConnectVertices.ConnectIndicesInFace(key, keyValuePair.Value, list, lookup, num++) : pb_ConnectVertices.ConnectIndicesInFace(key, keyValuePair.Value[0], keyValuePair.Value[1], list, lookup));
|
||||
if (list4 != null)
|
||||
{
|
||||
if (key.textureGroup < 0)
|
||||
{
|
||||
while (hashSet3.Contains(num3))
|
||||
{
|
||||
num3++;
|
||||
}
|
||||
hashSet3.Add(num3);
|
||||
}
|
||||
foreach (ConnectFaceRebuildData connectFaceRebuildData in list4)
|
||||
{
|
||||
connectFaceRebuildData.faceRebuildData.face.textureGroup = ((key.textureGroup >= 0) ? key.textureGroup : num3);
|
||||
connectFaceRebuildData.faceRebuildData.face.uv = new pb_UV(key.uv);
|
||||
connectFaceRebuildData.faceRebuildData.face.smoothingGroup = key.smoothingGroup;
|
||||
connectFaceRebuildData.faceRebuildData.face.manualUV = key.manualUV;
|
||||
connectFaceRebuildData.faceRebuildData.face.material = key.material;
|
||||
}
|
||||
list3.Add(key);
|
||||
list2.AddRange(list4);
|
||||
}
|
||||
}
|
||||
pb_FaceRebuildData.Apply(list2.Select((ConnectFaceRebuildData x) => x.faceRebuildData), pb, list, null, lookup, null);
|
||||
pb.SetSharedIndices(lookup);
|
||||
pb.SetSharedIndicesUV(new pb_IntArray[0]);
|
||||
int num4 = pb.DeleteFaces(list3).Length;
|
||||
lookup = pb.sharedIndices.ToDictionary();
|
||||
HashSet<int> hashSet4 = new HashSet<int>();
|
||||
for (int k = 0; k < list2.Count; k++)
|
||||
{
|
||||
for (int l = 0; l < list2[k].newVertexIndices.Count; l++)
|
||||
{
|
||||
hashSet4.Add(lookup[list2[k].newVertexIndices[l] + (list2[k].faceRebuildData.Offset() - num4)]);
|
||||
}
|
||||
}
|
||||
newVertices = hashSet4.Select((int x) => pb.sharedIndices[x][0]).ToArray<int>();
|
||||
pb.ToMesh();
|
||||
return new pb_ActionResult(Status.Success, string.Format("Connected {0} Vertices", hashSet.Count));
|
||||
}
|
||||
|
||||
// Token: 0x06000085 RID: 133 RVA: 0x0000B424 File Offset: 0x00009824
|
||||
private static List<ConnectFaceRebuildData> ConnectIndicesInFace(pb_Face face, int a, int b, List<pb_Vertex> vertices, Dictionary<int, int> lookup)
|
||||
{
|
||||
List<pb_Edge> list = pb_WingedEdge.SortEdgesByAdjacency(face);
|
||||
List<pb_Vertex>[] array = new List<pb_Vertex>[]
|
||||
{
|
||||
new List<pb_Vertex>(),
|
||||
new List<pb_Vertex>()
|
||||
};
|
||||
List<int>[] array2 = new List<int>[]
|
||||
{
|
||||
new List<int>(),
|
||||
new List<int>()
|
||||
};
|
||||
List<int>[] array3 = new List<int>[]
|
||||
{
|
||||
new List<int>(),
|
||||
new List<int>()
|
||||
};
|
||||
int num = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
if (list[i].Contains(a) && list[i].Contains(b))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int x = list[i].x;
|
||||
array[num].Add(vertices[x]);
|
||||
array2[num].Add(lookup[x]);
|
||||
if (x == a || x == b)
|
||||
{
|
||||
num = (num + 1) % 2;
|
||||
array3[num].Add(array[num].Count);
|
||||
array[num].Add(vertices[x]);
|
||||
array2[num].Add(lookup[x]);
|
||||
}
|
||||
}
|
||||
List<ConnectFaceRebuildData> list2 = new List<ConnectFaceRebuildData>();
|
||||
Vector3 vector = pb_Math.Normal(vertices, face.indices);
|
||||
for (int j = 0; j < array.Length; j++)
|
||||
{
|
||||
pb_FaceRebuildData pb_FaceRebuildData = pb_AppendPolygon.FaceWithVertices(array[j], false);
|
||||
pb_FaceRebuildData.sharedIndices = array2[j];
|
||||
Vector3 vector2 = pb_Math.Normal(array[j], pb_FaceRebuildData.face.indices);
|
||||
if (Vector3.Dot(vector, vector2) < 0f)
|
||||
{
|
||||
pb_FaceRebuildData.face.ReverseIndices();
|
||||
}
|
||||
list2.Add(new ConnectFaceRebuildData(pb_FaceRebuildData, array3[j]));
|
||||
}
|
||||
return list2;
|
||||
}
|
||||
|
||||
// Token: 0x06000086 RID: 134 RVA: 0x0000B5D0 File Offset: 0x000099D0
|
||||
private static List<ConnectFaceRebuildData> ConnectIndicesInFace(pb_Face face, List<int> indices, List<pb_Vertex> vertices, Dictionary<int, int> lookup, int sharedIndexOffset)
|
||||
{
|
||||
if (indices.Count < 3)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<pb_Edge> list = pb_WingedEdge.SortEdgesByAdjacency(face);
|
||||
int count = indices.Count;
|
||||
List<List<pb_Vertex>> list2 = pbUtil.Fill<List<pb_Vertex>>((int x) => new List<pb_Vertex>(), count);
|
||||
List<List<int>> list3 = pbUtil.Fill<List<int>>((int x) => new List<int>(), count);
|
||||
List<List<int>> list4 = pbUtil.Fill<List<int>>((int x) => new List<int>(), count);
|
||||
pb_Vertex pb_Vertex = pb_Vertex.Average(vertices, indices);
|
||||
Vector3 vector = pb_Math.Normal(vertices, face.indices);
|
||||
int num = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
int x2 = list[i].x;
|
||||
list2[num].Add(vertices[x2]);
|
||||
list3[num].Add(lookup[x2]);
|
||||
if (indices.Contains(x2))
|
||||
{
|
||||
list4[num].Add(list2[num].Count);
|
||||
list2[num].Add(pb_Vertex);
|
||||
list3[num].Add(sharedIndexOffset);
|
||||
num = (num + 1) % count;
|
||||
list4[num].Add(list2[num].Count);
|
||||
list2[num].Add(vertices[x2]);
|
||||
list3[num].Add(lookup[x2]);
|
||||
}
|
||||
}
|
||||
List<ConnectFaceRebuildData> list5 = new List<ConnectFaceRebuildData>();
|
||||
for (int j = 0; j < list2.Count; j++)
|
||||
{
|
||||
if (list2[j].Count >= 3)
|
||||
{
|
||||
pb_FaceRebuildData pb_FaceRebuildData = pb_AppendPolygon.FaceWithVertices(list2[j], false);
|
||||
pb_FaceRebuildData.sharedIndices = list3[j];
|
||||
Vector3 vector2 = pb_Math.Normal(list2[j], pb_FaceRebuildData.face.indices);
|
||||
if (Vector3.Dot(vector, vector2) < 0f)
|
||||
{
|
||||
pb_FaceRebuildData.face.ReverseIndices();
|
||||
}
|
||||
list5.Add(new ConnectFaceRebuildData(pb_FaceRebuildData, list4[j]));
|
||||
}
|
||||
}
|
||||
return list5;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ProBuilder2.Common;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x0200000E RID: 14
|
||||
public static class pb_DeleteVertices
|
||||
{
|
||||
// Token: 0x0600008C RID: 140 RVA: 0x0000B864 File Offset: 0x00009C64
|
||||
public static int[] RemoveUnusedVertices(this pb_Object pb)
|
||||
{
|
||||
List<int> list = new List<int>();
|
||||
HashSet<int> hashSet = new HashSet<int>(pb_Face.AllTriangles(pb.faces));
|
||||
for (int i = 0; i < pb.vertices.Length; i++)
|
||||
{
|
||||
if (!hashSet.Contains(i))
|
||||
{
|
||||
list.Add(i);
|
||||
}
|
||||
}
|
||||
pb.DeleteVerticesWithIndices(list);
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
// Token: 0x0600008D RID: 141 RVA: 0x0000B8C4 File Offset: 0x00009CC4
|
||||
public static void DeleteVerticesWithIndices(this pb_Object pb, IEnumerable<int> distInd)
|
||||
{
|
||||
if (distInd == null || distInd.Count<int>() < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pb_Vertex[] array = pb_Vertex.GetVertices(pb, null);
|
||||
int num = array.Length;
|
||||
int[] offset = new int[num];
|
||||
List<int> sorted = new List<int>(distInd);
|
||||
sorted.Sort();
|
||||
array = array.SortedRemoveAt(sorted);
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
offset[i] = pbUtil.NearestIndexPriorToValue<int>(sorted, i) + 1;
|
||||
}
|
||||
foreach (pb_Face pb_Face in pb.faces)
|
||||
{
|
||||
int[] indices = pb_Face.indices;
|
||||
for (int k = 0; k < indices.Length; k++)
|
||||
{
|
||||
indices[k] -= offset[indices[k]];
|
||||
}
|
||||
pb_Face.RebuildCaches();
|
||||
}
|
||||
IEnumerable<KeyValuePair<int, int>> enumerable = from x in pb.sharedIndices.ToDictionary()
|
||||
where sorted.BinarySearch(x.Key) < 0
|
||||
select x into y
|
||||
select new KeyValuePair<int, int>(y.Key - offset[y.Key], y.Value);
|
||||
IEnumerable<KeyValuePair<int, int>> enumerable2 = from x in pb.sharedIndicesUV.ToDictionary()
|
||||
where sorted.BinarySearch(x.Key) < 0
|
||||
select x into y
|
||||
select new KeyValuePair<int, int>(y.Key - offset[y.Key], y.Value);
|
||||
pb.SetVertices(array, false);
|
||||
pb.SetSharedIndices(enumerable);
|
||||
pb.SetSharedIndicesUV(enumerable2);
|
||||
pb.ToMesh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ProBuilder2.Common;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x0200000F RID: 15
|
||||
public static class pb_Extrude
|
||||
{
|
||||
// Token: 0x0600008E RID: 142 RVA: 0x0000BAB2 File Offset: 0x00009EB2
|
||||
public static bool Extrude(this pb_Object pb, pb_Face[] faces, ExtrudeMethod method, float distance)
|
||||
{
|
||||
if (method != ExtrudeMethod.IndividualFaces)
|
||||
{
|
||||
return pb_Extrude.ExtrudeAsGroups(pb, faces, method == ExtrudeMethod.FaceNormal, distance);
|
||||
}
|
||||
return pb_Extrude.ExtrudePerFace(pb, faces, distance);
|
||||
}
|
||||
|
||||
// Token: 0x0600008F RID: 143 RVA: 0x0000BAD4 File Offset: 0x00009ED4
|
||||
private static bool ExtrudePerFace(pb_Object pb, pb_Face[] faces, float distance)
|
||||
{
|
||||
if (faces == null || faces.Length < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
|
||||
int num = pb.sharedIndices.Length;
|
||||
int num2 = 0;
|
||||
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
||||
Dictionary<int, int> dictionary2 = pb.sharedIndicesUV.ToDictionary();
|
||||
List<pb_Face> list2 = new List<pb_Face>(pb.faces);
|
||||
Dictionary<int, int> dictionary3 = new Dictionary<int, int>();
|
||||
foreach (pb_Face pb_Face in faces)
|
||||
{
|
||||
pb_Face.smoothingGroup = -1;
|
||||
pb_Face.textureGroup = -1;
|
||||
Vector3 vector = pb_Math.Normal(pb, pb_Face) * distance;
|
||||
pb_Edge[] edges = pb_Face.edges;
|
||||
dictionary3.Clear();
|
||||
for (int j = 0; j < edges.Length; j++)
|
||||
{
|
||||
int count = list.Count;
|
||||
int x = edges[j].x;
|
||||
int y = edges[j].y;
|
||||
if (!dictionary3.ContainsKey(x))
|
||||
{
|
||||
dictionary3.Add(x, dictionary[x]);
|
||||
dictionary[x] = num + num2++;
|
||||
}
|
||||
if (!dictionary3.ContainsKey(y))
|
||||
{
|
||||
dictionary3.Add(y, dictionary[y]);
|
||||
dictionary[y] = num + num2++;
|
||||
}
|
||||
dictionary.Add(count, dictionary3[x]);
|
||||
dictionary.Add(count + 1, dictionary3[y]);
|
||||
dictionary.Add(count + 2, dictionary[x]);
|
||||
dictionary.Add(count + 3, dictionary[y]);
|
||||
pb_Vertex pb_Vertex = new pb_Vertex(list[x]);
|
||||
pb_Vertex pb_Vertex2 = new pb_Vertex(list[y]);
|
||||
pb_Vertex.position += vector;
|
||||
pb_Vertex2.position += vector;
|
||||
list.Add(new pb_Vertex(list[x]));
|
||||
list.Add(new pb_Vertex(list[y]));
|
||||
list.Add(pb_Vertex);
|
||||
list.Add(pb_Vertex2);
|
||||
pb_Face pb_Face2 = new pb_Face(new int[]
|
||||
{
|
||||
count,
|
||||
count + 1,
|
||||
count + 2,
|
||||
count + 1,
|
||||
count + 3,
|
||||
count + 2
|
||||
}, pb_Face.material, new pb_UV(pb_Face.uv), pb_Face.smoothingGroup, -1, -1, false);
|
||||
list2.Add(pb_Face2);
|
||||
}
|
||||
for (int k = 0; k < pb_Face.distinctIndices.Length; k++)
|
||||
{
|
||||
pb_Vertex pb_Vertex3 = list[pb_Face.distinctIndices[k]];
|
||||
pb_Vertex3.position.x = pb_Vertex3.position.x + vector.x;
|
||||
pb_Vertex pb_Vertex4 = list[pb_Face.distinctIndices[k]];
|
||||
pb_Vertex4.position.y = pb_Vertex4.position.y + vector.y;
|
||||
pb_Vertex pb_Vertex5 = list[pb_Face.distinctIndices[k]];
|
||||
pb_Vertex5.position.z = pb_Vertex5.position.z + vector.z;
|
||||
if (dictionary2 != null && dictionary2.ContainsKey(pb_Face.distinctIndices[k]))
|
||||
{
|
||||
dictionary2.Remove(pb_Face.distinctIndices[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
pb.SetVertices(list, false);
|
||||
pb.SetFaces(list2.ToArray());
|
||||
pb.SetSharedIndices(dictionary);
|
||||
pb.SetSharedIndicesUV(dictionary2);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Token: 0x06000090 RID: 144 RVA: 0x0000BE28 File Offset: 0x0000A228
|
||||
private static bool ExtrudeAsGroups(pb_Object pb, pb_Face[] faces, bool compensateAngleVertexDistance, float distance)
|
||||
{
|
||||
if (faces == null || faces.Length < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
|
||||
int num = pb.sharedIndices.Length;
|
||||
int num2 = 0;
|
||||
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
||||
Dictionary<int, int> dictionary2 = pb.sharedIndicesUV.ToDictionary();
|
||||
List<pb_Face> list2 = new List<pb_Face>(pb.faces);
|
||||
Dictionary<int, int> dictionary3 = new Dictionary<int, int>();
|
||||
Dictionary<int, int> dictionary4 = new Dictionary<int, int>();
|
||||
Dictionary<int, int> dictionary5 = new Dictionary<int, int>();
|
||||
Dictionary<int, pb_Tuple<Vector3, Vector3, List<int>>> dictionary6 = new Dictionary<int, pb_Tuple<Vector3, Vector3, List<int>>>();
|
||||
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, faces, true, dictionary);
|
||||
List<HashSet<pb_Face>> faceGroups = pb_Extrude.GetFaceGroups(wingedEdges);
|
||||
foreach (HashSet<pb_Face> hashSet in faceGroups)
|
||||
{
|
||||
Dictionary<pb_EdgeLookup, pb_Face> perimeterEdges = pb_Extrude.GetPerimeterEdges(hashSet, dictionary);
|
||||
dictionary4.Clear();
|
||||
dictionary3.Clear();
|
||||
foreach (KeyValuePair<pb_EdgeLookup, pb_Face> keyValuePair in perimeterEdges)
|
||||
{
|
||||
pb_EdgeLookup key = keyValuePair.Key;
|
||||
pb_Face value = keyValuePair.Value;
|
||||
int count = list.Count;
|
||||
int x = key.local.x;
|
||||
int y = key.local.y;
|
||||
if (!dictionary3.ContainsKey(x))
|
||||
{
|
||||
dictionary3.Add(x, dictionary[x]);
|
||||
int num3 = -1;
|
||||
if (dictionary4.TryGetValue(dictionary[x], out num3))
|
||||
{
|
||||
dictionary[x] = num3;
|
||||
}
|
||||
else
|
||||
{
|
||||
num3 = num + num2++;
|
||||
dictionary4.Add(dictionary[x], num3);
|
||||
dictionary[x] = num3;
|
||||
}
|
||||
}
|
||||
if (!dictionary3.ContainsKey(y))
|
||||
{
|
||||
dictionary3.Add(y, dictionary[y]);
|
||||
int num4 = -1;
|
||||
if (dictionary4.TryGetValue(dictionary[y], out num4))
|
||||
{
|
||||
dictionary[y] = num4;
|
||||
}
|
||||
else
|
||||
{
|
||||
num4 = num + num2++;
|
||||
dictionary4.Add(dictionary[y], num4);
|
||||
dictionary[y] = num4;
|
||||
}
|
||||
}
|
||||
dictionary.Add(count, dictionary3[x]);
|
||||
dictionary.Add(count + 1, dictionary3[y]);
|
||||
dictionary.Add(count + 2, dictionary[x]);
|
||||
dictionary.Add(count + 3, dictionary[y]);
|
||||
dictionary5.Add(count + 2, x);
|
||||
dictionary5.Add(count + 3, y);
|
||||
list.Add(new pb_Vertex(list[x]));
|
||||
list.Add(new pb_Vertex(list[y]));
|
||||
list.Add(null);
|
||||
list.Add(null);
|
||||
pb_Face pb_Face = new pb_Face(new int[]
|
||||
{
|
||||
count,
|
||||
count + 1,
|
||||
count + 2,
|
||||
count + 1,
|
||||
count + 3,
|
||||
count + 2
|
||||
}, value.material, new pb_UV(value.uv), value.smoothingGroup, -1, -1, false);
|
||||
list2.Add(pb_Face);
|
||||
}
|
||||
foreach (pb_Face pb_Face2 in hashSet)
|
||||
{
|
||||
pb_Face2.textureGroup = -1;
|
||||
Vector3 vector = pb_Math.Normal(pb, pb_Face2);
|
||||
for (int i = 0; i < pb_Face2.distinctIndices.Length; i++)
|
||||
{
|
||||
int num5 = pb_Face2.distinctIndices[i];
|
||||
if (!dictionary3.ContainsKey(num5) && dictionary4.ContainsKey(dictionary[num5]))
|
||||
{
|
||||
dictionary[num5] = dictionary4[dictionary[num5]];
|
||||
}
|
||||
int num6 = dictionary[num5];
|
||||
if (dictionary2 != null && dictionary2.ContainsKey(pb_Face2.distinctIndices[i]))
|
||||
{
|
||||
dictionary2.Remove(pb_Face2.distinctIndices[i]);
|
||||
}
|
||||
pb_Tuple<Vector3, Vector3, List<int>> pb_Tuple = null;
|
||||
if (dictionary6.TryGetValue(num6, out pb_Tuple))
|
||||
{
|
||||
pb_Tuple<Vector3, Vector3, List<int>> pb_Tuple2 = pb_Tuple;
|
||||
pb_Tuple2.Item1.x = pb_Tuple2.Item1.x + vector.x;
|
||||
pb_Tuple<Vector3, Vector3, List<int>> pb_Tuple3 = pb_Tuple;
|
||||
pb_Tuple3.Item1.y = pb_Tuple3.Item1.y + vector.y;
|
||||
pb_Tuple<Vector3, Vector3, List<int>> pb_Tuple4 = pb_Tuple;
|
||||
pb_Tuple4.Item1.z = pb_Tuple4.Item1.z + vector.z;
|
||||
pb_Tuple.Item3.Add(num5);
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary6.Add(num6, new pb_Tuple<Vector3, Vector3, List<int>>(vector, vector, new List<int> { num5 }));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (KeyValuePair<int, pb_Tuple<Vector3, Vector3, List<int>>> keyValuePair2 in dictionary6)
|
||||
{
|
||||
Vector3 vector2 = keyValuePair2.Value.Item1 / (float)keyValuePair2.Value.Item3.Count;
|
||||
vector2.Normalize();
|
||||
float num7 = ((!compensateAngleVertexDistance) ? 1f : pb_Math.Secant(Vector3.Angle(vector2, keyValuePair2.Value.Item2) * 0.017453292f));
|
||||
vector2.x *= distance * num7;
|
||||
vector2.y *= distance * num7;
|
||||
vector2.z *= distance * num7;
|
||||
foreach (int num8 in keyValuePair2.Value.Item3)
|
||||
{
|
||||
pb_Vertex pb_Vertex = list[num8];
|
||||
pb_Vertex.position.x = pb_Vertex.position.x + vector2.x;
|
||||
pb_Vertex pb_Vertex2 = list[num8];
|
||||
pb_Vertex2.position.y = pb_Vertex2.position.y + vector2.y;
|
||||
pb_Vertex pb_Vertex3 = list[num8];
|
||||
pb_Vertex3.position.z = pb_Vertex3.position.z + vector2.z;
|
||||
}
|
||||
}
|
||||
foreach (KeyValuePair<int, int> keyValuePair3 in dictionary5)
|
||||
{
|
||||
list[keyValuePair3.Key] = new pb_Vertex(list[keyValuePair3.Value]);
|
||||
}
|
||||
pb.SetVertices(list, false);
|
||||
pb.SetFaces(list2.ToArray());
|
||||
pb.SetSharedIndices(dictionary);
|
||||
pb.SetSharedIndicesUV(dictionary2);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Token: 0x06000091 RID: 145 RVA: 0x0000C528 File Offset: 0x0000A928
|
||||
private static List<HashSet<pb_Face>> GetFaceGroups(List<pb_WingedEdge> wings)
|
||||
{
|
||||
HashSet<pb_Face> hashSet = new HashSet<pb_Face>();
|
||||
List<HashSet<pb_Face>> list = new List<HashSet<pb_Face>>();
|
||||
foreach (pb_WingedEdge pb_WingedEdge in wings)
|
||||
{
|
||||
if (hashSet.Add(pb_WingedEdge.face))
|
||||
{
|
||||
HashSet<pb_Face> hashSet2 = new HashSet<pb_Face> { pb_WingedEdge.face };
|
||||
pb_GrowShrink.Flood(pb_WingedEdge, hashSet2);
|
||||
foreach (pb_Face pb_Face in hashSet2)
|
||||
{
|
||||
hashSet.Add(pb_Face);
|
||||
}
|
||||
list.Add(hashSet2);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// Token: 0x06000092 RID: 146 RVA: 0x0000C60C File Offset: 0x0000AA0C
|
||||
private static Dictionary<pb_EdgeLookup, pb_Face> GetPerimeterEdges(HashSet<pb_Face> faces, Dictionary<int, int> lookup)
|
||||
{
|
||||
Dictionary<pb_EdgeLookup, pb_Face> dictionary = new Dictionary<pb_EdgeLookup, pb_Face>();
|
||||
HashSet<pb_EdgeLookup> hashSet = new HashSet<pb_EdgeLookup>();
|
||||
foreach (pb_Face pb_Face in faces)
|
||||
{
|
||||
foreach (pb_Edge pb_Edge in pb_Face.edges)
|
||||
{
|
||||
pb_EdgeLookup pb_EdgeLookup = new pb_EdgeLookup(lookup[pb_Edge.x], lookup[pb_Edge.y], pb_Edge.x, pb_Edge.y);
|
||||
if (!hashSet.Add(pb_EdgeLookup))
|
||||
{
|
||||
if (dictionary.ContainsKey(pb_EdgeLookup))
|
||||
{
|
||||
dictionary.Remove(pb_EdgeLookup);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary.Add(pb_EdgeLookup, pb_Face);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ProBuilder2.Common;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x02000010 RID: 16
|
||||
public static class pb_Facetize
|
||||
{
|
||||
// Token: 0x06000093 RID: 147 RVA: 0x0000C6F4 File Offset: 0x0000AAF4
|
||||
public static pb_ActionResult Facetize(this pb_Object pb, IList<pb_Face> faces, out pb_Face[] newFaces)
|
||||
{
|
||||
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
|
||||
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
||||
List<pb_FaceRebuildData> list2 = new List<pb_FaceRebuildData>();
|
||||
foreach (pb_Face pb_Face in faces)
|
||||
{
|
||||
List<pb_FaceRebuildData> list3 = pb_Facetize.BreakFaceIntoTris(pb_Face, list, dictionary);
|
||||
list2.AddRange(list3);
|
||||
}
|
||||
pb_FaceRebuildData.Apply(list2, pb, list, null, dictionary, null);
|
||||
pb.DeleteFaces(faces);
|
||||
pb.ToMesh();
|
||||
newFaces = list2.Select((pb_FaceRebuildData x) => x.face).ToArray<pb_Face>();
|
||||
return new pb_ActionResult(Status.Success, string.Format("Triangulated {0} {1}", faces.Count, (faces.Count >= 2) ? "Faces" : "Face"));
|
||||
}
|
||||
|
||||
// Token: 0x06000094 RID: 148 RVA: 0x0000C7F0 File Offset: 0x0000ABF0
|
||||
private static List<pb_FaceRebuildData> BreakFaceIntoTris(pb_Face face, List<pb_Vertex> vertices, Dictionary<int, int> lookup)
|
||||
{
|
||||
int[] indices = face.indices;
|
||||
int num = indices.Length;
|
||||
List<pb_FaceRebuildData> list = new List<pb_FaceRebuildData>(num / 3);
|
||||
for (int i = 0; i < num; i += 3)
|
||||
{
|
||||
pb_FaceRebuildData pb_FaceRebuildData = new pb_FaceRebuildData();
|
||||
pb_FaceRebuildData.face = new pb_Face(face);
|
||||
pb_FaceRebuildData.face.SetIndices(new int[] { 0, 1, 2 });
|
||||
pb_FaceRebuildData.vertices = new List<pb_Vertex>
|
||||
{
|
||||
vertices[indices[i]],
|
||||
vertices[indices[i + 1]],
|
||||
vertices[indices[i + 2]]
|
||||
};
|
||||
pb_FaceRebuildData.sharedIndices = new List<int>
|
||||
{
|
||||
lookup[indices[i]],
|
||||
lookup[indices[i + 1]],
|
||||
lookup[indices[i + 2]]
|
||||
};
|
||||
list.Add(pb_FaceRebuildData);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ProBuilder2.Common;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x02000011 RID: 17
|
||||
public static class pb_GrowShrink
|
||||
{
|
||||
// Token: 0x06000096 RID: 150 RVA: 0x0000C8EC File Offset: 0x0000ACEC
|
||||
public static HashSet<pb_Face> GrowSelection(pb_Object pb, IList<pb_Face> faces, float maxAngleDiff = -1f)
|
||||
{
|
||||
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, true);
|
||||
HashSet<pb_Face> hashSet = new HashSet<pb_Face>(faces);
|
||||
HashSet<pb_Face> hashSet2 = new HashSet<pb_Face>();
|
||||
Vector3 vector = Vector3.zero;
|
||||
bool flag = maxAngleDiff > 0f;
|
||||
for (int i = 0; i < wingedEdges.Count; i++)
|
||||
{
|
||||
if (hashSet.Contains(wingedEdges[i].face))
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
vector = pb_Math.Normal(pb, wingedEdges[i].face);
|
||||
}
|
||||
pb_WingedEdgeEnumerator enumerator = wingedEdges[i].GetEnumerator();
|
||||
try
|
||||
{
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
pb_WingedEdge pb_WingedEdge = enumerator.Current;
|
||||
if (pb_WingedEdge.opposite != null && !hashSet.Contains(pb_WingedEdge.opposite.face))
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
Vector3 vector2 = pb_Math.Normal(pb, pb_WingedEdge.opposite.face);
|
||||
if (Vector3.Angle(vector, vector2) < maxAngleDiff)
|
||||
{
|
||||
hashSet2.Add(pb_WingedEdge.opposite.face);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hashSet2.Add(pb_WingedEdge.opposite.face);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
IDisposable disposable;
|
||||
if ((disposable = enumerator as IDisposable) != null)
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hashSet2;
|
||||
}
|
||||
|
||||
// Token: 0x06000097 RID: 151 RVA: 0x0000CA40 File Offset: 0x0000AE40
|
||||
public static void Flood(pb_WingedEdge wing, HashSet<pb_Face> selection)
|
||||
{
|
||||
pb_GrowShrink.Flood(null, wing, pb_GrowShrink.Vector3_Zero, -1f, selection);
|
||||
}
|
||||
|
||||
// Token: 0x06000098 RID: 152 RVA: 0x0000CA54 File Offset: 0x0000AE54
|
||||
public static void Flood(pb_Object pb, pb_WingedEdge wing, Vector3 wingNrm, float maxAngle, HashSet<pb_Face> selection)
|
||||
{
|
||||
pb_WingedEdge pb_WingedEdge = wing;
|
||||
do
|
||||
{
|
||||
pb_WingedEdge opposite = pb_WingedEdge.opposite;
|
||||
if (opposite != null && !selection.Contains(opposite.face))
|
||||
{
|
||||
if (maxAngle > 0f)
|
||||
{
|
||||
Vector3 vector = pb_Math.Normal(pb, opposite.face);
|
||||
if (Vector3.Angle(wingNrm, vector) < maxAngle && selection.Add(opposite.face))
|
||||
{
|
||||
pb_GrowShrink.Flood(pb, opposite, vector, maxAngle, selection);
|
||||
}
|
||||
}
|
||||
else if (selection.Add(opposite.face))
|
||||
{
|
||||
pb_GrowShrink.Flood(pb, opposite, wingNrm, maxAngle, selection);
|
||||
}
|
||||
}
|
||||
pb_WingedEdge = pb_WingedEdge.next;
|
||||
}
|
||||
while (pb_WingedEdge != wing);
|
||||
}
|
||||
|
||||
// Token: 0x06000099 RID: 153 RVA: 0x0000CAF4 File Offset: 0x0000AEF4
|
||||
public static HashSet<pb_Face> FloodSelection(pb_Object pb, IList<pb_Face> faces, float maxAngleDiff)
|
||||
{
|
||||
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, true);
|
||||
HashSet<pb_Face> hashSet = new HashSet<pb_Face>(faces);
|
||||
HashSet<pb_Face> hashSet2 = new HashSet<pb_Face>();
|
||||
for (int i = 0; i < wingedEdges.Count; i++)
|
||||
{
|
||||
if (!hashSet2.Contains(wingedEdges[i].face) && hashSet.Contains(wingedEdges[i].face))
|
||||
{
|
||||
hashSet2.Add(wingedEdges[i].face);
|
||||
pb_GrowShrink.Flood(pb, wingedEdges[i], (maxAngleDiff <= 0f) ? pb_GrowShrink.Vector3_Zero : pb_Math.Normal(pb, wingedEdges[i].face), maxAngleDiff, hashSet2);
|
||||
}
|
||||
}
|
||||
return hashSet2;
|
||||
}
|
||||
|
||||
// Token: 0x0400002E RID: 46
|
||||
private static readonly Vector3 Vector3_Zero = new Vector3(0f, 0f, 0f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ProBuilder2.Common;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x02000012 RID: 18
|
||||
public static class pb_Subdivide
|
||||
{
|
||||
// Token: 0x0600009B RID: 155 RVA: 0x0000CBC0 File Offset: 0x0000AFC0
|
||||
public static pb_ActionResult Subdivide(this pb_Object pb)
|
||||
{
|
||||
pb_Face[] array;
|
||||
return pb.Subdivide(pb.faces, out array);
|
||||
}
|
||||
|
||||
// Token: 0x0600009C RID: 156 RVA: 0x0000CBDC File Offset: 0x0000AFDC
|
||||
public static pb_ActionResult Subdivide(this pb_Object pb, IList<pb_Face> faces, out pb_Face[] subdividedFaces)
|
||||
{
|
||||
return pb.Connect(faces, out subdividedFaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Poly2Tri;
|
||||
using ProBuilder2.Common;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x02000013 RID: 19
|
||||
public static class pb_Triangulation
|
||||
{
|
||||
// Token: 0x0600009D RID: 157 RVA: 0x0000CBF4 File Offset: 0x0000AFF4
|
||||
public static bool SortAndTriangulate(IList<Vector2> points, out List<int> indices, bool convex = false)
|
||||
{
|
||||
IList<Vector2> list = pb_Projection.Sort(points, SortMethod.CounterClockwise);
|
||||
Dictionary<int, int> dictionary = new Dictionary<int, int>();
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
dictionary.Add(i, points.IndexOf(list[i]));
|
||||
}
|
||||
if (!pb_Triangulation.Triangulate(list, out indices, convex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int j = 0; j < indices.Count; j++)
|
||||
{
|
||||
indices[j] = dictionary[indices[j]];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Token: 0x0600009E RID: 158 RVA: 0x0000CC78 File Offset: 0x0000B078
|
||||
public static bool TriangulateVertices(IList<pb_Vertex> vertices, out List<int> triangles, bool unordered = true, bool convex = false)
|
||||
{
|
||||
Vector3[] array = new Vector3[vertices.Count];
|
||||
for (int i = 0; i < vertices.Count; i++)
|
||||
{
|
||||
array[i] = vertices[i].position;
|
||||
}
|
||||
return pb_Triangulation.TriangulateVertices(array, out triangles, unordered, convex);
|
||||
}
|
||||
|
||||
// Token: 0x0600009F RID: 159 RVA: 0x0000CCCC File Offset: 0x0000B0CC
|
||||
public static bool TriangulateVertices(Vector3[] vertices, out List<int> triangles, bool unordered = true, bool convex = false)
|
||||
{
|
||||
triangles = null;
|
||||
int num = ((vertices != null) ? vertices.Length : 0);
|
||||
if (num < 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (num == 3)
|
||||
{
|
||||
triangles = new List<int> { 0, 1, 2 };
|
||||
return true;
|
||||
}
|
||||
Vector3 normal = pb_Projection.FindBestPlane(vertices, null).normal;
|
||||
Vector2[] array = pb_Projection.PlanarProject(vertices, normal);
|
||||
if (unordered)
|
||||
{
|
||||
return pb_Triangulation.SortAndTriangulate(array, out triangles, convex);
|
||||
}
|
||||
return pb_Triangulation.Triangulate(array, out triangles, convex);
|
||||
}
|
||||
|
||||
// Token: 0x060000A0 RID: 160 RVA: 0x0000CD50 File Offset: 0x0000B150
|
||||
public static bool Triangulate(IList<Vector2> points, out List<int> indices, bool convex = false)
|
||||
{
|
||||
indices = new List<int>();
|
||||
int index = 0;
|
||||
Triangulatable triangulatable2;
|
||||
if (convex)
|
||||
{
|
||||
Triangulatable triangulatable = new PointSet(points.Select((Vector2 x) => new TriangulationPoint((double)x.x, (double)x.y, index++)).ToList<TriangulationPoint>());
|
||||
triangulatable2 = triangulatable;
|
||||
}
|
||||
else
|
||||
{
|
||||
triangulatable2 = new Polygon(points.Select((Vector2 x) => new PolygonPoint((double)x.x, (double)x.y, index++)));
|
||||
}
|
||||
Triangulatable triangulatable3 = triangulatable2;
|
||||
P2T.Triangulate(TriangulationAlgorithm.DTSweep, triangulatable3);
|
||||
foreach (DelaunayTriangle delaunayTriangle in triangulatable3.Triangles)
|
||||
{
|
||||
if (delaunayTriangle.Points[0].Index < 0 || delaunayTriangle.Points[1].Index < 0 || delaunayTriangle.Points[2].Index < 0)
|
||||
{
|
||||
pb_Log.Warning("Triangulation failed - additional vertices were inserted.");
|
||||
return false;
|
||||
}
|
||||
indices.Add(delaunayTriangle.Points[0].Index);
|
||||
indices.Add(delaunayTriangle.Points[1].Index);
|
||||
indices.Add(delaunayTriangle.Points[2].Index);
|
||||
}
|
||||
WindingOrder windingOrder = pbTriangleOps.GetWindingOrder(points);
|
||||
if (pbTriangleOps.GetWindingOrder(new Vector2[]
|
||||
{
|
||||
points[indices[0]],
|
||||
points[indices[1]],
|
||||
points[indices[2]]
|
||||
}) != windingOrder)
|
||||
{
|
||||
indices.Reverse();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using KdTree;
|
||||
using KdTree.Math;
|
||||
using ProBuilder2.Common;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ProBuilder2.MeshOperations
|
||||
{
|
||||
// Token: 0x02000014 RID: 20
|
||||
public static class pb_WeldVertices
|
||||
{
|
||||
// Token: 0x060000A1 RID: 161 RVA: 0x0000CF88 File Offset: 0x0000B388
|
||||
public static pb_ActionResult WeldVertices(this pb_Object pb, int[] indices, float neighborRadius, out int[] welds)
|
||||
{
|
||||
pb_Vertex[] vertices = pb_Vertex.GetVertices(pb, null);
|
||||
pb_IntArray[] sharedIndices = pb.sharedIndices;
|
||||
Dictionary<int, int> dictionary = sharedIndices.ToDictionary();
|
||||
HashSet<int> commonIndices = pb_IntArrayUtility.GetCommonIndices(dictionary, indices);
|
||||
int count = commonIndices.Count;
|
||||
int num = Math.Min(32, commonIndices.Count<int>());
|
||||
KdTree<float, int> kdTree = new KdTree<float, int>(3, new FloatMath(), AddDuplicateBehavior.Collect);
|
||||
foreach (int num2 in commonIndices)
|
||||
{
|
||||
Vector3 position = vertices[sharedIndices[num2][0]].position;
|
||||
kdTree.Add(new float[] { position.x, position.y, position.z }, num2);
|
||||
}
|
||||
float[] array = new float[3];
|
||||
Dictionary<int, int> dictionary2 = new Dictionary<int, int>();
|
||||
Dictionary<int, Vector3> dictionary3 = new Dictionary<int, Vector3>();
|
||||
int num3 = sharedIndices.Length;
|
||||
foreach (int num4 in commonIndices)
|
||||
{
|
||||
if (!dictionary2.ContainsKey(num4))
|
||||
{
|
||||
Vector3 position2 = vertices[sharedIndices[num4][0]].position;
|
||||
array[0] = position2.x;
|
||||
array[1] = position2.y;
|
||||
array[2] = position2.z;
|
||||
KdTreeNode<float, int>[] array2 = kdTree.RadialSearch(array, neighborRadius, num);
|
||||
if (num < count && array2.Length >= num)
|
||||
{
|
||||
array2 = kdTree.RadialSearch(array, neighborRadius, count);
|
||||
num = Math.Min(count, array2.Length + array2.Length / 2);
|
||||
}
|
||||
Vector3 zero = Vector3.zero;
|
||||
float num5 = 0f;
|
||||
for (int i = 0; i < array2.Length; i++)
|
||||
{
|
||||
int value = array2[i].Value;
|
||||
if (!dictionary2.ContainsKey(value))
|
||||
{
|
||||
zero.x += array2[i].Point[0];
|
||||
zero.y += array2[i].Point[1];
|
||||
zero.z += array2[i].Point[2];
|
||||
dictionary2.Add(value, num3);
|
||||
num5 += 1f;
|
||||
if (array2[i].Duplicates != null)
|
||||
{
|
||||
for (int j = 0; j < array2[i].Duplicates.Count; j++)
|
||||
{
|
||||
dictionary2.Add(array2[i].Duplicates[j], num3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
zero.x /= num5;
|
||||
zero.y /= num5;
|
||||
zero.z /= num5;
|
||||
dictionary3.Add(num3, zero);
|
||||
num3++;
|
||||
}
|
||||
}
|
||||
welds = new int[dictionary2.Count];
|
||||
int num6 = 0;
|
||||
foreach (KeyValuePair<int, int> keyValuePair in dictionary2)
|
||||
{
|
||||
int[] array3 = sharedIndices[keyValuePair.Key];
|
||||
welds[num6++] = array3[0];
|
||||
for (int k = 0; k < array3.Length; k++)
|
||||
{
|
||||
dictionary[array3[k]] = keyValuePair.Value;
|
||||
vertices[array3[k]].position = dictionary3[keyValuePair.Value];
|
||||
}
|
||||
}
|
||||
pb.SetSharedIndices(dictionary);
|
||||
pb.SetVertices(vertices, false);
|
||||
pb.ToMesh();
|
||||
return new pb_ActionResult(Status.Success, "Weld Vertices");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user