public void BuildMeshFromGeometry() { triMesh = new TriangleNet.Mesh(); triMesh.behavior.Quality = true; triMesh.behavior.MinAngle = 1f; triMesh.Triangulate(Geometry); // var statistic = new Statistic(); // statistic.Update(triMesh, 1); // Refine by setting a custom maximum area constraint. //triMesh.Refine(statistic.LargestArea / 4); //triMesh.Smooth(); triMesh.Renumber(); UniMesh.vertices = TriangleConverter.ConverteVertices(triMesh.Vertices); UniMesh.RecalculateNormals(); UniMesh.triangles = TriangleConverter.ConverteTriangles(triMesh.Triangles); UniMesh.uv = TriangleConverter.ConverteUVs(triMesh); 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)); }
public void SetMesh(TriangleNet.Mesh mesh) { int n = mesh.Vertices.Count; int i = 0; // Linear numbering of mesh mesh.Renumber(); // Copy points this.Vertices = new Vector3[n]; foreach (var pt in mesh.Vertices) { this.Vertices[i] = new Vector3((float)pt.X, (float)pt.Y, 0); i++; } // Copy Triangles var triangles = new List <int>(3 * mesh.Triangles.Count); foreach (var tri in mesh.Triangles) { triangles.Add(tri.P0); triangles.Add(tri.P1); triangles.Add(tri.P2); /*if (this.NumberOfRegions > 0) * { * this.TrianglePartition[i++] = tri.Region; * }*/ } this.Triangles = triangles.ToArray(); }
/// <summary> /// Copy mesh data. /// </summary> public void SetMesh(Mesh mesh) { // Clear unused buffers this.Segments = null; this.VoronoiPoints = null; this.VoronoiEdges = null; int n = mesh.Vertices.Count; int i = 0; this.NumberOfInputPoints = mesh.NumberOfInputPoints; // Linear numbering of mesh mesh.Renumber(); // Copy points this.Points = new float[2 * n]; foreach (var pt in mesh.Vertices) { this.Points[2 * i] = (float)pt.X; this.Points[2 * i + 1] = (float)pt.Y; i++; } // Copy segments n = mesh.Segments.Count; if (n > 0 && mesh.IsPolygon) { var segments = new List<uint>(2 * n); foreach (var seg in mesh.Segments) { segments.Add((uint)seg.P0); segments.Add((uint)seg.P1); } this.Segments = segments.ToArray(); } // Copy edges var edges = new List<uint>(2 * mesh.NumberOfEdges); EdgeEnumerator e = new EdgeEnumerator(mesh); while (e.MoveNext()) { edges.Add((uint)e.Current.P0); edges.Add((uint)e.Current.P1); } this.MeshEdges = edges.ToArray(); if (this.NumberOfRegions > 0) { this.TrianglePartition = new int[mesh.Triangles.Count]; } i = 0; // Copy Triangles var triangles = new List<uint>(3 * mesh.Triangles.Count); foreach (var tri in mesh.Triangles) { triangles.Add((uint)tri.P0); triangles.Add((uint)tri.P1); triangles.Add((uint)tri.P2); if (this.NumberOfRegions > 0) { this.TrianglePartition[i++] = tri.Region; } } this.Triangles = triangles.ToArray(); this.Bounds = new BoundingBox( (float)mesh.Bounds.Xmin, (float)mesh.Bounds.Xmax, (float)mesh.Bounds.Ymin, (float)mesh.Bounds.Ymax); }
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; } }
/// <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) }); }
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); }
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; }
/// <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 Write(Mesh mesh, string filename) { using (StreamWriter writer = new StreamWriter(filename)) { int nv = mesh.Vertices.Count; int ns = mesh.Segments.Count; int nh = mesh.Holes.Count; int ne = mesh.Triangles.Count; writer.Write("{"); // Config header writer.Write("\"config\":{"); writer.Write("\"ver\":1,"); writer.Write("\"type\":\"{0}\",", ne > 0 ? "mesh" : (ns > 0 ? "poly" : "points")); writer.Write("\"dim\":2"); writer.Write("}"); if (mesh.CurrentNumbering == NodeNumbering.None) { mesh.Renumber(NodeNumbering.Linear); } // Write the coordinates if (nv > 0) { writer.Write(","); WritePoints(mesh, writer, nv); } // Write the segments if (ns > 0) { writer.Write(","); WriteSegments(mesh.Segments, writer, ns); } // Write the holes if (nh > 0) { writer.Write(","); WriteHoles(mesh.Holes, writer, nh); } // Write the elements if (ne > 0) { writer.Write(","); WriteTriangles(mesh.Triangles, writer, ne); } writer.Write("}"); } }
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); }