public Mesh CreateMeshFromPoints(bool combine) { if (spriteRenderer != null && points.Length > 2) { int pointNum = points.Length; if (combine && combineMesh != null) { pointNum = points.Length + combineMesh.vertices.Length; } //Create triangle.NET geometry TriangleNet.Geometry.InputGeometry geometry = new TriangleNet.Geometry.InputGeometry(pointNum); geometry.AddPolygon(points); if (combine && combineMesh != null) { geometry.AddPolygon(combineMesh.vertices.Select(x => (Vector2)x).ToArray()); } //Triangulate TriangleNet.Mesh triangleMesh = new TriangleNet.Mesh(); triangleMesh.Triangulate(geometry); //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 = triangleMesh.Triangles.ToUnityMeshTriangleIndices(); mesh.Clear(); mesh = new Mesh(); mesh.vertices = vertices; mesh.triangles = triangles; mesh.uv = genUV(mesh.vertices); mesh.normals = normals; return(mesh); } else { return(null); } }
// 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); }
// 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 = 30; TriMesh.Triangulate(geometry); Debug.Log("Size : " + TriMesh.Vertices.Count); int i = 0; foreach (var pt in TriMesh.Vertices) { Debug.Log(i++ + " : " + pt.X + "," + pt.Y); } foreach (var tri in TriMesh.Triangles) { /*Debug.Log(tri.)*/ } FileWriter.Write(TriMesh, "Assets/Plugins/Data/superior_mesh.ele"); }
/// <summary> /// Add a polygon ring to the geometry and make it a hole. /// </summary> /// <remarks> /// WARNING: This works for convex polygons, but not for non-convex regions in general. /// </remarks> /// <param name="points">List of points which make up the hole.</param> /// <param name="mark">Common boundary mark for all segments of the hole.</param> public static void AddRingAsHole(this InputGeometry geometry, IEnumerable<TriangleNet.Geometry.Point> points, int mark = 0) { // Save the current number of points. int N = geometry.Count; int m = 0; foreach (var pt in points) { geometry.AddPoint(pt.X, pt.Y, pt.Boundary, pt.Attributes); m++; } for (int i = 0; i < m; i++) { geometry.AddSegment(N + i, N + ((i + 1) % m), mark); } //a lényeg az hogy kell egy a lyukon lévő pont,hogy jelezze hogy az egy lyuk poligon... a legegyszerübb trükk a következő, az egybefüggő (akár konkáv) poligont háromszögesítem, ezzel nincs gond, ezután kiválasztok egy testzőleges háromszöget, és veszem annak a középpontját..ez már tuti hogy a nagy poligon belső pontja TriangleNetMesh mesh = new TriangleNetMesh(); var inputGeometry = new InputGeometry(); inputGeometry.AddRing(points); mesh.Triangulate(inputGeometry); var firstTriangle = new List<Triangle>(mesh.Triangles)[0]; double x = 0.0; double y = 0.0; for (int iii = 0; iii < 3; iii++) { var vertex = firstTriangle.GetVertex(iii); x += vertex.X; y += vertex.Y; } geometry.AddHole(x / 3, y / 3); }
public static UnityEngine.Mesh Mesh(this Polygon this_, string name = "") { // Create geometry. InputGeometry geometry = this_.InputGeometry(); // Triangulate. TriangleNet.Mesh triangulatedMesh = new TriangleNet.Mesh(); triangulatedMesh.Triangulate(geometry); // Counts. int vertexCount = triangulatedMesh.vertices.Count; int triangleCount = triangulatedMesh.triangles.Count; // Debug.Log("Mesh.vertexCount ("+vertexCount+")"); // NumberOfInputPoints // Debug.Log("Mesh.triangleCount ("+triangleCount+")"); // NumberOfInputPoints // Mesh store. Vector3[] _vertices = new Vector3[vertexCount]; Vector2[] _uv = new Vector2[vertexCount]; Vector3[] _normals = new Vector3[vertexCount]; int[] _triangles = new int[triangleCount * 3]; foreach (KeyValuePair <int, TriangleNet.Data.Vertex> eachEntry in triangulatedMesh.vertices) { int index = eachEntry.Key; TriangleNet.Data.Vertex eachVertex = eachEntry.Value; _vertices[index] = new Vector3( (float)eachVertex.x, (float)eachVertex.y, 0.0f // As of 2D ); _uv[index] = _vertices[index]; _normals[index] = Vector3.forward; } int cursor = 0; foreach (KeyValuePair <int, TriangleNet.Data.Triangle> eachPair in triangulatedMesh.triangles) { TriangleNet.Data.Triangle eachTriangle = eachPair.Value; _triangles[cursor] = eachTriangle.P2; _triangles[cursor + 1] = eachTriangle.P1; _triangles[cursor + 2] = eachTriangle.P0; cursor += 3; } // Create / setup mesh. Mesh mesh = new Mesh(); mesh.vertices = _vertices; mesh.uv = _uv; mesh.normals = _normals; mesh.subMeshCount = 1; mesh.SetTriangles(_triangles, 0); mesh.name = name; return(mesh); }
public static TriangleNet.Mesh Generate(IEnumerable <Vector2> circuit) { var mesh = new TriangleNet.Mesh(Behavior); var geometry = GetGeometryFor(circuit); mesh.Triangulate(geometry); return(mesh); }
Mesh generateFaceMesh(ShapePoints shape) { var mesh = new Mesh(); var verts = new List <Vector3>(); var tris = new List <int>(); var uvs = new List <Vector2>(); var uv2 = new List <Vector2>(); var geometry = new InputGeometry(); for (int i = 0; i < shape.edge.Length; ++i) { var pt = shape.edge[i]; geometry.AddPoint(pt.x, pt.y); verts.Add(pt.p.AsVector3(-pt.groundness * _groundPull)); uvs.Add(pt.p); uv2.Add(new Vector2(pt.groundness * pt.groundness, 0)); geometry.AddSegment(i, (i + 1) % shape.edge.Length); } for (int i = 0; i < shape.interior.Length; ++i) { var pt = shape.interior[i]; geometry.AddPoint(pt.x, pt.y); verts.Add(pt.p.AsVector3(-pt.groundness * _groundPull + UnityEngine.Random.value * 0.4f)); uvs.Add(pt.p); uv2.Add(new Vector2(pt.groundness * pt.groundness, 0)); } var behave = new TriangleNet.Behavior(); behave.Algorithm = TriangleNet.TriangulationAlgorithm.Incremental; var meshRepresentation = new TriangleNet.Mesh(behave); meshRepresentation.Triangulate(geometry); foreach (var tri in meshRepresentation.Triangles) { tris.Add(tri.GetVertex(2).ID); tris.Add(tri.GetVertex(1).ID); tris.Add(tri.GetVertex(0).ID); } mesh.vertices = verts.ToArray(); mesh.triangles = tris.ToArray(); mesh.uv = uvs.ToArray(); mesh.uv2 = uv2.ToArray(); mesh.RecalculateNormals(); mesh.RecalculateBounds(); 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 void Triangulate() { indices.Clear(); if (texVertices.Count >= 3) { InputGeometry inputGeometry = new InputGeometry(texVertices.Count); for (int i = 0; i < texVertices.Count; ++i) { Vector2 vertex = texVertices[i].vertex; inputGeometry.AddPoint(vertex.x, vertex.y); } for (int i = 0; i < edges.Count; ++i) { Edge edge = edges[i]; inputGeometry.AddSegment(texVertices.IndexOf(edge.vertex1), texVertices.IndexOf(edge.vertex2)); } 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 < texVertices.Count && triangle.P0 >= 0 && triangle.P1 < texVertices.Count && triangle.P0 >= 0 && triangle.P2 < texVertices.Count) { indices.Add(triangle.P0); indices.Add(triangle.P2); indices.Add(triangle.P1); } } } isDirty = true; }
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 triangleMesh = new TriangleNet.Mesh(); triangleMesh.Triangulate(inputGeometry); 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); } } } }
/// <summary> /// Creates a surface from the given points. /// </summary> /// <param name="points">Input points</param> /// <param name="surface">The type of surface being operated on</param> public void SurfaceFromPoints(Point3dCollection points, SurfaceType surface) { TriangleNet.Mesh mesh = new TriangleNet.Mesh(); TriangleNet.Geometry.InputGeometry geometry = new TriangleNet.Geometry.InputGeometry(points.Count); foreach (Point3d point in points) { geometry.AddPoint(point.X, point.Y, 0, point.Z); } mesh.Triangulate(geometry); if (surface == SurfaceType.Original) { originalSurface = mesh; } else { proposedSurface = mesh; } }
public static TriangleNet.Mesh TriangulateMesh(List <PointF> path, float minAngle, float maxAngle, bool conformingDelaunay, bool quality, bool convex) { if (path == null) { return(null); } if (path.Count <= 2) { return(null); } List <FTriangle> outTris = new List <FTriangle>(); MeshRenderer.Core.RenderData renderData = new MeshRenderer.Core.RenderData(); MeshRenderer.Core.RenderManager renderManager = new MeshRenderer.Core.RenderManager(); TriangleNet.Geometry.InputGeometry input = new TriangleNet.Geometry.InputGeometry(path.Count); TriangleNet.Mesh mesh = new TriangleNet.Mesh(); input.AddPoint(path[0].X, path[0].Y); for (int i = 1; i < path.Count; i++) { input.AddPoint(path[i].X, path[i].Y); input.AddSegment(i - 1, i); } input.AddSegment(path.Count - 1, 0); renderData.SetInputGeometry(input); renderManager.CreateDefaultControl(); renderManager.SetData(renderData); mesh.Behavior.MinAngle = FMath.Clamp(0, 40, minAngle); mesh.Behavior.MaxAngle = FMath.Clamp(80, 180, maxAngle); mesh.Behavior.ConformingDelaunay = conformingDelaunay; mesh.Behavior.Quality = quality; mesh.Behavior.Convex = convex; mesh.Triangulate(input); return(mesh); }
private void RunTessellation(List <SampleVertexData> lVerts, MTMeshData.LOD lod) { if (lVerts.Count < 3) { ++curIdx; return; } InputGeometry geometry = new InputGeometry(); for (int i = 0; i < lVerts.Count; i++) { geometry.AddPoint(lVerts[i].Position.x, lVerts[i].Position.z, 0); } TriangleNet.Mesh meshRepresentation = new TriangleNet.Mesh(); meshRepresentation.Triangulate(geometry); int vIdx = 0; lod.vertices = new Vector3[meshRepresentation.Vertices.Count]; lod.normals = new Vector3[meshRepresentation.Vertices.Count]; lod.uvs = new Vector2[meshRepresentation.Vertices.Count]; lod.faces = new int[meshRepresentation.triangles.Count * 3]; foreach (var v in meshRepresentation.Vertices) { lod.vertices[vIdx] = new Vector3(v.x, lVerts[vIdx].Position.y, v.y); lod.normals[vIdx] = lVerts[vIdx].Normal; lod.uvs[vIdx] = lVerts[vIdx].UV; ++vIdx; } vIdx = 0; foreach (var t in meshRepresentation.triangles.Values) { lod.faces[vIdx] = t.P2; lod.faces[vIdx + 1] = t.P1; lod.faces[vIdx + 2] = t.P0; vIdx += 3; } }
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> /// 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); } } } }
// Use this for initialization void Start() { geometry = new InputGeometry(); List <Point> shape = new List <Point> (); shape.Add(new Point(0f, 0f)); shape.Add(new Point(2f, 2f)); shape.Add(new Point(1f, 4f)); shape.Add(new Point(3f, 5f)); shape.Add(new Point(-3f, 5f)); shape.Add(new Point(-1f, 4f)); shape.Add(new Point(-2f, 2f)); geometry.AddRing(shape); //it is necessary to put a border around all the points in order to get triangulation to work correctly when holes are used // List<Point> border = new List<Point>(); // border.Add(new Point(distance, verticalDistance)); // border.Add(new Point(distance, -verticalDistance)); // border.Add(new Point(-distance, -verticalDistance)); // border.Add(new Point(-distance, verticalDistance)); // geometry.AddRing(border); // List<Point> outlinePoints = new List<Point>(logoOutline.points.Length); // foreach (Vector2 coordinates in logoOutline.points) // { // outlinePoints.Add(new Point(coordinates)); // } // // geometry.AddRingAsHole(outlinePoints, 0); // // // foreach(UPolygon hole in holes) // { // List<Point> holePoints = new List<Point>(hole.points.Length); // // foreach (Vector2 coordinates in hole.points) // holePoints.Add(new Point(coordinates)); // // geometry.AddRing(holePoints, 0); // } // 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.RandomRange(0, 2 * Mathf.PI); // float length = Random.RandomRange(0, circleDistance); // // Vector2 pos = new Vector2(Mathf.Cos(radians), Mathf.Sin(radians)) * length; // pos += offset; // // bool insideOutline = logoOutline.PointInPolygon(pos); // // bool stillAlloved = false; // for (int i = 0; i < holes.Length; i++ ) // { // if (holes[i].PointInPolygon(pos)) // stillAlloved = true; // } // // if (!insideOutline || stillAlloved) // geometry.AddPoint((float)pos.x, (float)pos.y, 0); // } // } 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.RandomRange(-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, 0); Vector3 p1 = new Vector3(vertex1.x, vertex1.y, 0); Vector3 p2 = new Vector3(vertex2.x, vertex2.y, 0); 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.vertices = vertices.ToArray(); mesh.triangles = triangleIndices.ToArray(); mesh.RecalculateNormals(); GetComponent <MeshFilter>().mesh = mesh; }
// Use this for initialization void Start() { Map = new GameMap(); Map.TerrainData = LowPolyTerrainData.GetRandomMap(); var building = new Building(); building.Positions.Add(new Vector2Int(6, 1)); building.Positions.Add(new Vector2Int(7, 1)); building.Positions.Add(new Vector2Int(8, 1)); building.Positions.Add(new Vector2Int(9, 1)); building.Positions.Add(new Vector2Int(10, 1)); building.Positions.Add(new Vector2Int(11, 1)); building.Positions.Add(new Vector2Int(12, 1)); building.Positions.Add(new Vector2Int(13, 1)); building.Positions.Add(new Vector2Int(14, 1)); building.Positions.Add(new Vector2Int(11, 2)); building.Positions.Add(new Vector2Int(12, 2)); building.Positions.Add(new Vector2Int(12, 3)); building.Positions.Add(new Vector2Int(13, 3)); building.Positions.Add(new Vector2Int(13, 4)); building.Positions.Add(new Vector2Int(14, 4)); building.Positions.Add(new Vector2Int(14, 5)); building.Positions.Add(new Vector2Int(15, 5)); building.RemoveTrees(Map.TerrainData); //Map.Buildings.Add(building); building = new Building(); //building.Positions.Add(new Vector2Int(6, 2)); building.Positions.Add(new Vector2Int(7, 2)); building.Positions.Add(new Vector2Int(8, 2)); building.Positions.Add(new Vector2Int(9, 2)); building.Positions.Add(new Vector2Int(10, 2)); building.Positions.Add(new Vector2Int(5, 3)); building.Positions.Add(new Vector2Int(6, 3)); building.Positions.Add(new Vector2Int(7, 3)); building.Positions.Add(new Vector2Int(8, 3)); building.Positions.Add(new Vector2Int(9, 3)); building.Positions.Add(new Vector2Int(10, 3)); building.Positions.Add(new Vector2Int(11, 3)); //building.Positions.Add(new Vector2Int(5, 4)); building.Positions.Add(new Vector2Int(6, 4)); building.Positions.Add(new Vector2Int(7, 4)); building.Positions.Add(new Vector2Int(8, 4)); building.Positions.Add(new Vector2Int(9, 4)); building.Positions.Add(new Vector2Int(10, 4)); building.Positions.Add(new Vector2Int(11, 4)); building.Positions.Add(new Vector2Int(10, 6)); building.Positions.Add(new Vector2Int(11, 6)); building.Positions.Add(new Vector2Int(12, 6)); building.Type = "house"; building.RemoveTrees(Map.TerrainData); //Map.Buildings.Add(building); building = new Building(); var floor = new BuildingFloor(); floor.Positions.Add(new Vector2Int(13, 2)); floor.Positions.Add(new Vector2Int(14, 2)); floor.Positions.Add(new Vector2Int(15, 2)); floor.Positions.Add(new Vector2Int(16, 2)); floor.Positions.Add(new Vector2Int(14, 3)); floor.Positions.Add(new Vector2Int(15, 3)); floor.Positions.Add(new Vector2Int(16, 3)); floor.WallEdges.Add(new WallEdge(new Vector2Int(13, 2), 2)); floor.WallEdges.Add(new WallEdge(new Vector2Int(13, 2), 0)); floor.BaseHeight = 20.0f; floor.FloorHeight = 0.2f; floor.Height = 10.0f; floor.Map = Map; building.Floors.Add(floor); floor = new BuildingFloor(); floor.Positions.Add(new Vector2Int(14, 2)); floor.Positions.Add(new Vector2Int(15, 2)); floor.Positions.Add(new Vector2Int(16, 2)); floor.Positions.Add(new Vector2Int(14, 3)); floor.Positions.Add(new Vector2Int(15, 3)); floor.Positions.Add(new Vector2Int(16, 3)); floor.WallEdges.Add(new WallEdge(new Vector2Int(14, 2), 2)); floor.WallEdges.Add(new WallEdge(new Vector2Int(15, 2), 2)); floor.BaseHeight = 30.0f; floor.FloorHeight = 0.2f; floor.Height = 10.0f; floor.Map = Map; building.Floors.Add(floor); floor = new BuildingFloor(); floor.Positions.Add(new Vector2Int(15, 4)); floor.Positions.Add(new Vector2Int(16, 4)); floor.Positions.Add(new Vector2Int(17, 4)); floor.Positions.Add(new Vector2Int(17, 3)); floor.Positions.Add(new Vector2Int(18, 3)); floor.WallEdges.Add(new WallEdge(new Vector2Int(15, 4), 0)); floor.WallEdges.Add(new WallEdge(new Vector2Int(16, 4), 0)); floor.WallEdges.Add(new WallEdge(new Vector2Int(17, 4), 1, 2)); floor.BaseHeight = 22.0f; floor.FloorHeight = 0.2f; floor.Height = 10.0f; floor.Map = Map; building.Floors.Add(floor); building.Type = "generic"; building.RemoveTrees(Map.TerrainData); Map.Buildings.Add(building); Init(Map); var geometry = new InputGeometry(); //it is necessary to put a border around all the points in order to get triangulation to work correctly when holes are used var border = new List <Point>(); border.Add(new Point(10, 6)); border.Add(new Point(10, -6)); border.Add(new Point(-10, -6)); border.Add(new Point(-10, 6)); geometry.AddRing(border); border = new List <Point>(); border.Add(new Point(7, 4)); border.Add(new Point(7, 2)); border.Add(new Point(5, 2)); border.Add(new Point(5, 4)); geometry.AddRingAsHole(border); border = new List <Point>(); border.Add(new Point(3, 2)); border.Add(new Point(3, -6)); border.Add(new Point(-3, -6)); border.Add(new Point(-3, 2)); geometry.AddRingAsHole(border); var meshRepresentation = new TriangleNet.Mesh(); meshRepresentation.Triangulate(geometry); var triangleIndex = 0; var vertices = new List <Vector3>(meshRepresentation.triangles.Count * 3); var triangleIndices = new List <int>(meshRepresentation.triangles.Count * 3); foreach (var pair in meshRepresentation.triangles) { var triangle = pair.Value; var vertex0 = triangle.GetVertex(0); var vertex1 = triangle.GetVertex(1); var vertex2 = triangle.GetVertex(2); var p0 = new Vector3(vertex0.x, vertex0.y, 0); var p1 = new Vector3(vertex1.x, vertex1.y, 0); var p2 = new Vector3(vertex2.x, vertex2.y, 0); vertices.Add(p0); vertices.Add(p1); vertices.Add(p2); triangleIndices.Add(triangleIndex + 2); triangleIndices.Add(triangleIndex + 1); triangleIndices.Add(triangleIndex); triangleIndex += 3; } var mesh = new Mesh(); mesh.vertices = vertices.ToArray(); mesh.triangles = triangleIndices.ToArray(); mesh.RecalculateNormals(); var newObj = new GameObject(); newObj.name = "Test"; newObj.transform.parent = transform; newObj.AddComponent <MeshFilter>(); newObj.AddComponent <MeshRenderer>(); newObj.GetComponent <MeshFilter>().mesh = mesh; /* * var path = new List<ClipperLib.IntPoint>(); * path.Add(new ClipperLib.IntPoint(-3000, 0)); * path.Add(new ClipperLib.IntPoint(1000, 0)); * path.Add(new ClipperLib.IntPoint(6000, 3000)); * path.Add(new ClipperLib.IntPoint(6000, -3000)); * path.Add(new ClipperLib.IntPoint(1000, 0)); * //path.Add(new ClipperLib.IntPoint(5000, 0)); * //path.Add(new ClipperLib.IntPoint(1000, -3500)); * //path.Add(new ClipperLib.IntPoint(-3000, 0)); * * var co = new ClipperLib.ClipperOffset(); * co.AddPath(path, ClipperLib.JoinType.jtSquare, ClipperLib.EndType.etClosedLine); * * var result = new List<List<ClipperLib.IntPoint>>(); * co.Execute(ref result, 500); * foreach (var intpoint in path) * { * var point = new Vector3((float)intpoint.X / 1000.0f, 0, (float)intpoint.Y / 1000.0f); * Debug.DrawLine(point, point + Vector3.up * 3, Color.cyan, 100); * } * * foreach (var intpath in result) * { * foreach (var intpoint in intpath) * { * var point = new Vector3((float)intpoint.X / 1000.0f, 0, (float)intpoint.Y / 1000.0f); * Debug.DrawLine(point, point + Vector3.up * 3, Color.red, 100); * } * } */ }
public static void CreateMesh(GameObject meshContainer, string path, string path2, string adfname) { var subgraphs = _LoadMarkerToSubgraph(path, path2); meshContainer.name = adfname + "Mesh"; InputGeometry geometry = new InputGeometry(); TriangleNet.Mesh meshRepresentation; MeshFilter mf = meshContainer.GetComponent <MeshFilter> () as MeshFilter; Mesh mesh; float zOffset = 0.1f; float[] maxArea = new float[2] { 0, 0 }; List <List <Point> > clusters = new List <List <Point> > (); foreach (Graph <Node> s in subgraphs) { List <Point> points = new List <Point> (); foreach (Node n in s.Nodes) { Point tmp = new Point(n.position.x, n.position.z); zOffset = n.position.y; points.Add(tmp); } if (points.Count > 2) { clusters.Add(points); // Calculate areas of the clusters. The largest is the external ring, while the others must be holes. float num = CalculateArea(points); if (num > maxArea [0]) { maxArea [0] = num; maxArea [1] = clusters.Count - 1; } } Debug.Log(clusters [clusters.Count - 1].Count); } geometry.AddRing(clusters[(int)maxArea[1]]); clusters.RemoveAt((int)maxArea [1]); foreach (List <Point> c in clusters) { geometry.AddRingAsHole(c); } meshRepresentation = new TriangleNet.Mesh(); meshRepresentation.Triangulate(geometry); // Dictionary<int, float> zOffsets = new Dictionary<int, float>(); // // foreach(KeyValuePair<int, TriangleNet.Data.Vertex> pair in meshRepresentation.vertices) // { // zOffsets.Add(pair.Key, Random.RandomRange(-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, zOffset, vertex0.y); Vector3 p1 = new Vector3(vertex1.x, zOffset, vertex1.y); Vector3 p2 = new Vector3(vertex2.x, zOffset, vertex2.y); // 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.vertices = vertices.ToArray(); mesh.triangles = triangleIndices.ToArray(); mesh.RecalculateNormals(); //GetComponent<MeshFilter>().mesh = mesh; mf.mesh = mesh; Exporter e = meshContainer.GetComponent <Exporter> () as Exporter; e.DoExport(true); // // File.WriteAllBytes(Application.persistentDataPath + "/" + adfname + "Mesh", MeshSerializer.WriteMesh (mesh, true)); meshContainer.SetActive(true); meshContainer.GetComponent <NavMeshSurface> ().BuildNavMesh(); Debug.Log("NavMesh created"); //MeshSaverEditor.SaveMesh (mesh, "meshtest", true, true); //ObjExporterScript.MeshToString(GetComponent<MeshFilter>(), }
// returns list of list of vertices, each one being a triangle public static List <List <Vector2> > MakeTriangles(List <List <Vector2> > loops) { //Debug.LogFormat("loop1 = {0}, loopL = {1}", loops[0].Count, loops[loops.Count - 1].Count); // first off, the loops should be sorted by area, so we can just go from the start expecting the first polygon to be the largest one and last the smallest. List <List <Vector2> > polygons = new List <List <Vector2> >(); Dictionary <List <Vector2>, List <List <Vector2> > > holes = new Dictionary <List <Vector2>, List <List <Vector2> > >(); //for (int i = loops.Count - 1; i >= 0; i--) for (int i = 0; i < loops.Count; i++) { List <Vector2> loop = loops[i]; // first we check if this loop intersects any polygon. if it does, add hole to dictionary. if it doesn't, just add polygon. bool anyHole = false; for (int j = 0; j < polygons.Count; j++) { if (CheckIntersection(polygons[j], loop)) { //Debug.LogFormat("adding hole (len = {0}) to polygon (len = {1})", loop.Count, polygons[j].Count); //Debug.LogFormat("polygon {0} intersects loop {1}", j, i); if (!holes.ContainsKey(polygons[j])) { holes[polygons[j]] = new List <List <Vector2> >(); } holes[polygons[j]].Add(((IEnumerable <Vector2>)loop).Reverse().ToList()); anyHole = true; break; } } if (!anyHole) { //Debug.LogFormat("adding polygon (len = {0})", loop.Count); polygons.Add(loop); } //break; } List <List <Vector2> > output = new List <List <Vector2> >(); for (int i = 0; i < polygons.Count; i++) { List <Vector2> polygon = polygons[i]; if (polygon.Count < 3) { continue; } //Debug.LogFormat("polygon points = {0}", polygon.Count); InputGeometry input = new InputGeometry(); for (int j = 0; j < polygon.Count; j++) { input.AddPoint(polygon[j].x, polygon[j].y); } // add segments for (int j = 0; j < polygon.Count; j++) { input.AddSegment(j, (j + 1) % polygon.Count, 0); } if (holes.ContainsKey(polygon)) { for (int j = 0; j < holes[polygon].Count; j++) { List <Vector2> hole = holes[polygon][j]; // add holes segments int basePt = input.points.Count; float cx = 0; float cy = 0; for (int k = 0; k < hole.Count; k++) { input.AddPoint(hole[k].x, hole[k].y); cx += hole[k].x; cy += hole[k].y; } cx /= hole.Count; cy /= hole.Count; for (int k = 0; k < hole.Count; k++) { input.AddSegment(basePt + k, basePt + ((k + 1) % hole.Count), j + 1); } input.AddHole(cx, cy); } } if (input.points.Count < 3) { continue; } // TriangleNet.Mesh mesh = new TriangleNet.Mesh(); mesh.Triangulate(input); // put triangles to output for (int j = 0; j < mesh.Triangles.Count; j++) { Triangle mtri = mesh.Triangles.ElementAt(j); List <Vector2> triangle = new List <Vector2>(); for (int k = 0; k < 3; k++) { triangle.Add(new Vector2((float)mtri.vertices[k].x, (float)mtri.vertices[k].y)); } output.Add(triangle); } } return(output); }
public static void RunPopulationScenario() { WaterTableArgs args = new WaterTableArgs(); Bitmap bmp = new Bitmap(args.inputPath + "rivers.png"); IField2d <float> baseMap = new Utils.FieldFromBitmap(new Bitmap(args.inputPath + "base_heights.png")); baseMap = new ReResField(baseMap, (float)bmp.Width / baseMap.Width); var wtf = Utils.GenerateWaters(bmp, baseMap); Utils.OutputAsColoredMap(wtf, wtf.RiverSystems, bmp, args.outputPath + "colored_map.png"); IField2d <float> rainfall = new Utils.FieldFromBitmap(new Bitmap(args.inputPath + "rainfall.png")); rainfall = new ReResField(rainfall, (float)wtf.Width / rainfall.Width); IField2d <float> wateriness = Utils.GetWaterinessMap(wtf, rainfall); Utils.OutputField(new NormalizedComposition2d <float>(wateriness), bmp, args.outputPath + "wateriness.png"); var locations = Utils.GetSettlementLocations(wtf, wateriness); SparseField2d <float> settlementMap = new SparseField2d <float>(wtf.Width, wtf.Height, 0f); foreach (var loc in locations) { settlementMap.Add(loc, wateriness[loc.y, loc.x]); } Utils.OutputField(settlementMap, bmp, args.outputPath + "settlements.png"); TriangleNet.Geometry.InputGeometry pointSet = new TriangleNet.Geometry.InputGeometry(); foreach (var loc in locations) { pointSet.AddPoint(loc.x, loc.y); } TriangleNet.Mesh mesh = new TriangleNet.Mesh(); mesh.Triangulate(pointSet); //TriangleNet.Tools.AdjacencyMatrix mat = new TriangleNet.Tools.AdjacencyMatrix(mesh); Field2d <float> meshField = new Field2d <float>(settlementMap); foreach (var e in mesh.Edges) { var v0 = mesh.GetVertex(e.P0); var v1 = mesh.GetVertex(e.P1); float distance = (float)Math.Sqrt(Math.Pow(v0.X - v1.X, 2) + Math.Pow(v0.Y - v1.Y, 2)); for (float t = 0f; t <= 1f; t += 0.5f / distance) { int x = (int)Math.Round((1f - t) * v0.X + t * v1.X); int y = (int)Math.Round((1f - t) * v0.Y + t * v1.Y); meshField[y, x] = 0.5f; } meshField[(int)v0.Y, (int)v0.X] = 1f; meshField[(int)v1.Y, (int)v1.X] = 1f; } Utils.OutputField(meshField, bmp, args.outputPath + "mesh.png"); }
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 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 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 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); }
private void CreateMesh() { Sprite sprite = spriteRenderer.sprite; Rect bounds = GetBounds(polygon); TriangleNet.Mesh tnMesh = new TriangleNet.Mesh(); TriangleNet.Geometry.InputGeometry input = new TriangleNet.Geometry.InputGeometry(); input.AddPolygon(polygon); tnMesh.Triangulate(input); Mesh mesh = new Mesh(); mesh.vertices = tnMesh.Vertices.Select(p => new Vector3((float)p.X, (float)p.Y, 0)).ToArray(); // Not sure about winding // If there is an interesting error, It is probably because of cw/ccw windings int[] tris = tnMesh.Triangles.ToUnityMeshTriangleIndices(); mesh.triangles = tris; List <Vector2> uv = new List <Vector2>(); Vector3 lower = new Vector3(bounds.x, bounds.y); Vector3 size = new Vector3(bounds.xMax, bounds.yMax) - lower; Rect uv_bounds = new Rect(sprite.rect.x / sprite.texture.width, sprite.rect.y / sprite.texture.height, sprite.rect.width / sprite.texture.width, sprite.rect.height / sprite.texture.height); float scalex = sprite.bounds.size.x / bounds.width; float scaley = sprite.bounds.size.y / bounds.height; Vector3[] scaled = mesh.vertices; for (int i = 0; i < mesh.vertices.Length; i++) { Vector3 v = scaled[i]; Vector3 rel = v - lower; uv.Add(new Vector2(rel.x / size.x * uv_bounds.width, rel.y / size.y * uv_bounds.height) + new Vector2(uv_bounds.x, uv_bounds.y)); scaled[i] = new Vector3(v.x * scalex, v.y * scaley, v.z) - ((Vector3)bounds.center * scalex) + sprite.bounds.center; } mesh.MarkDynamic(); mesh.vertices = scaled; mesh.uv = uv.ToArray(); mesh.RecalculateNormals(); mesh.RecalculateBounds(); mesh.Optimize(); //GameObject go = new GameObject(); //MeshFilter mf = go.AddComponent<MeshFilter>(); //mf.sharedMesh = mesh; //MeshRenderer mr = go.AddComponent<MeshRenderer>(); //mr.sharedMaterial = spriteRenderer.sharedMaterial; // Check if the Meshes directory exists, if not, create it. DirectoryInfo meshDir = new DirectoryInfo("Assets/Meshes"); if (Directory.Exists(meshDir.FullName) == false) { Directory.CreateDirectory(meshDir.FullName); } ScriptableObjectUtility.CreateAsset(mesh, "Meshes/" + spriteRenderer.gameObject.name + ".Mesh"); }
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; } }
/// <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; } } } }
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); } } } }
protected void GenerateTrisForShape() { if (vertices.Length >= 6 && vertices.Length % 2 == 0) { InputGeometry bottomGeometry = new InputGeometry(); List <Point> shape = new List <Point> (); int halfVertLen = vertices.Length / 2; for (int i = 0; i < halfVertLen; i++) { shape.Add(new Point(vertices[i].x, vertices[i].z)); } bottomGeometry.AddRing(shape); TriangleNet.Mesh bottomMesh = new TriangleNet.Mesh(); bottomMesh.Triangulate(bottomGeometry); List <Vector3> verts = new List <Vector3>(bottomMesh.triangles.Count * 3); List <int> triangleIndices = new List <int>(bottomMesh.triangles.Count * 3); foreach (KeyValuePair <int, TriangleNet.Data.Triangle> pair in bottomMesh.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, 0, vertex0.y); Vector3 p1 = new Vector3(vertex1.x, 0, vertex1.y); Vector3 p2 = new Vector3(vertex2.x, 0, vertex2.y); verts.Add(p0); verts.Add(p1); verts.Add(p2); triangleIndices.Add(GetIndexForVertex(p0)); triangleIndices.Add(GetIndexForVertex(p1)); triangleIndices.Add(GetIndexForVertex(p2)); } // Create top Side List <int> triangleIndecesReversed = new List <int>(); for (int i = triangleIndices.Count - 1; i >= 0; i--) { triangleIndecesReversed.Add(triangleIndices[i] + halfVertLen); } triangleIndices.AddRange(triangleIndecesReversed); // Add edges List <int> edgeIndeces = new List <int>(); for (int i = 0; i < halfVertLen; i++) { int leftBottom = i; int rightBottom = (i == halfVertLen - 1 ? 0 : i + 1); int leftTop = i + halfVertLen; int rightTop = (i == halfVertLen - 1 ? halfVertLen : i + halfVertLen + 1); edgeIndeces.Add(leftTop); edgeIndeces.Add(rightTop); edgeIndeces.Add(leftBottom); edgeIndeces.Add(rightBottom); edgeIndeces.Add(leftBottom); edgeIndeces.Add(rightTop); } triangleIndices.AddRange(edgeIndeces); tris = triangleIndices.ToArray(); } else { Debug.LogError("[BaseShape.GenerateTrisForShape] Invalid vertices set for shape!"); } }