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]; 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; } }
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)); }
private int CreateRoofTriangulation(List <Vector3> corners, float height, MeshData data) { _mesh = new TriangleNet.Mesh(); var inp = new InputGeometry(corners.Count); for (int i = 0; i < corners.Count; i++) { var v = corners[i]; inp.AddPoint(v.x, v.z); inp.AddSegment(i, (i + 1) % corners.Count); } _mesh.Behavior.Algorithm = TriangulationAlgorithm.SweepLine; _mesh.Behavior.Quality = true; _mesh.Triangulate(inp); var vertsStartCount = data.Vertices.Count; data.Vertices.AddRange(corners.Select(x => new Vector3(x.x, height, x.z)).ToList()); foreach (var tri in _mesh.Triangles) { data.Indices.Add(vertsStartCount + tri.P1); data.Indices.Add(vertsStartCount + tri.P0); data.Indices.Add(vertsStartCount + tri.P2); } return(vertsStartCount); }
private static ICollection <Triangle> Triangulate(InputGeometry input) { TriangleNet.Mesh mesh = new TriangleNet.Mesh(); mesh.Behavior.ConformingDelaunay = true; mesh.Behavior.Algorithm = TriangulationAlgorithm.SweepLine; mesh.Behavior.Convex = false; mesh.Triangulate(input); return(mesh.Triangles); }
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; }
private void CreateMesh(InputGeometry corners, MeshData meshdata) { var mesh = new TriangleNet.Mesh(); mesh.Behavior.Algorithm = TriangulationAlgorithm.SweepLine; mesh.Behavior.Quality = true; mesh.Triangulate(corners); var vertsStartCount = meshdata.Vertices.Count; meshdata.Vertices.AddRange(corners.Points.Select(x => new Vector3((float)x.X, 0, (float)x.Y)).ToList()); foreach (var tri in mesh.Triangles) { meshdata.Indices.Add(vertsStartCount + tri.P1); meshdata.Indices.Add(vertsStartCount + tri.P0); meshdata.Indices.Add(vertsStartCount + tri.P2); } }
public override void Run(VectorFeatureUnity feature, MeshData md) { if (md.Vertices.Distinct().Count() < 3) { return; } var data = new List <int>(); var _mesh = new TriangleNet.Mesh(); var inp = new InputGeometry(md.Vertices.Count); for (int i = 0; i < md.Vertices.Count; i++) { var v = md.Vertices[i]; inp.AddPoint(v.x, v.z); inp.AddSegment(i, (i + 1) % md.Vertices.Count); } _mesh.Behavior.Algorithm = TriangulationAlgorithm.SweepLine; _mesh.Behavior.Quality = true; _mesh.Triangulate(inp); foreach (var tri in _mesh.Triangles) { data.Add(tri.P1); data.Add(tri.P0); data.Add(tri.P2); } if (_mesh.Vertices.Count != md.Vertices.Count) { md.Vertices.Clear(); using (var sequenceEnum = _mesh.Vertices.GetEnumerator()) { while (sequenceEnum.MoveNext()) { md.Vertices.Add(new Vector3((float)sequenceEnum.Current.x, 0, (float)sequenceEnum.Current.y)); } } } md.Triangles.Add(data); }
private List <int> CreateRoofTriangulation(List <Vector3> corners) { var data = new List <int>(); var _mesh = new TriangleNet.Mesh(); var inp = new InputGeometry(corners.Count); for (int i = 0; i < corners.Count; i++) { var v = corners[i]; inp.AddPoint(v.x, v.z); inp.AddSegment(i, (i + 1) % corners.Count); } _mesh.Behavior.Algorithm = TriangulationAlgorithm.SweepLine; _mesh.Behavior.Quality = true; _mesh.Triangulate(inp); foreach (var tri in _mesh.Triangles) { data.Add(tri.P1); data.Add(tri.P0); data.Add(tri.P2); } return(data); }
private void CreateMesh(List <Vector3> corners, float height, BuildingSettings typeSettings, MeshData data, Vector2 min, Vector2 size) { _mesh = new TriangleNet.Mesh(); var inp = new InputGeometry(corners.Count); for (int i = 0; i < corners.Count; i++) { var v = corners[i]; inp.AddPoint(v.x, v.z); inp.AddSegment(i, (i + 1) % corners.Count); } _mesh.Behavior.Algorithm = TriangulationAlgorithm.SweepLine; _mesh.Behavior.Quality = true; _mesh.Triangulate(inp); var vertsStartCount = data.Vertices.Count; data.Vertices.AddRange(corners.Select(x => new Vector3(x.x, height, x.z)).ToList()); foreach (var tri in _mesh.Triangles) { data.Indices.Add(vertsStartCount + tri.P1); data.Indices.Add(vertsStartCount + tri.P0); data.Indices.Add(vertsStartCount + tri.P2); } foreach (var c in corners) { data.UV.Add(new Vector2((c.x - min.x), (c.z - min.y))); } if (typeSettings.IsVolumetric) { float d = 0f; Vector3 v1; Vector3 v2; int ind = 0; for (int i = 1; i < corners.Count; i++) { v1 = data.Vertices[vertsStartCount + i - 1]; v2 = data.Vertices[vertsStartCount + i]; ind = data.Vertices.Count; data.Vertices.Add(v1); data.Vertices.Add(v2); data.Vertices.Add(new Vector3(v1.x, 0, v1.z)); data.Vertices.Add(new Vector3(v2.x, 0, v2.z)); d = (v2 - v1).magnitude; data.UV.Add(new Vector2(0, 0)); data.UV.Add(new Vector2(d, 0)); data.UV.Add(new Vector2(0, height)); data.UV.Add(new Vector2(d, height)); data.Indices.Add(ind); data.Indices.Add(ind + 2); data.Indices.Add(ind + 1); data.Indices.Add(ind + 1); data.Indices.Add(ind + 2); data.Indices.Add(ind + 3); } v1 = data.Vertices[vertsStartCount]; v2 = data.Vertices[vertsStartCount + corners.Count - 1]; ind = data.Vertices.Count; data.Vertices.Add(v1); data.Vertices.Add(v2); data.Vertices.Add(new Vector3(v1.x, 0, v1.z)); data.Vertices.Add(new Vector3(v2.x, 0, v2.z)); d = (v2 - v1).magnitude; data.UV.Add(new Vector2(0, 0)); data.UV.Add(new Vector2(d, 0)); data.UV.Add(new Vector2(0, height)); data.UV.Add(new Vector2(d, height)); data.Indices.Add(ind); data.Indices.Add(ind + 1); data.Indices.Add(ind + 2); data.Indices.Add(ind + 1); data.Indices.Add(ind + 3); data.Indices.Add(ind + 2); } }
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(); //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]; 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 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 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) }; }
/// <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 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; }
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); }
private void RecalculateVertices() { if (points.Count < 2) { return; } vertexPositionColorArray = null; var lineColor = Color.Red; #region clipper List<IntPoint> clipperPath = new List<IntPoint>(points.Count); foreach (var point in points) { clipperPath.Add(new IntPoint(point.X * ClipperScale, point.Y * ClipperScale)); } List<List<IntPoint>> clipperSolution = new List<List<IntPoint>>(); ClipperOffset clipperOffset = new ClipperOffset(); clipperOffset.AddPath(clipperPath, JoinType.jtRound, EndType.etOpenRound); clipperOffset.Execute(ref clipperSolution, lineThickness / 2.0f * ClipperScale); #endregion #region triangle.net InputGeometry InputGeometry = new InputGeometry(); Mesh TriangleMesh = new Mesh(); for (int iii = 0; iii < clipperSolution.Count; iii++) { var trianglePath = clipperSolution[iii].Select(p => new TrianglePoint(p.X / (float)ClipperScale, p.Y / (float)ClipperScale)).ToList(); if (iii == 0) { InputGeometry.AddRing(trianglePath); } else { InputGeometry.AddRingAsHole(trianglePath); } } #endregion if (InputGeometry.Count > 0) { TriangleMesh.Triangulate(InputGeometry); vertexPositionColorArray = TriangleMesh.GetTriangleList().Select(v => new VertexPositionColor(new Vector3((float)v.X, (float)v.Y, 0.0f), lineColor)).ToArray(); vertexBuffer = new VertexBuffer(GraphicsDevice, VertexPositionColor.VertexDeclaration, vertexPositionColorArray.Length, BufferUsage.WriteOnly); vertexBuffer.SetData<VertexPositionColor>(vertexPositionColorArray); } }
private void endBtn_Click(object sender, RoutedEventArgs e) { this._host.CommandReset.Click -= endBtn_Click; this._host.Menues.IsEnabled = true; this._host.UIMessage.Visibility = Visibility.Hidden; //this.JGraphMode = false; this._host.Cursor = Cursors.Arrow; this._host.FloorScene.MouseLeftButtonDown -= FloorScene_MouseLeftButtonDown; try { #region Create Graph HashSet <UV> pnts = new HashSet <UV>(); TriangleNet.Behavior behavior = new Behavior(); TriangleNet.Mesh t_mesh = new TriangleNet.Mesh(); TriangleNet.Geometry.InputGeometry geom = new TriangleNet.Geometry.InputGeometry(); foreach (Node node in JGNodes) { TriangleNet.Data.Vertex vertex = new TriangleNet.Data.Vertex(node.Coordinates.U, node.Coordinates.V, 0); geom.AddPoint(vertex); pnts.Add(node.Coordinates); } t_mesh.Triangulate(geom); var graph = new JGGraph(pnts); foreach (var item in t_mesh.Triangles) { UV a = null; var vrtx = t_mesh.GetVertex(item.P0); if (vrtx != null) { a = new UV(vrtx.X, vrtx.Y); } UV b = null; vrtx = t_mesh.GetVertex(item.P1); if (vrtx != null) { b = new UV(vrtx.X, vrtx.Y); } UV c = null; vrtx = t_mesh.GetVertex(item.P2); if (vrtx != null) { c = new UV(vrtx.X, vrtx.Y); } if (a != null && b != null) { graph.AddConnection(a, b); } if (a != null && c != null) { graph.AddConnection(a, c); } if (c != null && b != null) { graph.AddConnection(c, b); } } #endregion #region Remove Edges with isovists at the ends that do not overlap this.edges = graph.ToEdges(); Dictionary <int, Isovist> IsovistGuid = new Dictionary <int, Isovist>(); foreach (JGVertex item in graph.Vertices) { double x = double.NegativeInfinity; foreach (JGVertex vertex in item.Connections) { var y = item.Point.DistanceTo(vertex.Point); if (y > x) { x = y; } } var isovist = CellularIsovistCalculator.GetIsovist(item.Point, x, BarrierType.Visual, this._host.cellularFloor); IsovistGuid.Add(item.Point.GetHashCode(), isovist); } HashSet <JGEdge> visibleVertexes = new HashSet <JGEdge>(); foreach (JGEdge item in this.edges) { Isovist v1 = null; IsovistGuid.TryGetValue(item.P1.GetHashCode(), out v1); Isovist v2 = null; IsovistGuid.TryGetValue(item.P2.GetHashCode(), out v2); if (v1 != null && v2 != null) { if (v2.VisibleCells.Overlaps(v1.VisibleCells)) { visibleVertexes.Add(item); } } } #endregion #region setting the edges JGEdge.LineToEdgeGuide.Clear(); foreach (JGEdge edge in this.edges) { edge.Clear(); } this.edges = visibleVertexes.ToList <JGEdge>(); foreach (JGEdge item in this.edges) { item.Draw(); } #endregion //cleaning up the used data t_mesh = null; graph = null; geom.Clear(); geom = null; visibleVertexes = null; IsovistGuid = null; //enabling edit mode this.EditGraph.IsEnabled = true; this.DrawJG.IsEnabled = true; this.Hide_show_Menu.IsEnabled = true; this.CreateCovexGraph.Header = "Reset Convex Graph"; } catch (Exception error) { MessageBox.Show(error.Report()); } }
// 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 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(); }
public TriangulatedGlyph(Glyph glyphData, TrueTypeFile.HorizontalMetric horizontalMetric) { indices = new List<int>(); vertices = new List<Vertex>(); advanceWidth = horizontalMetric.AdvanceWidth; leftSideBearing = horizontalMetric.LeftSideBearing; if (glyphData.IsCompound) { } else { if (glyphData.Contours.Length == 0) return; List<Triangle> triangles; List<LinkedList<ControlPoint>> contours = CreateContours(glyphData, out triangles); int count = 0; bool split; do { split = SplitTriangles(ref triangles); count++; } while (split && count < 4); foreach (var triangle in triangles) { ControlPoint p = (triangle.B + triangle.C) / 2; int windingNumber = GetWindingNumber(p, glyphData); triangle.IsInside = windingNumber == 0; if (triangle.IsInside) triangle.Contour.AddAfter(triangle.BNode, triangle.A); } PolyTree tree = ClipperHelper.Combine(contours.Select(contour => contour.ToList()).ToList()); int pointIndex = 0; var inputGeometry = new InputGeometry(); SearchTree(inputGeometry, ref pointIndex, tree); if (inputGeometry.Count > 0) { var mesh = new Mesh(); mesh.Triangulate(inputGeometry); int highestIndex = 0; var indexDict = new Dictionary<int, int>(); foreach (TriangleNet.Data.Triangle triangle in mesh.Triangles) { int[] newIndices; List<Vertex> newVertices = IndexVertices(triangle, indexDict, ref highestIndex, out newIndices); indices.AddRange(newIndices); vertices.AddRange(newVertices); } foreach (var triangle in triangles) { indices.Add(vertices.Count); vertices.Add(new Vertex((float)triangle.B.X, (float)triangle.B.Y, 0, 0, triangle.IsInside)); indices.Add(vertices.Count); vertices.Add(new Vertex((float)triangle.A.X, (float)triangle.A.Y, 0.5f, 0, triangle.IsInside)); indices.Add(vertices.Count); vertices.Add(new Vertex((float)triangle.C.X, (float)triangle.C.Y, 1, 1, triangle.IsInside)); } } } }
/// <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 Triangulate(out List<int[]> indices, out List<Vertex[]> vertices) { indices = new List<int[]>(); vertices = new List<Vertex[]>(); if (polygons == null) return; int pointIndex = 0; var inputGeometry = new InputGeometry(); SearchTree(inputGeometry, ref pointIndex, tree); var mesh = new Mesh(); mesh.Triangulate(inputGeometry); int highestIndex = 0; var currentIndices = new List<int>(); var currentVertices = new List<Vertex>(); var indexDict = new Dictionary<int, int>(); foreach (Triangle triangle in mesh.Triangles) { bool indexOverflow = currentIndices.Count + 3 > Renderer.IndexBufferSize; if (indexOverflow) { indices.Add(currentIndices.ToArray()); vertices.Add(currentVertices.ToArray()); currentIndices.Clear(); currentVertices.Clear(); indexDict.Clear(); highestIndex = 0; } int[] newIndices; List<Vertex> newVertices = IndexVertices(triangle, indexDict, ref highestIndex, out newIndices); if (currentVertices.Count + newVertices.Count > Renderer.VertexBufferSize) { indices.Add(currentIndices.ToArray()); vertices.Add(currentVertices.ToArray()); currentIndices.Clear(); currentVertices.Clear(); indexDict.Clear(); highestIndex = 3; newIndices[0] = 0; newIndices[1] = 1; newIndices[2] = 2; indexDict.Add(triangle.P0, 0); indexDict.Add(triangle.P1, 1); indexDict.Add(triangle.P2, 2); newVertices.Clear(); TriangleNet.Data.Vertex vertex0 = triangle.GetVertex(0); TriangleNet.Data.Vertex vertex1 = triangle.GetVertex(1); TriangleNet.Data.Vertex vertex2 = triangle.GetVertex(2); newVertices.Add(new Vertex((float)vertex0.X, (float)vertex0.Y)); newVertices.Add(new Vertex((float)vertex1.X, (float)vertex1.Y)); newVertices.Add(new Vertex((float)vertex2.X, (float)vertex2.Y)); } currentIndices.AddRange(newIndices); currentVertices.AddRange(newVertices); } indices.Add(currentIndices.ToArray()); vertices.Add(currentVertices.ToArray()); }
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 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 void Triangulate() { if (input == null) return; //Stopwatch sw = new Stopwatch(); mesh = new Mesh(); if (meshControlView.ParamConformDelChecked) { mesh.Behavior.ConformingDelaunay = true; } if (meshControlView.ParamSweeplineChecked) { mesh.Behavior.Algorithm = TriangulationAlgorithm.SweepLine; } if (meshControlView.ParamQualityChecked) { mesh.Behavior.Quality = true; mesh.Behavior.MinAngle = meshControlView.ParamMinAngleValue; double maxAngle = meshControlView.ParamMaxAngleValue; if (maxAngle < 180) { mesh.Behavior.MaxAngle = maxAngle; } // Ignore area constraints on initial triangulation. //double area = slMaxArea.Value * 0.01; //if (area > 0 && area < 1) //{ // var size = input.Bounds; // double min = Math.Min(size.Width, size.Height); // mesh.Behavior.MaxArea, area * min); //} } if (meshControlView.ParamConvexChecked) { mesh.Behavior.Convex = true; } try { //sw.Start(); mesh.Triangulate(input); //sw.Stop(); statisticView.UpdateStatistic(mesh); HandleMeshUpdate(); if (meshControlView.ParamQualityChecked) { settings.RefineMode = true; } } catch (Exception ex) { LockOnException(); DarkMessageBox.Show("Exception - Triangulate", ex.Message, MessageBoxButtons.OK); } UpdateLog(); }
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); }