public Mesh Build(MeshSmoothingMethod method, int times = 5, float alpha = 0.2f, float beta = 0.5f) { var mesh = triangulation.Build( (Vertex2D v) => { float z = 0f; if (heightTable.ContainsKey(v)) { z = heightTable[v]; } return(new Vector3(v.Coordinate.x, v.Coordinate.y, -z)); } ); mesh = Symmetrize(mesh); switch (method) { case MeshSmoothingMethod.Laplacian: mesh = MeshSmoothing.LaplacianFilter(mesh, times); break; case MeshSmoothingMethod.HC: mesh = MeshSmoothing.HCFilter(mesh, times, alpha, beta); break; } network = VertexConnection.BuildNetwork(mesh.triangles); return(mesh); }
public static VertexConnection[] FindAllOverLappingVert(Mesh mesh) { Vector3[] vertices = mesh.vertices; VertexConnection[] connections = new VertexConnection[vertices.Length]; for (int i = 0; i < vertices.Length; i++) { var P1 = vertices[i]; var VC1 = connections[i]; for (int n = i + 1; n < vertices.Length; n++) { if (P1 == vertices[n]) { var VC2 = connections[n]; if (VC2 == null) { VC2 = connections[n] = new VertexConnection(); } if (VC1 == null) { VC1 = connections[i] = new VertexConnection(); } VC1.connections.Add(n); VC2.connections.Add(i); } } } return(connections); }
public static VertexConnection[] GetSharedVertices(Vector3[] vertices) { VertexConnection[] connections = new VertexConnection[vertices.Length]; for (int i = 0; i < vertices.Length; i++) { var P1 = vertices[i]; var VC1 = connections[i]; for (int n = i + 1; n < vertices.Length; n++) { if (P1 == vertices[n]) { var VC2 = connections[n]; if (VC2 == null) { VC2 = connections[n] = new VertexConnection(); } if (VC1 == null) { VC1 = connections[i] = new VertexConnection(); } VC1.connections.Add(n); VC2.connections.Add(i); } } } return(connections); }
// Use this for initialization void Start() { hmul = 1F / hardness; mf = GetComponent<MeshFilter> (); mc = GetComponent<MeshCollider> (); verts = mf.mesh.vertices; tris = mf.mesh.triangles; //mf.mesh.SetIndices (tris, MeshTopology.LineStrip, 0); connections = new VertexConnection[verts.Length]; for (int i = 0; i < verts.Length; i++) { Vector3 P1 = verts [i]; VertexConnection VC1 = connections [i]; for (int n = i+1; n < verts.Length; n++) { if (P1 == verts [n]) { var VC2 = connections [n]; if (VC2 == null) VC2 = connections [n] = new VertexConnection (); if (VC1 == null) VC1 = connections [i] = new VertexConnection (); VC1.connections.Add (n); VC2.connections.Add (i); } } } }
public static Vector3[] LaplacianFilter(Vector3[] vertices, int[] triangles, int times) { var network = VertexConnection.BuildNetwork(triangles); for (int i = 0; i < times; i++) { vertices = LaplacianFilter(network, vertices, triangles); } return(vertices); }
static Vector3[] HCFilter(Vector3[] vertices, int[] triangles, int times, float alpha, float beta) { alpha = Mathf.Clamp01(alpha); beta = Mathf.Clamp01(beta); var network = VertexConnection.BuildNetwork(triangles); Vector3[] origin = new Vector3[vertices.Length]; Array.Copy(vertices, origin, vertices.Length); for (int i = 0; i < times; i++) { vertices = HCFilter(network, origin, vertices, triangles, alpha, beta); } return(vertices); }
static Vector3[] HCFilter(Vector3[] vertices, List <int> limitedTriangles, int times, float alpha, float beta) { alpha = Mathf.Clamp01(alpha); beta = Mathf.Clamp01(beta); var limitedTrianglesArray = limitedTriangles.ToArray(); var network = VertexConnection.BuildNetwork(limitedTrianglesArray); var limitedVertexCount = limitedTriangles.Max(); Vector3[] origin = new Vector3[limitedVertexCount]; Array.Copy(vertices, origin, limitedVertexCount); for (int i = 0; i < times; i++) { vertices = HCFilter(network, origin, vertices, limitedTrianglesArray, alpha, beta); } return(vertices); }
public static Vector3[] LaplacianFilter(Vector3[] sourceVertices, int[] sourceTriangles, int times, JobHandle initialJobHandlerDependency) { var filterJobHandlers = new List <JobHandle>(); int batchSize = 250; Network = VertexConnection.BuildNetwork(sourceTriangles); LatestVertices = sourceVertices; for (int i = 0; i < times; i++) { var vertexArray = new NativeArray <Vector3>(LatestVertices, Allocator.TempJob); var trianglesArray = new NativeArray <int>(sourceTriangles, Allocator.TempJob); var job = new LaplactianFilterJob { vertices = vertexArray, triangles = trianglesArray }; if (i == 0) { filterJobHandlers.Add(job.Schedule(vertexArray.Length, batchSize, initialJobHandlerDependency)); } else { filterJobHandlers.Add(job.Schedule(vertexArray.Length, batchSize, filterJobHandlers[i - 1])); } filterJobHandlers.Last().Complete(); // set vertices LatestVertices = new Vector3[vertexArray.Length]; vertexArray.CopyTo(LatestVertices); vertexArray.Dispose(); trianglesArray.Dispose(); } return(LatestVertices); }
void Start() { vertexConnection = GetComponent <VertexConnection>(); meshSmoothing = GetComponent <MeshSmoothing>(); meshSmoothing.SetVertexConnection(vertexConnection); //mesh = meshFilter.sharedMesh; mesh = meshFilter.mesh; mesh = ApplyNormalNoise(mesh); switch (type) { case FilterType.Laplacian: mesh = meshSmoothing.LaplacianFilter(mesh, times); break; case FilterType.HC: mesh = meshSmoothing.HCFilter(mesh, times, hcAlpha, hcBeta); break; } }
// private class AdjacentNeightboursHelper{ // // Does the vertex v exist in the list of vertices // public static bool isVertexExist(List<Vector3>adjacentV, Vector3 v) // { // bool marker = false; // foreach (Vector3 vec in adjacentV) // if (Mathf.Approximately(vec.x,v.x) && Mathf.Approximately(vec.y,v.y) && Mathf.Approximately(vec.z,v.z)) // { // marker = true; // break; // } // // return marker; // } // } //Finds adjacent neighbours of the supplied vertex. //sharedPositions can be filled by Helper.GetSharedVertices() if the mesh has seams/gaps public static List <Vector3> FindAdjacentVertexNeighbours(Vector3[] vertices, int[] triangles, Vector3 vertex, VertexConnection[] sharedPositions = null) { List <Vector3> adjacentV = new List <Vector3>(); HashSet <int> facemarker = new HashSet <int>(); int facecount = 0; if (sharedPositions == null) { sharedPositions = new VertexConnection[vertices.Length]; } //caches int v1 = 0; int v2 = 0; bool marker = false; int tk, tk1, tk2; VertexConnection sharedPosition; // Find matching vertices for (int i = 0; i < vertices.Length; ++i) { if (Mathf.Approximately(Vector3.Distance(vertex, vertices[i]), 0)) { // v1 = 0; // v2 = 0; // marker = false; // Find vertex indices from the triangle array for (int k = 0; k < triangles.Length; k = k + 3) { if (facemarker.Contains(k) == false) { v1 = 0; v2 = 0; marker = false; tk = triangles[k]; tk1 = triangles[k + 1]; tk2 = triangles[k + 2]; if (i == tk) { v1 = tk1; v2 = tk2; marker = true; } if (i == tk1) { v1 = tk; v2 = tk2; marker = true; } if (i == tk2) { v1 = tk; v2 = tk1; marker = true; } facecount++; if (marker) { // Once face has been used mark it so it does not get used again facemarker.Add(k); // // Add non duplicate vertices to the list // if (AdjacentNeightboursHelper.isVertexExist(adjacentV, v[v1]) == false ) // { // adjacentV.Add(v[v1]); // //Debug.Log("Adjacent vertex index = " + v1); // } // // if ( AdjacentNeightboursHelper.isVertexExist(adjacentV, v[v2]) == false ) // { // adjacentV.Add(v[v2]); // //Debug.Log("Adjacent vertex index = " + v2); // } // Add non duplicate vertices to the list // This is faster than the above code sharedPosition = sharedPositions[v1]; if (sharedPosition == null) { adjacentV.Add(vertices[v1]); } else { for (int sv = 0; sv < sharedPosition.connections.Count; ++sv) { adjacentV.Add(vertices[sharedPosition.connections[sv]]); } } sharedPosition = sharedPositions[v2]; if (sharedPosition == null) { adjacentV.Add(vertices[v2]); } else { for (int sv = 0; sv < sharedPosition.connections.Count; ++sv) { adjacentV.Add(vertices[sharedPosition.connections[sv]]); } } marker = false; } } } } } //Debug.Log("Faces Found = " + facecount); return(adjacentV); }
/** * Splits face per vertex. * Todo - Could implement more sanity checks - namely testing for edges before sending to Split_Internal. However, * the split method is smart enough to fail on those cases, so ignore for now. */ public static bool ConnectVertices(this pb_Object pb, List <VertexConnection> vertexConnectionsUnfiltered, out pb_Face[] faces) { List <VertexConnection> vertexConnections = new List <VertexConnection>(); List <int> inds = new List <int>(); int i = 0; for (i = 0; i < vertexConnectionsUnfiltered.Count; i++) { VertexConnection vc = vertexConnectionsUnfiltered[i]; vc.indices = vc.indices.Distinct().ToList(); if (vc.isValid) { inds.AddRange(vc.indices); vertexConnections.Add(vc); } } if (vertexConnections.Count < 1) { faces = null; return(false); } int len = vertexConnections.Count; List <pb_Face> successfullySplitFaces = new List <pb_Face>(); List <pb_Face> all_splitFaces = new List <pb_Face>(); List <Vector3[]> all_splitVertices = new List <Vector3[]>(); List <int[]> all_splitSharedIndices = new List <int[]>(); bool[] success = new bool[len]; pb_IntArray[] sharedIndices = pb.sharedIndices; i = 0; foreach (VertexConnection vc in vertexConnections) { pb_Face[] splitFaces = null; Vector3[][] splitVertices = null; int[][] splitSharedIndices = null; if (vc.indices.Count < 3) { int indA = vc.face.indices.IndexOf(vc.indices[0], sharedIndices); int indB = vc.face.indices.IndexOf(vc.indices[1], sharedIndices); if (indA < 0 || indB < 0) { success[i] = false; continue; } indA = vc.face.indices[indA]; indB = vc.face.indices[indB]; success[i] = SplitFace_Internal(new SplitSelection(pb, vc.face, pb.vertices[indA], pb.vertices[indB], true, true, indA, indB), out splitFaces, out splitVertices, out splitSharedIndices); if (success[i]) { successfullySplitFaces.Add(vc.face); } } else { success[i] = PokeFace_Internal(pb, vc.face, vc.indices.ToArray(), out splitFaces, out splitVertices, out splitSharedIndices); if (success[i]) { successfullySplitFaces.Add(vc.face); } } if (success[i]) { int texGroup = pb.UnusedTextureGroup(i + 1); for (int j = 0; j < splitFaces.Length; j++) { splitFaces[j].textureGroup = texGroup; all_splitFaces.Add(splitFaces[j]); all_splitVertices.Add(splitVertices[j]); all_splitSharedIndices.Add(splitSharedIndices[j]); } } i++; } if (all_splitFaces.Count < 1) { faces = null; return(false); } pb_Face[] appendedFaces = pb.AppendFaces(all_splitVertices.ToArray(), all_splitFaces.ToArray(), all_splitSharedIndices.ToArray()); inds.AddRange(pb_Face.AllTriangles(appendedFaces)); pb.WeldVertices(inds.ToArray(), Mathf.Epsilon); pb.DeleteFaces(successfullySplitFaces.ToArray()); faces = appendedFaces; return(true); }
public void SetVertexConnection(VertexConnection vC) { vertexConnection = vC; }