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); }
/// <summary> /// Find the abutting triangle; same edge. [sym(abc) -> ba*] /// </summary> public void SymSelf() { //this = tri.triangles[orient]; // decode(ptr, otri); int tmp = orient; orient = triangle.neighbors[tmp].orient; triangle = triangle.neighbors[tmp].triangle; }
public static Polygon GetPolygon(ref TriangleNet.Data.Triangle triangle) { List<Coordinate> coords = new List<Coordinate>(); Vertex v1 = triangle.GetVertex(0); coords.Add(new Coordinate(v1.X, v1.Y)); v1 = triangle.GetVertex(1); coords.Add(new Coordinate(v1.X, v1.Y)); v1 = triangle.GetVertex(2); coords.Add(new Coordinate(v1.X, v1.Y)); return new Polygon(coords); }
public List<Polygon> GetPolygons() { List<Polygon> polygons = new List<Polygon>(); foreach (var ts in mesh.Triangles) { TriangleNet.Data.Triangle tr = ts; polygons.Add(GetPolygon(ref tr)); } return polygons; }
public static List<Point> GetTriangleAsPoints(ref TriangleNet.Data.Triangle triangle) { Vertex v1 = triangle.GetVertex(0); Vertex v2 = triangle.GetVertex(1); Vertex v3 = triangle.GetVertex(2); List<Point> points = new List<Point>(); points.Add(new Point(v1.X, v1.Y, v1.Attributes[0])); points.Add(new Point(v2.X, v2.Y, v2.Attributes[0])); points.Add(new Point(v3.X, v3.Y, v3.Attributes[0])); return points; }
public static bool Contains(ref TriangleNet.Data.Triangle triangle, double x, double y) { Vertex v1 = triangle.GetVertex(0); Vertex v2 = triangle.GetVertex(1); Vertex v3 = triangle.GetVertex(2); Vertex pt = new Vertex(x, y); bool b1, b2, b3; b1 = Sign(ref pt, ref v1, ref v2) < 0.0f; b2 = Sign(ref pt, ref v2, ref v3) < 0.0f; b3 = Sign(ref pt, ref v3, ref v1) < 0.0f; return ((b1 == b2) && (b2 == b3)); }
public int FindTriangleThatContains(double x, double y) { for (int i = 0; i < triangles.Count; i++) { TriangleNet.Data.Triangle ts = triangles[i]; if (Contains(ref ts, x, y)) { return i; } } return -1; }
public double GetZ(int index, double x, double y) { if (index < triangles.Count) { TriangleNet.Data.Triangle tr = triangles[index]; if (Contains(ref tr, x, y)) { Point normal = triangleNormals[index]; double d = trianglePlaneEquationDs[index]; double value = (normal.X * x + normal.Y * y + d) / -normal.Z; return value; } } return double.MinValue; }
public double GetZ(double x, double y) { double value = -99999999999999999.00; int count = 0; foreach (var ts in triangles) { TriangleNet.Data.Triangle tr = ts; if (Contains(ref tr, x, y)) { Point normal = triangleNormals[count]; double d = trianglePlaneEquationDs[count]; return (normal.X * x + normal.Y * y + d) / -normal.Z; } } return value; }
/// <summary> /// Process all trianlges connected to given triangle and apply given action. /// </summary> public void Process(Triangle triangle, Action<Triangle> func) { if (triangle != Mesh.dummytri) { // Make sure the triangle under consideration still exists. // It may have been eaten by the virus. if (!Otri.IsDead(triangle)) { // Put one triangle in the virus pool. triangle.infected = true; viri.Add(triangle); // Apply one region's attribute and/or area constraint. ProcessRegion(func); // The virus pool should be empty now. } } // Free up memory (virus pool should be empty anyway). viri.Clear(); }
void OnDrawGizmos() { if (holes.Length <= 0) { return; } Gizmos.color = Color.black; logoOutline.GizmoDraw(); Gizmos.color = Color.white; foreach (UPolygon hole in holes) { hole.GizmoDraw(); } if (meshRepresentation == null) { return; } Gizmos.color = Color.cyan; 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); Vector2 p0 = new Vector2((float)vertex0.x, (float)vertex0.y); Vector2 p1 = new Vector2((float)vertex1.x, (float)vertex1.y); Vector2 p2 = new Vector2((float)vertex2.x, (float)vertex2.y); Gizmos.DrawLine(p0, p1); Gizmos.DrawLine(p1, p2); Gizmos.DrawLine(p2, p0); } }
/// <summary> /// Initialize the triangle that fills "outer space" and the omnipresent subsegment. /// </summary> /// <remarks> /// The triangle that fills "outer space," called 'dummytri', is pointed to /// by every triangle and subsegment on a boundary (be it outer or inner) of /// the triangulation. Also, 'dummytri' points to one of the triangles on /// the convex hull (until the holes and concavities are carved), making it /// possible to find a starting triangle for point location. // /// The omnipresent subsegment, 'dummysub', is pointed to by every triangle /// or subsegment that doesn't have a full complement of real subsegments /// to point to. // /// 'dummytri' and 'dummysub' are generally required to fulfill only a few /// invariants: their vertices must remain NULL and 'dummytri' must always /// be bonded (at offset zero) to some triangle on the convex hull of the /// mesh, via a boundary edge. Otherwise, the connections of 'dummytri' and /// 'dummysub' may change willy-nilly. This makes it possible to avoid /// writing a good deal of special-case code (in the edge flip, for example) /// for dealing with the boundary of the mesh, places where no subsegment is /// present, and so forth. Other entities are frequently bonded to /// 'dummytri' and 'dummysub' as if they were real mesh entities, with no /// harm done. /// </remarks> private void DummyInit() { // Set up 'dummytri', the 'triangle' that occupies "outer space." dummytri = new Triangle(); dummytri.hash = -1; dummytri.id = -1; // Initialize the three adjoining triangles to be "outer space." These // will eventually be changed by various bonding operations, but their // values don't really matter, as long as they can legally be // dereferenced. dummytri.neighbors[0].triangle = dummytri; dummytri.neighbors[1].triangle = dummytri; dummytri.neighbors[2].triangle = dummytri; if (behavior.useSegments) { // Set up 'dummysub', the omnipresent subsegment pointed to by any // triangle side or subsegment end that isn't attached to a real // subsegment. dummysub = new Segment(); dummysub.hash = -1; // Initialize the two adjoining subsegments to be the omnipresent // subsegment. These will eventually be changed by various bonding // operations, but their values don't really matter, as long as they // can legally be dereferenced. dummysub.subsegs[0].seg = dummysub; dummysub.subsegs[1].seg = dummysub; // Initialize the three adjoining subsegments of 'dummytri' to be // the omnipresent subsegment. dummytri.subsegs[0].seg = dummysub; dummytri.subsegs[1].seg = dummysub; dummytri.subsegs[2].seg = dummysub; } }
/// <summary> /// Deallocate space for a triangle, marking it dead. /// </summary> /// <param name="dyingtriangle"></param> internal void TriangleDealloc(Triangle dyingtriangle) { // Mark the triangle as dead. This makes it possible to detect dead // triangles when traversing the list of all triangles. Otri.Kill(dyingtriangle); triangles.Remove(dyingtriangle.hash); }
/// <summary> /// Create a new triangle with orientation zero. /// </summary> /// <param name="newotri">Reference to the new triangle.</param> internal void MakeTriangle(ref Otri newotri) { Triangle tri = new Triangle(); tri.hash = this.hash_tri++; tri.id = tri.hash; newotri.triangle = tri; newotri.orient = 0; triangles.Add(tri.hash, tri); }
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>(), }
/// <summary> /// Set the region attribute of all trianlges connected to given triangle. /// </summary> public void Process(Triangle triangle) { // Default action is to just set the region id for all trianlges. this.Process(triangle, (tri) => { tri.region = triangle.region; }); }
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); }
// 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; }
/// <summary> /// Set a triangle's deallocation. /// </summary> public static void Kill(Triangle tria) { tria.neighbors[0].triangle = null; tria.neighbors[2].triangle = null; }
/// <summary> /// Check a triangle's deallocation. /// </summary> public static bool IsDead(Triangle tria) { return tria.neighbors[0].triangle == null; }
/// <summary> /// Find the previous edge (clockwise) of the adjacent triangle. [rprev(abc) -> b**] /// </summary> public void RprevSelf() { //SymSelf(); int tmp = orient; orient = triangle.neighbors[tmp].orient; triangle = triangle.neighbors[tmp].triangle; //LprevSelf(); orient = minus1Mod3[orient]; //SymSelf(); tmp = orient; orient = triangle.neighbors[tmp].orient; triangle = triangle.neighbors[tmp].triangle; }
/// <summary> /// Find the next edge (counterclockwise) of the adjacent triangle. [rnext(abc) -> *a*] /// </summary> public void RnextSelf() { //SymSelf(); int tmp = orient; orient = triangle.neighbors[tmp].orient; triangle = triangle.neighbors[tmp].triangle; //LnextSelf(); orient = plus1Mod3[orient]; //SymSelf(); tmp = orient; orient = triangle.neighbors[tmp].orient; triangle = triangle.neighbors[tmp].triangle; }
/// <summary> /// Find the holes and infect them. Find the area constraints and infect /// them. Infect the convex hull. Spread the infection and kill triangles. /// Spread the area constraints. /// </summary> public void CarveHoles() { Otri searchtri = default(Otri); Vertex searchorg, searchdest; LocateResult intersect; Triangle[] regionTris = null; if (!mesh.behavior.Convex) { // Mark as infected any unprotected triangles on the boundary. // This is one way by which concavities are created. InfectHull(); } if (!mesh.behavior.NoHoles) { // Infect each triangle in which a hole lies. foreach (var hole in mesh.holes) { // Ignore holes that aren't within the bounds of the mesh. if (mesh.bounds.Contains(hole)) { // Start searching from some triangle on the outer boundary. searchtri.triangle = Mesh.dummytri; searchtri.orient = 0; searchtri.SymSelf(); // Ensure that the hole is to the left of this boundary edge; // otherwise, locate() will falsely report that the hole // falls within the starting triangle. searchorg = searchtri.Org(); searchdest = searchtri.Dest(); if (Primitives.CounterClockwise(searchorg, searchdest, hole) > 0.0) { // Find a triangle that contains the hole. intersect = mesh.locator.Locate(hole, ref searchtri); if ((intersect != LocateResult.Outside) && (!searchtri.IsInfected())) { // Infect the triangle. This is done by marking the triangle // as infected and including the triangle in the virus pool. searchtri.Infect(); viri.Add(searchtri.triangle); } } } } } // Now, we have to find all the regions BEFORE we carve the holes, because locate() won't // work when the triangulation is no longer convex. (Incidentally, this is the reason why // regional attributes and area constraints can't be used when refining a preexisting mesh, // which might not be convex; they can only be used with a freshly triangulated PSLG.) if (mesh.regions.Count > 0) { int i = 0; regionTris = new Triangle[mesh.regions.Count]; // Find the starting triangle for each region. foreach (var region in mesh.regions) { regionTris[i] = Mesh.dummytri; // Ignore region points that aren't within the bounds of the mesh. if (mesh.bounds.Contains(region.point)) { // Start searching from some triangle on the outer boundary. searchtri.triangle = Mesh.dummytri; searchtri.orient = 0; searchtri.SymSelf(); // Ensure that the region point is to the left of this boundary // edge; otherwise, locate() will falsely report that the // region point falls within the starting triangle. searchorg = searchtri.Org(); searchdest = searchtri.Dest(); if (Primitives.CounterClockwise(searchorg, searchdest, region.point) > 0.0) { // Find a triangle that contains the region point. intersect = mesh.locator.Locate(region.point, ref searchtri); if ((intersect != LocateResult.Outside) && (!searchtri.IsInfected())) { // Record the triangle for processing after the // holes have been carved. regionTris[i] = searchtri.triangle; regionTris[i].region = region.id; } } } i++; } } if (viri.Count > 0) { // Carve the holes and concavities. Plague(); } if (regionTris != null) { var iterator = new RegionIterator(mesh); for (int i = 0; i < regionTris.Length; i++) { if (regionTris[i] != Mesh.dummytri) { // Make sure the triangle under consideration still exists. // It may have been eaten by the virus. if (!Otri.IsDead(regionTris[i])) { // Apply one region's attribute and/or area constraint. iterator.Process(regionTris[i]); } } } } // Free up memory (virus pool should be empty anyway). viri.Clear(); }
static List<Vertex> IndexVertices(Triangle triangle, Dictionary<int, int> indexDict, ref int highestIndex, out int[] newIndices) { var newVertices = new List<Vertex>(); newIndices = new int[3]; if (indexDict.ContainsKey(triangle.P0)) { newIndices[0] = indexDict[triangle.P0]; } else { TriangleNet.Data.Vertex vertex0 = triangle.GetVertex(0); newVertices.Add(new Vertex((float)vertex0.X, (float)vertex0.Y)); indexDict.Add(vertex0.ID, highestIndex); newIndices[0] = highestIndex; highestIndex++; } if (indexDict.ContainsKey(triangle.P1)) { newIndices[1] = indexDict[triangle.P1]; } else { TriangleNet.Data.Vertex vertex1 = triangle.GetVertex(1); newVertices.Add(new Vertex((float)vertex1.X, (float)vertex1.Y)); indexDict.Add(vertex1.ID, highestIndex); newIndices[1] = highestIndex; highestIndex++; } if (indexDict.ContainsKey(triangle.P2)) { newIndices[2] = indexDict[triangle.P2]; } else { TriangleNet.Data.Vertex vertex2 = triangle.GetVertex(2); newVertices.Add(new Vertex((float)vertex2.X, (float)vertex2.Y)); indexDict.Add(vertex2.ID, highestIndex); newIndices[2] = highestIndex; highestIndex++; } return newVertices; }