// Reacreate a unity mesh with vertices, triangles, and normals. // TODO: IT NOW ASSUMES A FACE IS A TRIANGLE // TODO: FAN TRIANGULATION? Can we assume that all generated faces will be simple convex?? public Mesh GetMesh() { Mesh meshRes = new Mesh(); List <int> meshTriangles = new List <int>(); List <Vector3> meshVertices = new List <Vector3>(); List <Vector3> meshNormals = new List <Vector3>(); // Foreach face. Walk it and save the vertex and normal data toghether with triangle indices. int triIdx = 0; foreach (HEFace face in faces) { // Each face has a normal and an index into halfEdges // Get the face halfedges List <short> faceHalfEdges = HalfEdge.FaceHalfEdges(face, halfEdges); if (faceHalfEdges.Count != 3) { Debug.Assert(faceHalfEdges.Count == 3); } foreach (short i in faceHalfEdges) { meshVertices.Add(vertices[halfEdges[i].verIndex].v); meshNormals.Add(face.normal); meshTriangles.Add(triIdx); triIdx++; } } meshRes.vertices = meshVertices.ToArray(); meshRes.triangles = meshTriangles.ToArray(); meshRes.normals = meshNormals.ToArray(); return(meshRes); }
public void Triangulate() { // Update each face to contain three vertices. Adds new faces when necessary. int origFaceCount = faces.Count; for (int i = 0; i < origFaceCount; i++) { List <short> faceEdges = HalfEdge.FaceHalfEdges(faces[i], halfEdges); if (faceEdges.Count == 3) { // Already a triangle continue; } // There are two cases, 4 or 5 vertices, for 4 vertices we can just do it over the diagonal if (faceEdges.Count == 4) { List <short> onPlaneIdx = GetConfigEdges(faces[i], PlaneConfig.On); SplitFace(faces[i], halfEdges[onPlaneIdx[0]], halfEdges[halfEdges[halfEdges[onPlaneIdx[0]].nextIndex].nextIndex]); } else if (faceEdges.Count == 5) { // Algorithm; // Get the two vertices on the plane List <short> onPlaneIdx = GetConfigEdges(faces[i], PlaneConfig.On); List <short> leftPlaneIdx = GetConfigEdges(faces[i], PlaneConfig.Left); List <short> rightPlaneIdx = GetConfigEdges(faces[i], PlaneConfig.Right); // Either there are two on the left side or on the right side. (Always 2 On) // This will be the left place idx face. We need to create two new half-edges between the on edges // Lets say we have l1-l2-o1-r1-o2 then the right triangle is o1-r1-o2 // Should make a function that takes a face and two vertices (half edges rather) and splits it in two List <short> onEdgesIndices = GetConfigEdges(faces[i], PlaneConfig.On); SplitFace(faces[i], halfEdges[onEdgesIndices[0]], halfEdges[onEdgesIndices[1]]); // TODO: Make a verify function that verifies the half-edge data structure... // Check that the new faces are atleast the right size.. List <short> f1 = HalfEdge.FaceHalfEdges(faces[i], halfEdges); List <short> f2 = HalfEdge.FaceHalfEdges(faces[faces.Count - 1], halfEdges); // One of the new faces have 4 vertices, so we need to triangulate it / split into two if (f1.Count == 4) { SplitFace(faces[i], halfEdges[faces[i].heIndex], halfEdges[halfEdges[halfEdges[faces[i].heIndex].nextIndex].nextIndex]); } else { int idx = faces.Count - 1; SplitFace(faces[idx], halfEdges[faces[idx].heIndex], halfEdges[halfEdges[halfEdges[faces[idx].heIndex].nextIndex].nextIndex]); } } else { // Don't go here... // shouldn't be possible } } }
// Return indices of HalfEdges with vertices that have the given config List <short> GetConfigEdges(HEFace face, PlaneConfig config) { List <short> he = HalfEdge.FaceHalfEdges(face, halfEdges); List <short> res = new List <short>(); foreach (short s in he) { if (vertices[halfEdges[s].verIndex].config == config) { res.Add(s); } } return(res); }
private string PrintFaceConfig(HEFace face) { List <short> he = HalfEdge.FaceHalfEdges(face, halfEdges); string res = ""; string res1 = "face idx: "; foreach (short s in he) { res += " " + vertices[halfEdges[s].verIndex].config.ToString() + "(" + s + "," + halfEdges[s].nextIndex + ")" + " "; res1 += s + ": " + halfEdges[s].faceIndex + ". "; } res1 += ". with face pointing at = " + faces[halfEdges[he[0]].faceIndex].heIndex; return(res + "\n" + res1); }
private List <short> GetOnVertices(HEFace face) { List <short> res = new List <short>(); List <short> he = HalfEdge.FaceHalfEdges(face, halfEdges); foreach (short s in he) { if (vertices[halfEdges[s].verIndex].config == PlaneConfig.On) { res.Add(halfEdges[s].verIndex); } } return(res); }
private PlaneConfig GetFaceConfig(HEFace face) { // If any vertex is left / right the whole face is it List <short> heIdx = HalfEdge.FaceHalfEdges(face, halfEdges); foreach (short s in heIdx) { if (vertices[halfEdges[s].verIndex].config == PlaneConfig.Left) { return(PlaneConfig.Left); } else if (vertices[halfEdges[s].verIndex].config == PlaneConfig.Right) { return(PlaneConfig.Right); } } return(PlaneConfig.On); }