public override InputGeometry Generate(double param0, double param1, double param2) { // Number of points on the outer circle int n = GetParamValueInt(0, param0); int count, npoints; double radius = GetParamValueInt(1, param1); // Step size on the outer circle double h = 2 * Math.PI * radius / n; // Current radius and step size double r, dphi; InputGeometry input = new InputGeometry(n + 1); // Inner cirlce (radius = 1) r = 1; npoints = (int)(2 * Math.PI * r / h); dphi = 2 * Math.PI / npoints; for (int i = 0; i < npoints; i++) { input.AddPoint(r * Math.Cos(i * dphi), r * Math.Sin(i * dphi), 1); input.AddSegment(i, (i + 1) % npoints, 1); } count = input.Count; // Center cirlce r = (radius + 1) / 2.0; npoints = (int)(2 * Math.PI * r / h); dphi = 2 * Math.PI / npoints; for (int i = 0; i < npoints; i++) { input.AddPoint(r * Math.Cos(i * dphi), r * Math.Sin(i * dphi), 2); input.AddSegment(count + i, count + (i + 1) % npoints, 2); } count = input.Count; // Outer cirlce r = radius; npoints = (int)(2 * Math.PI * r / h); dphi = 2 * Math.PI / npoints; for (int i = 0; i < npoints; i++) { input.AddPoint(r * Math.Cos(i * dphi), r * Math.Sin(i * dphi), 3); input.AddSegment(count + i, count + (i + 1) % npoints, 3); } input.AddHole(0, 0); // Regions: |++++++|++++++|---| // r 1 0 input.AddRegion((r + 3.0) / 4.0, 0, 1); input.AddRegion((3 * r + 1.0) / 4.0, 0, 2); return input; }
/// <summary> /// Rebuild the input geometry. /// </summary> private InputGeometry Rebuild() { InputGeometry geometry = new InputGeometry(mesh.vertices.Count); foreach (var vertex in mesh.vertices.Values) { geometry.AddPoint(vertex.x, vertex.y, vertex.mark); } foreach (var segment in mesh.subsegs.Values) { geometry.AddSegment(segment.P0, segment.P1, segment.Boundary); } foreach (var hole in mesh.holes) { geometry.AddHole(hole.x, hole.y); } foreach (var region in mesh.regions) { geometry.AddRegion(region.point.x, region.point.y, region.id); } return geometry; }
private static Mesh buildMesh(Dictionary<Point, Color> pointIndex) { InputGeometry g = new InputGeometry(); foreach (var value in pointIndex) { g.AddPoint(value.Key.X, value.Key.Y); } Mesh m = new Mesh(); m.Triangulate(g); return m; }
public override InputGeometry Generate(double param0, double param1, double param2) { int n = GetParamValueInt(0, param0); int m = n / 2; InputGeometry input = new InputGeometry(n + 1); double ro, r = 10; double step = 2 * Math.PI / m; // Inner ring for (int i = 0; i < m; i++) { input.AddPoint(r * Math.Cos(i * step), r * Math.Sin(i * step)); input.AddSegment(i, (i + 1) % m); } r = 1.5 * r; step = 2 * Math.PI / n; double offset = step / 2; // Outer ring for (int i = 0; i < n; i++) { ro = r; if (i % 2 == 0) { ro = r + r * Util.Random.NextDouble() * (param1 / 100); } input.AddPoint(ro * Math.Cos(i * step + offset), ro * Math.Sin(i * step + offset)); input.AddSegment(m + i, m + ((i + 1) % n)); } input.AddHole(0, 0); return input; }
public override InputGeometry Generate(double param0, double param1, double param2) { int numPoints = GetParamValueInt(0, param0); numPoints = (numPoints / 10) * 10; if (numPoints < 5) { numPoints = 5; } double exp = (param1 + 10) / 100; InputGeometry input = new InputGeometry(numPoints); int i = 0, cNum = 2 * (int)Math.Floor(Math.Sqrt(numPoints)); double r, phi, radius = 100, step = 2 * Math.PI / cNum; // Distrubute points equally on circle border for (; i < cNum; i++) { // Add a little error r = Util.Random.NextDouble(); input.AddPoint((radius + r) * Math.Cos(i * step), (radius + r) * Math.Sin(i * step)); } for (; i < numPoints; i++) { // Use sqrt(rand) to get normal distribution right. r = Math.Pow(Util.Random.NextDouble(), exp) * radius; phi = Util.Random.NextDouble() * Math.PI * 2; input.AddPoint(r * Math.Cos(phi), r * Math.Sin(phi)); } return input; }
private Mesh TriangulateMesh() { if (verts.Count > 2) { var tnMesh = new TriangleNet.Mesh(); var input = new TriangleNet.Geometry.InputGeometry(); var localVertices = verts.Select(v => spriteRenderer.transform.InverseTransformPoint(v.position)).ToArray(); for (int i = 0; i < verts.Count; i++) { verts[i].index = i; input.AddPoint(verts[i].position.x, verts[i].position.y); } foreach (var seg in segments) { if (!seg.IsDeleted()) { input.AddSegment(seg.first.index, seg.second.index); } } foreach (var hole in holes) { input.AddHole(hole.x, hole.y); } tnMesh.Triangulate(input); try { Mesh mesh = new Mesh(); mesh.vertices = localVertices; mesh.triangles = tnMesh.Triangles.ToUnityMeshTriangleIndices(); mesh.uv = genUV(mesh.vertices); mesh.RecalculateBounds(); mesh.RecalculateNormals(); return(mesh); } catch { Debug.LogError("Mesh topology was wrong. Make sure you dont have intersecting edges."); throw; } } else { return(null); } }
private static InputGeometry GetGeometryFor(IEnumerable <Vector2> circuit) { var result = new TriangleNet.Geometry.InputGeometry(circuit.Count()); foreach (var v in circuit) { result.AddPoint(v.x, v.y); } for (int i = 0; i < result.Count - 1; i++) { result.AddSegment(i, i + 1, 1); } result.AddSegment(result.Count - 1, 0, 1); return(result); }
public override InputGeometry Generate(double param0, double param1, double param2) { int numPoints = GetParamValueInt(0, param0); numPoints = (numPoints / 10) * 10; if (numPoints < 5) { numPoints = 5; } InputGeometry input = new InputGeometry(numPoints); int width = GetParamValueInt(1, param1); int height = GetParamValueInt(2, param2); for (int i = 0; i < numPoints; i++) { input.AddPoint(Util.Random.NextDouble() * width, Util.Random.NextDouble() * height); } return input; }
/// <summary> /// Read vertex information of the given line. /// </summary> /// <param name="data">The input geometry.</param> /// <param name="index">The current vertex index.</param> /// <param name="line">The current line.</param> /// <param name="attributes">Number of point attributes</param> /// <param name="marks">Number of point markers (0 or 1)</param> static void ReadVertex(InputGeometry data, int index, string[] line, int attributes, int marks) { float x = float.Parse(line[1], nfi); float y = float.Parse(line[2], nfi); int mark = 0; float[] attribs = attributes == 0 ? null : new float[attributes]; // Read the vertex attributes. for (int j = 0; j < attributes; j++) { if (line.Length > 3 + j) { attribs[j] = float.Parse(line[3 + j]); } } // Read a vertex marker. if (marks > 0 && line.Length > 3 + attributes) { mark = int.Parse(line[3 + attributes]); } data.AddPoint(x, y, mark, attribs); }
public Mesh CreateMeshFromVerts(Vector3[] vertsToCopy, Mesh mesh, List <int> pathSplitIds, Transform SpriteGO = null) { Sprite spr = new Sprite(); Rect rec = new Rect(); Vector3 bound = Vector3.zero; TextureImporter textureImporter = new TextureImporter(); if (SpriteGO != null && SpriteGO.GetComponent <SpriteRenderer>() && SpriteGO.GetComponent <SpriteRenderer>().sprite) { spr = SpriteGO.GetComponent <SpriteRenderer>().sprite; rec = spr.rect; bound = SpriteGO.GetComponent <Renderer>().bounds.max - SpriteGO.GetComponent <Renderer>().bounds.min; 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 (Vector3 p in vertsToCopy) { geometry.AddPoint(p.x, p.y); } //Add segments int prevEnd = 0; for (int i = 0; i < vertsToCopy.Length - 1; i++) { if (!pathSplitIds.Contains(i + 1)) { geometry.AddSegment(i, i + 1); //Debug.Log ("joining " + i + " to " + (i + 1)); } else { geometry.AddSegment(i, prevEnd); prevEnd = i + 1; } } if (pathSplitIds.Count <= 1) { //Debug.Log ("joining " + (vertsToCopy.Length - 1) + " to 0"); geometry.AddSegment(vertsToCopy.Length - 1, 0); } //Triangulate, refine and smooth TriangleNet.Mesh triangleNetMesh = new TriangleNet.Mesh(); triangleNetMesh.Triangulate(geometry); //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); if (SpriteGO != null && SpriteGO.GetComponent <SpriteRenderer>()) { 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; } mesh.vertices = vertices; mesh.triangles = triangles; mesh.uv = uvs; mesh.normals = normals; return(mesh); }
public static void Triangulate(List<Vector2> vertices, List<IndexedEdge> edges, List<Hole> holes,ref List<int> indices) { indices.Clear(); if(vertices.Count >= 3) { InputGeometry inputGeometry = new InputGeometry(vertices.Count); for(int i = 0; i < vertices.Count; ++i) { Vector2 position = vertices[i]; inputGeometry.AddPoint(position.x,position.y); } for(int i = 0; i < edges.Count; ++i) { IndexedEdge edge = edges[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 trangleMesh = new TriangleNet.Mesh(); trangleMesh.Triangulate(inputGeometry); foreach (TriangleNet.Data.Triangle triangle in trangleMesh.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 static List<SampleTri> BuildMesh(Dictionary<Point, Pixel> pointIndex) { InputGeometry g = new InputGeometry(); foreach (var value in pointIndex) { g.AddPoint(value.Key.X, value.Key.Y); } Mesh m = new Mesh(); m.Triangulate(g); List<SampleTri> sampleMesh = new List<SampleTri>(); Dictionary<ITriangle, SampleTri> table = new Dictionary<ITriangle, SampleTri>(); Dictionary<Point, Sample> sampleTable = new Dictionary<Point, Sample>(); foreach (var mTri in m.Triangles) { SampleTri tri = new SampleTri(mTri); for (int i = 0; i < 3; i++) tri.TriangleNeighbours.Add(mTri.GetNeighbor(i)); sampleMesh.Add(tri); table.Add(mTri, tri); if (sampleTable.ContainsKey(tri.U.Point)) tri.U = sampleTable[tri.U.Point]; else sampleTable[tri.U.Point] = tri.U; if (sampleTable.ContainsKey(tri.V.Point)) tri.V = sampleTable[tri.V.Point]; else sampleTable[tri.V.Point] = tri.V; if (sampleTable.ContainsKey(tri.W.Point)) tri.W = sampleTable[tri.W.Point]; else sampleTable[tri.W.Point] = tri.W; } foreach (var tri in sampleMesh) { foreach (var triangleNeighbour in tri.TriangleNeighbours) { if (triangleNeighbour != null) tri.SampleTriNeighbours.Add(table[triangleNeighbour]); } tri.U.Triangles.Add(tri); tri.V.Triangles.Add(tri); tri.W.Triangles.Add(tri); tri.U.Color = pointIndex[tri.U.Point]; tri.V.Color = pointIndex[tri.V.Point]; tri.W.Color = pointIndex[tri.W.Point]; tri.CenterColor = tri.U.Color; } return sampleMesh; }
public Mesh TriangulateMesh(Vector3[] Vertices) { if (Vertices.Length < 3) { return(null); } geometry = new InputGeometry(); foreach (Vector3 Vert in Vertices) { geometry.AddPoint(Vert.x, Vert.y); } List <Point> points = new List <Point>(); for (float offsetX = -distance; offsetX < distance; offsetX += boxDistance) { for (float offsetY = -verticalDistance; offsetY < verticalDistance; offsetY += boxDistance) { Vector2 offset = new Vector2(offsetX, offsetY) + Vector2.one * boxDistance * 0.5f; float radians = Random.Range(0, 2 * Mathf.PI); float length = Random.Range(0, circleDistance); Vector2 pos = new Vector2(Mathf.Cos(radians), Mathf.Sin(radians)) * length; pos += offset; } } meshRepresentation = new TriangleNet.Mesh(); meshRepresentation.Triangulate(geometry); //generate mesh based on triangulation Dictionary <int, float> zOffsets = new Dictionary <int, float>(); foreach (KeyValuePair <int, TriangleNet.Data.Vertex> pair in meshRepresentation.vertices) { zOffsets.Add(pair.Key, Random.Range(-zOffset, zOffset)); } int triangleIndex = 0; List <Vector3> vertices = new List <Vector3>(meshRepresentation.triangles.Count * 3); List <int> triangleIndices = new List <int>(meshRepresentation.triangles.Count * 3); foreach (KeyValuePair <int, TriangleNet.Data.Triangle> pair in meshRepresentation.triangles) { TriangleNet.Data.Triangle triangle = pair.Value; TriangleNet.Data.Vertex vertex0 = triangle.GetVertex(0); TriangleNet.Data.Vertex vertex1 = triangle.GetVertex(1); TriangleNet.Data.Vertex vertex2 = triangle.GetVertex(2); Vector3 p0 = new Vector3(vertex0.x, vertex0.y, zOffsets[vertex0.id]); Vector3 p1 = new Vector3(vertex1.x, vertex1.y, zOffsets[vertex1.id]); Vector3 p2 = new Vector3(vertex2.x, vertex2.y, zOffsets[vertex2.id]); vertices.Add(p0); vertices.Add(p1); vertices.Add(p2); triangleIndices.Add(triangleIndex + 2); triangleIndices.Add(triangleIndex + 1); triangleIndices.Add(triangleIndex); triangleIndex += 3; } mesh = new Mesh(); mesh.name = "Triangulated Terrain"; mesh.vertices = vertices.ToArray(); mesh.triangles = triangleIndices.ToArray(); return(mesh); }
public static PolyGisLayer CreateFromContour(Game engine, DVector2[] lonLatRad, Color color) { var triangulator = new TriangleNet.Mesh(); triangulator.Behavior.Algorithm = TriangulationAlgorithm.SweepLine; InputGeometry ig = new InputGeometry(); ig.AddPoint(lonLatRad[0].X, lonLatRad[0].Y); for (int v = 1; v < lonLatRad.Length; v++) { ig.AddPoint(lonLatRad[v].X, lonLatRad[v].Y); ig.AddSegment(v-1, v); } ig.AddSegment(lonLatRad.Length - 1, 0); triangulator.Triangulate(ig); if (triangulator.Vertices.Count != lonLatRad.Length) { Log.Warning("Vertices count not match"); return null; } var points = new List<Gis.GeoPoint>(); foreach (var pp in triangulator.Vertices) { points.Add(new Gis.GeoPoint { Lon = pp.X, Lat = pp.Y, Color = color }); } var indeces = new List<int>(); foreach (var tr in triangulator.Triangles) { indeces.Add(tr.P0); indeces.Add(tr.P1); indeces.Add(tr.P2); } return new PolyGisLayer(engine, points.ToArray(), indeces.ToArray(), true) { Flags = (int)(PolyFlags.NO_DEPTH | PolyFlags.DRAW_TEXTURED | PolyFlags.CULL_NONE | PolyFlags.VERTEX_SHADER | PolyFlags.PIXEL_SHADER | PolyFlags.USE_PALETTE_COLOR) }; }
public WaterSurfacePolygon(List<Point> points) { mesh = new TriangleNet.Mesh(); mesh.Behavior.Quality = true; this.points = points; triangleNormals = new List<Point>(); trianglePlaneEquationDs = new List<double>(); InputGeometry geomtery = new InputGeometry(); for (int i = 0; i < points.Count; i++) { Point p = points[i]; if (i == 0) { minX = maxX = p.X; minY = maxY = p.Y; minZ = maxZ = p.Z; } else { minX = Math.Min(p.X, minX); maxX = Math.Max(p.X, maxX); minY = Math.Min(p.Y, minY); maxY = Math.Max(p.Y, maxY); minZ = Math.Min(p.Z, minZ); maxZ = Math.Max(p.Z, maxZ); } geomtery.AddPoint(p.X, p.Y, 0, p.Z); //add segments if (i > 0) { geomtery.AddSegment(i - 1, i, 0); } if (i == points.Count - 1) { geomtery.AddSegment(i, 0, 0); } } mesh.Triangulate(geomtery); triangles = new List<TriangleNet.Data.Triangle>(); foreach (TriangleNet.Data.Triangle tr in mesh.Triangles) { if (tr.P0 < points.Count && tr.P1 < points.Count && tr.P2 < points.Count) { triangles.Add(tr); } } calculateNormalsAndDs(); }
static void SearchTree(InputGeometry inputGeometry, ref int pointIndex, PolyNode node) { foreach (PolyNode childNode in node.Childs) { int startIndex = pointIndex; foreach (Vector2 point in childNode.Contour) { inputGeometry.AddPoint(point.X, point.Y); if (pointIndex > startIndex) inputGeometry.AddSegment(pointIndex - 1, pointIndex); pointIndex++; } inputGeometry.AddSegment(pointIndex - 1, startIndex); if (childNode.IsHole) { for (int i = 0, j = childNode.Contour.Count - 1, k = childNode.Contour.Count - 2; i < childNode.Contour.Count; k = j, j = i, i++) { Vector2 a1 = childNode.Contour[k]; Vector2 a2 = childNode.Contour[j]; Vector2 a3 = childNode.Contour[i]; if (Vector2.VectorProduct(a2 - a1, a3 - a1) < 0) { Vector2 c = (a1 + a3) / 2; Vector2 d = a2 - c; float x = c.Length * 2; Vector2 hole; do { x /= 2; hole = c + (1 - x) * d; } while (!IsInside(childNode, hole)); x /= 512; hole = c + (1 - x) * d; inputGeometry.AddHole(hole.X, hole.Y); break; } } } SearchTree(inputGeometry, ref pointIndex, childNode); } }
private void ReadPoints(InputGeometry geometry, Dictionary<string, object> points, ref int count) { ArrayList data = points["data"] as ArrayList; ArrayList markers = null; ArrayList attributes = null; if (points.ContainsKey("markers")) { markers = points["markers"] as ArrayList; } if (points.ContainsKey("attributes")) { attributes = points["attributes"] as ArrayList; } if (data != null) { int mark, n = data.Count; if (n % 2 != 0) { throw new Exception("JSON format error (points)."); } // Number of points count = n / 2; for (int i = 0; i < n; i += 2) { mark = 0; if (markers != null && markers.Count == count) { mark = int.Parse(markers[i / 2].ToString()); } geometry.AddPoint( double.Parse(data[i].ToString(), Util.Nfi), double.Parse(data[i + 1].ToString(), Util.Nfi), mark ); } } }
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; } }
void SearchTree(InputGeometry inputGeometry, ref int pointIndex, PolyNode node) { foreach (PolyNode childNode in node.Childs) { int startIndex = pointIndex; foreach (ControlPoint point in childNode.Contour) { inputGeometry.AddPoint(point.X, point.Y); if (pointIndex > startIndex) inputGeometry.AddSegment(pointIndex - 1, pointIndex); pointIndex++; } inputGeometry.AddSegment(pointIndex - 1, startIndex); if (childNode.IsHole) { for (int i = 0, j = childNode.Contour.Count - 1, k = childNode.Contour.Count - 2; i < childNode.Contour.Count; k = j, j = i, i++) { ControlPoint a1 = childNode.Contour[k]; ControlPoint a2 = childNode.Contour[j]; ControlPoint a3 = childNode.Contour[i]; if (ControlPoint.VectorProduct(a2 - a1, a3 - a1) < 0) { ControlPoint c = ((a1 + a3) / 2) - a2; double x = 2; ControlPoint hole; do { x /= 2; hole = a2 + (c * x); } while (!IsInside(childNode, hole)); inputGeometry.AddHole(hole.X, hole.Y); break; } } } SearchTree(inputGeometry, ref pointIndex, childNode); } }
public void CreateSubdividedMesh(Vector2[] vertsToCopy, Transform transform, int smoothLevel) { Sprite spr = transform.GetComponent<SpriteRenderer>().sprite; Rect rec = spr.rect; Vector3 bound = transform.GetComponent<Renderer>().bounds.max- transform.GetComponent<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(); if(smoothLevel>0) triangleNetMesh.behavior.MinAngle = 10; triangleNetMesh.Triangulate(geometry); if (smoothLevel > 0) { 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 Mesh CreateMeshFromVerts(Vector3[] vertsToCopy, Mesh mesh, List<int> pathSplitIds, Transform SpriteGO = null) { Sprite spr = new Sprite(); Rect rec = new Rect(); Vector3 bound = Vector3.zero; TextureImporter textureImporter = new TextureImporter(); if(SpriteGO !=null && SpriteGO.GetComponent<SpriteRenderer>() && SpriteGO.GetComponent<SpriteRenderer>().sprite) { spr = SpriteGO.GetComponent<SpriteRenderer>().sprite; rec = spr.rect; bound = SpriteGO.GetComponent<Renderer>().bounds.max- SpriteGO.GetComponent<Renderer>().bounds.min ; 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 (Vector3 p in vertsToCopy) { geometry.AddPoint(p.x,p.y); } //Add segments int prevEnd = 0; for (int i=0;i<vertsToCopy.Length-1;i++) { if (!pathSplitIds.Contains (i+1)) { geometry.AddSegment (i, i + 1); //Debug.Log ("joining " + i + " to " + (i + 1)); } else { geometry.AddSegment (i, prevEnd); prevEnd = i + 1; } } if (pathSplitIds.Count <= 1) { //Debug.Log ("joining " + (vertsToCopy.Length - 1) + " to 0"); geometry.AddSegment(vertsToCopy.Length - 1, 0); } //Triangulate, refine and smooth TriangleNet.Mesh triangleNetMesh = new TriangleNet.Mesh(); triangleNetMesh.Triangulate(geometry); //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); if (SpriteGO != null && SpriteGO.GetComponent<SpriteRenderer>() ) { 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; } mesh.vertices = vertices; mesh.triangles = triangles; mesh.uv = uvs; mesh.normals = normals; return mesh; }
private Mesh TriangulateMesh() { if (verts.Count > 2) { var tnMesh = new TriangleNet.Mesh(); var input = new TriangleNet.Geometry.InputGeometry(); var localVertices = verts.Select(v => spriteRenderer.transform.InverseTransformPoint(v.position)).ToArray(); for(int i = 0; i < verts.Count; i++) { verts[i].index = i; input.AddPoint(verts[i].position.x, verts[i].position.y); } foreach(var seg in segments) { if(!seg.IsDeleted()) input.AddSegment(seg.first.index, seg.second.index); } foreach(var hole in holes) { input.AddHole(hole.x, hole.y); } tnMesh.Triangulate(input); try { Mesh mesh = new Mesh(); mesh.vertices = localVertices; mesh.triangles = tnMesh.Triangles.ToUnityMeshTriangleIndices(); mesh.uv = genUV(mesh.vertices); mesh.RecalculateBounds(); mesh.RecalculateNormals(); return mesh; } catch { Debug.LogError("Mesh topology was wrong. Make sure you dont have intersecting edges."); throw; } } else { return null; } }
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); } } } }
void InitBuildingsOSM() { var osm = Game.GetService<LayerService>().OpenStreetMapSource; List<GeoVert> lines = new List<GeoVert>(); List<GeoVert> simple = new List<GeoVert>(); var nodes = osm.allNodes; int k = 0; foreach (var way in osm.allWays) { if (!way.Value.isBuilding) continue; var centerMerc = way.Value.BBox.Center(); float width = (way.Value.BBox.Maximum - way.Value.BBox.Minimum).X * 10000.0f; float length = (way.Value.BBox.Maximum - way.Value.BBox.Minimum).Y * 10000.0f; double lon, lat; GeoHelper.TileToWorldPos(centerMerc.X, centerMerc.Y, 0, out lon, out lat); simple.Add(new GeoVert { Lon = DMathUtil.DegreesToRadians(lon), Lat = DMathUtil.DegreesToRadians(lat), Color = Color.White, Position = Vector3.Zero, Tex = new Vector4(width, length, 0, 0) }); List<DVector2> buildingVertices = new List<DVector2>(); for (int i = 0; i < way.Value.nodeRef.Length - 1; i++) { var nInds = way.Value.nodeRef; lines.Add(new GeoVert { Lon = DMathUtil.DegreesToRadians(nodes[nInds[i]].Longitude), Lat = DMathUtil.DegreesToRadians(nodes[nInds[i]].Latitude), Position = new Vector3(1.0f, 0.0f, 0.0f), Color = Color.Yellow, Tex = Vector4.Zero }); lines.Add(new GeoVert { Lon = DMathUtil.DegreesToRadians(nodes[nInds[i+1]].Longitude), Lat = DMathUtil.DegreesToRadians(nodes[nInds[i+1]].Latitude), Position = new Vector3(1.0f, 0.0f, 0.0f), Color = Color.Yellow, Tex = Vector4.Zero }); buildingVertices.Add(new DVector2(nodes[nInds[i]].Longitude, nodes[nInds[i]].Latitude)); } buildingVertices.Add(new DVector2(nodes[way.Value.nodeRef[way.Value.nodeRef.Length - 1]].Longitude, nodes[way.Value.nodeRef[way.Value.nodeRef.Length - 1]].Latitude)); ///////////////////////////////////////// var mesh = new Mesh(); mesh.Behavior.Quality = false; mesh.Behavior.MinAngle = 25; mesh.Behavior.Convex = false; var ig = new InputGeometry(); ig.AddPoint(buildingVertices[0].X, buildingVertices[0].Y); for (int v = 1; v < buildingVertices.Count; v++) { ig.AddPoint(buildingVertices[v].X, buildingVertices[v].Y); ig.AddSegment(v - 1, v); } ig.AddSegment(buildingVertices.Count - 1, 0); mesh.Triangulate(ig); int n = mesh.Vertices.Count; mesh.Renumber(); buildings = new GeoVert[mesh.Triangles.Count*3]; int ind = 0; foreach (var triangle in mesh.Triangles) { buildings[ind++] = new GeoVert { Lon = DMathUtil.DegreesToRadians(mesh.Vertices.ElementAt(triangle.P0).X), Lat = DMathUtil.DegreesToRadians(mesh.Vertices.ElementAt(triangle.P0).Y), Position = new Vector3(0.1f, 0.0f, 0.0f), Color = Color.Green, Tex = Vector4.Zero }; buildings[ind++] = new GeoVert { Lon = DMathUtil.DegreesToRadians(mesh.Vertices.ElementAt(triangle.P1).X), Lat = DMathUtil.DegreesToRadians(mesh.Vertices.ElementAt(triangle.P1).Y), Position = new Vector3(0.1f, 0.0f, 0.0f), Color = Color.Green, Tex = Vector4.Zero }; buildings[ind++] = new GeoVert { Lon = DMathUtil.DegreesToRadians(mesh.Vertices.ElementAt(triangle.P2).X), Lat = DMathUtil.DegreesToRadians(mesh.Vertices.ElementAt(triangle.P2).Y), Position = new Vector3(0.1f, 0.0f, 0.0f), Color = Color.Green, Tex = Vector4.Zero }; } ///////////////////////////////////////// k++; if (k >= 1) break; } simpleBuildings = simple.ToArray(); contourBuildings = lines.ToArray(); contourBuildingsVB = new VertexBuffer(Game.GraphicsDevice, typeof (GeoVert), contourBuildings.Length); contourBuildingsVB.SetData(contourBuildings, 0, contourBuildings.Length); simpleBuildingsVB = new VertexBuffer(Game.GraphicsDevice, typeof(GeoVert), simpleBuildings.Length); simpleBuildingsVB.SetData(simpleBuildings, 0, simpleBuildings.Length); buildingsVB = new VertexBuffer(Game.GraphicsDevice, typeof(GeoVert), buildings.Length); buildingsVB.SetData(buildings, 0, buildings.Length); }
/// <summary> /// Get a list of triangles which will fill the area described by the slice /// </summary> public IEnumerable<Triangle> Triangles() { TriangleNet.Behavior behavior = new TriangleNet.Behavior(); behavior.ConformingDelaunay = true; foreach (var poly in IndividualPolygons()) { PolyNode node = polyTree.GetFirst(); InputGeometry geometry = new InputGeometry(); while (node != null) { var offset = geometry.Points.Count(); var index = 0; foreach (IntPoint point in node.Contour) { geometry.AddPoint(point.X, point.Y); if (index > 0) { geometry.AddSegment(index - 1 + offset, index + offset); } index++; } geometry.AddSegment(index - 1 + offset, offset); if (node.IsHole) { // To describe a hole, AddHole must be called with a location inside the hole. IntPoint last = new IntPoint(0, 0); bool lastKnown = false; double longest = 0; IntPoint longestAlong = new IntPoint(0, 0); IntPoint from = new IntPoint(0, 0); foreach (IntPoint point in node.Contour) { if (lastKnown) { IntPoint along = new IntPoint(point.X - last.X, point.Y - last.Y); double length = Math.Sqrt(along.X * along.X + along.Y * along.Y); if (length > longest) { longest = length; longestAlong = along; from = last; } } last = point; lastKnown = true; } if (longest > 0) { double perpendicularX = ((double)longestAlong.Y * (double)scale * 0.001d) / longest; double perpendicularY = -((double)longestAlong.X * (double)scale * 0.001d) / longest; geometry.AddHole(perpendicularX + from.X + longestAlong.X / 2.0d, perpendicularY + from.Y + longestAlong.Y / 2.0d); } else { } } node = node.GetNext(); } if (geometry.Points.Count() > 0) { var mesh = new TriangleNet.Mesh(behavior); mesh.Triangulate(geometry); mesh.Renumber(); foreach (Triangle t in this.GetMeshTriangles(mesh)) { yield return t; } } } }
/// <summary> /// /// </summary> /// <param name="name"></param> /// <param name="contour"></param> void AddMunicipalDivision(string name, List<DVector2> contour) { if (municipalDivisions.ContainsKey(name)) return; var mesh = new TriangleNet.Mesh(); mesh.Behavior.Quality = true; mesh.Behavior.MinAngle = 25; mesh.Behavior.Convex = false; var ig = new InputGeometry(); ig.AddPoint(contour[0].X, contour[0].Y); for (int v = 1; v < contour.Count; v++) { ig.AddPoint(contour[v].X, contour[v].Y); ig.AddSegment(v - 1, v); } ig.AddSegment(contour.Count - 1, 0); mesh.Triangulate(ig); int n = mesh.Vertices.Count; mesh.Renumber(); // Vertices var moVerts = new GeoVert[n]; int i = 0; foreach (var pt in mesh.Vertices) { moVerts[i] = new GeoVert { Lon = pt.X * Math.PI / 180.0, Lat = pt.Y * Math.PI / 180.0, Position = Vector3.Zero, Tex = Vector4.Zero, Color = Color.White }; i++; } // Triangles var triangles = new int[3 * mesh.Triangles.Count]; i = 0; foreach (var tri in mesh.Triangles) { triangles[i * 3 + 0] = tri.P0; triangles[i * 3 + 1] = tri.P1; triangles[i * 3 + 2] = tri.P2; i++; } // Contour vertices var contourVerts = new GeoVert[contour.Count*2]; contourVerts[1] = new GeoVert { Lon = contour[0].X * Math.PI / 180.0, Lat = contour[0].Y * Math.PI / 180.0, Position = Vector3.Zero, Tex = Vector4.Zero, Color = Color.Red }; for (int j = 1; j < contour.Count; j++) { contourVerts[2*j+1] = new GeoVert { Lon = contour[j].X * Math.PI / 180.0, Lat = contour[j].Y * Math.PI / 180.0, Position = Vector3.Zero, Tex = Vector4.Zero, Color = Color.Red }; contourVerts[2*j] = contourVerts[2*(j - 1) + 1]; } contourVerts[0] = contourVerts[contourVerts.Length-1]; // Create buffers var vb = new VertexBuffer(Game.GraphicsDevice, typeof (GeoVert), moVerts.Length); var inds = new IndexBuffer(Game.GraphicsDevice, triangles.Length); var cont = new VertexBuffer(Game.GraphicsDevice, typeof (GeoVert), contourVerts.Length); vb.SetData(moVerts, 0, moVerts.Length); inds.SetData(triangles, 0, triangles.Length); cont.SetData(contourVerts, 0, contourVerts.Length); municipalDivisions.Add(name, new MD { Contour = cont, Indeces = inds, Vertices = vb, Value = r.NextFloat(0.0f, 1.0f) }); }
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]; 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; } }
public override InputGeometry Generate(double param0, double param1, double param2) { int numPoints = GetParamValueInt(1, param1); InputGeometry input = new InputGeometry(numPoints + 4); double x, y, step = 2 * Math.PI / numPoints; double r = GetParamValueInt(2, param2); // Generate circle for (int i = 0; i < numPoints; i++) { x = r * Math.Cos(i * step); y = r * Math.Sin(i * step); input.AddPoint(x, y, 2); input.AddSegment(i, (i + 1) % numPoints, 2); } numPoints = input.Count; int numPointsB = GetParamValueInt(0, param0); // Box sides are 100 units long step = 100.0 / numPointsB; // Left box boundary points for (int i = 0; i < numPointsB; i++) { input.AddPoint(-50, -50 + i * step, 1); } // Top box boundary points for (int i = 0; i < numPointsB; i++) { input.AddPoint(-50 + i * step, 50, 1); } // Right box boundary points for (int i = 0; i < numPointsB; i++) { input.AddPoint(50, 50 - i * step, 1); } // Bottom box boundary points for (int i = 0; i < numPointsB; i++) { input.AddPoint(50 - i * step, -50, 1); } // Add box segments for (int i = numPoints; i < input.Count - 1; i++) { input.AddSegment(i, i + 1, 1); } // Add last segments which closes the box input.AddSegment(input.Count - 1, numPoints, 1); // Add hole input.AddHole(0, 0); return input; }
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; }
/// <summary> /// Read vertex information of the given line. /// </summary> /// <param name="data">The input geometry.</param> /// <param name="index">The current vertex index.</param> /// <param name="line">The current line.</param> /// <param name="attributes">Number of point attributes</param> /// <param name="marks">Number of point markers (0 or 1)</param> static void ReadVertex(InputGeometry data, int index, string[] line, int attributes, int marks) { double x = double.Parse(line[1], nfi); double y = double.Parse(line[2], nfi); int mark = 0; double[] attribs = attributes == 0 ? null : new double[attributes]; // Read the vertex attributes. for (int j = 0; j < attributes; j++) { if (line.Length > 3 + j) { attribs[j] = double.Parse(line[3 + j], CultureInfo.InvariantCulture); } } // Read a vertex marker. if (marks > 0 && line.Length > 3 + attributes) { mark = int.Parse(line[3 + attributes]); } data.AddPoint(x, y, mark, attribs); }