// Use this for initialization void Start() { TriMesh = new TriangleNet.Mesh(); /*_mesh.Triangulate("Assets/Plugins/Data/superior.poly");*/ var geometry = FileReader.ReadPolyFile("Assets/Plugins/Data/superior.poly"); TriMesh.behavior.Quality = true; TriMesh.behavior.MinAngle = 33.8f; TriMesh.Triangulate(geometry); //TriMesh.Refine(true); // Get mesh statistics. var statistic = new Statistic(); statistic.Update(TriMesh, 1); // Refine by setting a custom maximum area constraint. TriMesh.Refine(statistic.LargestArea / 4); TriMesh.Smooth(); Debug.Log(string.Format("width {0:0.00}, height {1:0.00}; min {2:0.00}, {3:0.00}; max {4:0.00}, {5:0.00}", TriMesh.Bounds.Width, TriMesh.Bounds.Height, TriMesh.Bounds.Xmin, TriMesh.Bounds.Ymin, TriMesh.Bounds.Xmax, TriMesh.Bounds.Ymax)); OnRender(TriMesh); }
public static void Tessellate(List <Vector2> vertices, List <IndexedEdge> indexedEdges, List <Hole> holes, List <int> indices, float tessellationAmount) { if (tessellationAmount <= 0f) { return; } indices.Clear(); if (vertices.Count >= 3) { InputGeometry inputGeometry = new InputGeometry(vertices.Count); for (int i = 0; i < vertices.Count; ++i) { Vector2 vertex = vertices[i]; inputGeometry.AddPoint(vertex.x, vertex.y); } for (int i = 0; i < indexedEdges.Count; ++i) { IndexedEdge edge = indexedEdges[i]; inputGeometry.AddSegment(edge.index1, edge.index2); } for (int i = 0; i < holes.Count; ++i) { Vector2 hole = holes[i].vertex; inputGeometry.AddHole(hole.x, hole.y); } TriangleNet.Mesh triangleMesh = new TriangleNet.Mesh(); TriangleNet.Tools.Statistic statistic = new TriangleNet.Tools.Statistic(); triangleMesh.Triangulate(inputGeometry); triangleMesh.Behavior.MinAngle = 20.0; triangleMesh.Behavior.SteinerPoints = -1; triangleMesh.Refine(true); statistic.Update(triangleMesh, 1); triangleMesh.Refine(statistic.LargestArea / tessellationAmount); triangleMesh.Renumber(); vertices.Clear(); indexedEdges.Clear(); foreach (TriangleNet.Data.Vertex vertex in triangleMesh.Vertices) { vertices.Add(new Vector2((float)vertex.X, (float)vertex.Y)); } foreach (TriangleNet.Data.Segment segment in triangleMesh.Segments) { indexedEdges.Add(new IndexedEdge(segment.P0, segment.P1)); } foreach (TriangleNet.Data.Triangle triangle in triangleMesh.Triangles) { if (triangle.P0 >= 0 && triangle.P0 < vertices.Count && triangle.P0 >= 0 && triangle.P1 < vertices.Count && triangle.P0 >= 0 && triangle.P2 < vertices.Count) { indices.Add(triangle.P0); indices.Add(triangle.P2); indices.Add(triangle.P1); } } } }
public void CreateSubdividedMesh(Vector2[] vertsToCopy, Transform transform, int smoothLevel) { Sprite spr = transform.GetComponent <SpriteRenderer>().sprite; Rect rec = spr.rect; Vector3 bound = transform.renderer.bounds.max - transform.renderer.bounds.min; TextureImporter textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(spr)) as TextureImporter; //Create triangle.NET geometry TriangleNet.Geometry.InputGeometry geometry = new TriangleNet.Geometry.InputGeometry(vertsToCopy.Length); //Add vertices foreach (Vector2 p in vertsToCopy) { geometry.AddPoint(p.x, p.y); } //Add segments for (int i = 0; i < vertsToCopy.Length - 1; i++) { geometry.AddSegment(i, i + 1); } geometry.AddSegment(vertsToCopy.Length - 1, 0); //Triangulate, refine and smooth TriangleNet.Mesh triangleNetMesh = new TriangleNet.Mesh(); triangleNetMesh.behavior.MinAngle = 10; triangleNetMesh.Triangulate(geometry); if (smoothLevel > 1) { triangleNetMesh.Refine(true); } TriangleNet.Tools.Statistic statistic = new TriangleNet.Tools.Statistic(); statistic.Update(triangleNetMesh, 1); // Refine by setting a custom maximum area constraint. if (smoothLevel > 2) { triangleNetMesh.Refine(statistic.LargestArea / 8); } try { triangleNetMesh.Smooth(); } catch { //Debug.LogWarning("unable to smooth"); } triangleNetMesh.Renumber(); //transform vertices Vector3[] vertices = new Vector3[triangleNetMesh.Vertices.Count]; Vector2[] uvs = new Vector2[triangleNetMesh.Vertices.Count]; Vector3[] normals = new Vector3[triangleNetMesh.Vertices.Count]; int idx = 0; foreach (TriangleNet.Data.Vertex v in triangleNetMesh.Vertices) { vertices[idx] = new Vector3((float)v.X, (float)v.Y, 0); normals[idx] = new Vector3(0, 0, -1); Vector2 newUv = new Vector2(((float)v.X / bound.x) + 0.5f, ((float)v.Y / bound.y) + 0.5f); newUv.x *= rec.width / spr.texture.width; newUv.y *= rec.height / spr.texture.height; //Debug.Log(spr.textureRectOffset); newUv.x += (rec.x) / spr.texture.width; newUv.y += (rec.y) / spr.texture.height; SpriteMetaData[] smdArray = textureImporter.spritesheet; Vector2 pivot = new Vector2(.0f, .0f);; for (int i = 0; i < smdArray.Length; i++) { if (smdArray[i].name == spr.name) { switch (smdArray[i].alignment) { case (0): smdArray[i].pivot = Vector2.zero; break; case (1): smdArray[i].pivot = new Vector2(0f, 1f) - new Vector2(.5f, .5f); break; case (2): smdArray[i].pivot = new Vector2(0.5f, 1f) - new Vector2(.5f, .5f); break; case (3): smdArray[i].pivot = new Vector2(1f, 1f) - new Vector2(.5f, .5f); break; case (4): smdArray[i].pivot = new Vector2(0f, .5f) - new Vector2(.5f, .5f); break; case (5): smdArray[i].pivot = new Vector2(1f, .5f) - new Vector2(.5f, .5f); break; case (6): smdArray[i].pivot = new Vector2(0f, 0f) - new Vector2(.5f, .5f); break; case (7): smdArray[i].pivot = new Vector2(0.5f, 0f) - new Vector2(.5f, .5f); break; case (8): smdArray[i].pivot = new Vector2(1f, 0f) - new Vector2(.5f, .5f); break; case (9): smdArray[i].pivot -= new Vector2(.5f, .5f); break; } pivot = smdArray[i].pivot; } } if (textureImporter.spriteImportMode == SpriteImportMode.Single) { pivot = textureImporter.spritePivot - new Vector2(.5f, .5f); } newUv.x += ((pivot.x) * rec.width) / spr.texture.width; newUv.y += ((pivot.y) * rec.height) / spr.texture.height; uvs[idx] = newUv; idx++; } //transform triangles int[] triangles = new int[triangleNetMesh.Triangles.Count * 3]; idx = 0; foreach (TriangleNet.Data.Triangle t in triangleNetMesh.Triangles) { triangles[idx++] = t.P1; triangles[idx++] = t.P0; triangles[idx++] = t.P2; } finalVertices = vertices; finalTriangles = triangles; finalUvs = uvs; finalNormals = normals; }
public static void Tessellate(List<Vector2> vertices, List<IndexedEdge> indexedEdges, List<Hole> holes, List<int> indices, float tessellationAmount) { if(tessellationAmount <= 0f) { return; } indices.Clear(); if(vertices.Count >= 3) { InputGeometry inputGeometry = new InputGeometry(vertices.Count); for(int i = 0; i < vertices.Count; ++i) { Vector2 vertex = vertices[i]; inputGeometry.AddPoint(vertex.x,vertex.y); } for(int i = 0; i < indexedEdges.Count; ++i) { IndexedEdge edge = indexedEdges[i]; inputGeometry.AddSegment(edge.index1,edge.index2); } for(int i = 0; i < holes.Count; ++i) { Vector2 hole = holes[i].vertex; inputGeometry.AddHole(hole.x,hole.y); } TriangleNet.Mesh triangleMesh = new TriangleNet.Mesh(); TriangleNet.Tools.Statistic statistic = new TriangleNet.Tools.Statistic(); triangleMesh.Triangulate(inputGeometry); triangleMesh.Behavior.MinAngle = 20.0; triangleMesh.Behavior.SteinerPoints = -1; triangleMesh.Refine(true); statistic.Update(triangleMesh,1); triangleMesh.Refine(statistic.LargestArea / tessellationAmount); triangleMesh.Renumber(); vertices.Clear(); indexedEdges.Clear(); foreach(TriangleNet.Data.Vertex vertex in triangleMesh.Vertices) { vertices.Add(new Vector2((float)vertex.X,(float)vertex.Y)); } foreach(TriangleNet.Data.Segment segment in triangleMesh.Segments) { indexedEdges.Add(new IndexedEdge(segment.P0,segment.P1)); } foreach (TriangleNet.Data.Triangle triangle in triangleMesh.Triangles) { if(triangle.P0 >= 0 && triangle.P0 < vertices.Count && triangle.P0 >= 0 && triangle.P1 < vertices.Count && triangle.P0 >= 0 && triangle.P2 < vertices.Count) { indices.Add(triangle.P0); indices.Add(triangle.P2); indices.Add(triangle.P1); } } } }
public void SubdivideMesh(int divisions) { if (spriteRenderer != null && points.Length > 2) { // Unparent the skin temporarily before adding the mesh Transform polygonParent = spriteRenderer.transform.parent; spriteRenderer.transform.parent = null; // Reset the rotation before creating the mesh so the UV's will align properly Quaternion localRotation = spriteRenderer.transform.localRotation; spriteRenderer.transform.localRotation = Quaternion.identity; // Reset the scale before creating the mesh so the UV's will align properly Vector3 localScale = spriteRenderer.transform.localScale; spriteRenderer.transform.localScale = Vector3.one; //Create triangle.NET geometry TriangleNet.Geometry.InputGeometry geometry = new TriangleNet.Geometry.InputGeometry(points.Length); //Add vertices foreach (Vector2 point in points) { geometry.AddPoint(point.x, point.y); } int N = geometry.Count; int end = 0; //Add vertices foreach (Vector2 point in points) { geometry.AddPoint(point.x, point.y); end++; } for (int i = 0; i < end; i++) { geometry.AddSegment(N + i, N + ((i + 1) % end)); } //Triangulate and subdivide the mesh TriangleNet.Mesh triangleMesh = new TriangleNet.Mesh(); if (divisions > 0) { triangleMesh.behavior.MinAngle = 10; } triangleMesh.Triangulate(geometry); if (divisions > 0) { if (divisions > 1) { triangleMesh.Refine(true); } TriangleNet.Tools.Statistic stat = new TriangleNet.Tools.Statistic(); stat.Update(triangleMesh, 1); // Refine by area if (divisions > 2) { triangleMesh.Refine(stat.LargestArea / 8); } try { triangleMesh.Smooth(); } catch { //Debug.Log("Cannot subdivide"); } triangleMesh.Renumber(); } //transform vertices points = new Vector2[triangleMesh.Vertices.Count]; Vector3[] vertices = new Vector3[triangleMesh.Vertices.Count]; Vector2[] uvs = new Vector2[triangleMesh.Vertices.Count]; Vector3[] normals = new Vector3[triangleMesh.Vertices.Count]; int n = 0; foreach (TriangleNet.Data.Vertex v in triangleMesh.Vertices) { points[n] = new Vector2((float)v.X, (float)v.Y); vertices[n] = new Vector3((float)v.X, (float)v.Y, 0); normals[n] = new Vector3(0, 0, -1); n++; } //transform triangles int[] triangles = new int[triangleMesh.Triangles.Count * 3]; n = 0; foreach (TriangleNet.Data.Triangle t in triangleMesh.Triangles) { triangles[n++] = t.P1; triangles[n++] = t.P0; triangles[n++] = t.P2; } mesh.Clear(); mesh = new Mesh(); mesh.vertices = vertices; mesh.triangles = triangles; mesh.uv = genUV(mesh.vertices); mesh.normals = normals; mesh.RecalculateNormals(); mesh.RecalculateBounds(); // Reset the rotations of the object spriteRenderer.transform.localRotation = localRotation; spriteRenderer.transform.localScale = localScale; spriteRenderer.transform.parent = polygonParent; meshCreated = true; } }