// Cut the face in two parts. Assumes that the face is convex public Face Cut(Vertex v1, Vertex v2) { Debug.Assert(v1.hmesh == hmesh); Debug.Assert(v2.hmesh == hmesh); Debug.Assert(v1.halfedge != null); Debug.Assert(v2.halfedge != null); Debug.Assert(v1 != v2); Halfedge v1He = null; Halfedge v2He = null; foreach (var he in Circulate()) { if (he.vert == v1) { v1He = he; } else if (he.vert == v2) { v2He = he; } } if (v1He == null || v2He == null) { Debug.LogError("Cannot find vertices for split"); return(null); } Debug.Assert(v1He != v2He); Halfedge v1HeNext = v1He.next; Halfedge v2HeNext = v2He.next; Face f = hmesh.CreateFace(); Halfedge he1 = hmesh.CreateHalfedge(); Halfedge he2 = hmesh.CreateHalfedge(); he1.Glue(he2); v1He.Link(he1); he1.Link(v2HeNext); v2He.Link(he2); he2.Link(v1HeNext); he1.vert = v2; he2.vert = v1; halfedge = he1; ReassignFaceToEdgeLoop(); f.halfedge = he2; f.ReassignFaceToEdgeLoop(); v1.halfedge = v1HeNext; v2.halfedge = v2HeNext; return(f); }
public static HMesh CreateTestMeshQuad() { HMesh mesh = new HMesh(); var face = mesh.CreateFace(); var edges = new[] { mesh.CreateHalfedge(), mesh.CreateHalfedge(), mesh.CreateHalfedge(), mesh.CreateHalfedge(), }; var verts = new[] { mesh.CreateVertex(new Vector3(0, 0, 0)), mesh.CreateVertex(new Vector3(1, 0, 0)), mesh.CreateVertex(new Vector3(1, 0, 1)), mesh.CreateVertex(new Vector3(0, 0, 1)), }; for (int i = 0; i < 4; i++) { edges[i].Link(face); edges[i].next = edges[(i + 1) % 4]; edges[(i + 1) % 4].prev = edges[i]; edges[i].vert = verts[i]; } return(mesh); }
public static HMesh CreateTestMeshPolygon(EarClipTest clip) { HMesh mesh = new HMesh(); Transform t = clip.transform; var face = mesh.CreateFace(); var edges = new Halfedge[t.childCount]; var verts = new List <Vertex>(); for (int i = 0; i < t.childCount; i++) { edges[i] = mesh.CreateHalfedge(); verts.Add(mesh.CreateVertex(t.GetChild(i).position)); } for (int i = 0; i < t.childCount; i++) { edges[i].Link(face); edges[i].next = edges[(i + 1) % t.childCount]; edges[(i + 1) % t.childCount].prev = edges[i]; edges[i].vert = verts[i]; } return(mesh); }
public static HMesh CreateTestMeshQuad() { HMesh mesh = new HMesh(); var face = mesh.CreateFace(); var edges = new Halfedge[]{ mesh.CreateHalfedge(), mesh.CreateHalfedge(), mesh.CreateHalfedge(), mesh.CreateHalfedge(), }; var verts = new Vertex[]{ mesh.CreateVertex(new Vector3(0,0,0)), mesh.CreateVertex(new Vector3(1,0,0)), mesh.CreateVertex(new Vector3(1,0,1)), mesh.CreateVertex(new Vector3(0,0,1)), }; for (int i=0;i<4;i++){ edges[i].Link(face); edges[i].next = edges[(i+1)%4]; edges[(i+1)%4].prev = edges[i]; edges[i].vert = verts[i]; verts[i].halfedge = edges[i].next; } return mesh; }
public static HMesh CreateTestMeshNGon(int n) { HMesh mesh = new HMesh(); var face = mesh.CreateFace(); List <Halfedge> edges = new List <Halfedge>(); List <Vertex> verts = new List <Vertex> (); for (var i = 0; i < n; i++) { edges.Add(mesh.CreateHalfedge()); verts.Add(mesh.CreateVertex(new Vector3(Mathf.Sin((i * Mathf.PI * 2) / n), 0, Mathf.Cos((i * Mathf.PI * 2) / n)))); } for (var i = 0; i < n; i++) { edges[i].Link(face); edges[i].next = edges[(i + 1) % n]; edges[(i + 1) % n].prev = edges[i]; edges[i].vert = verts[i]; } return(mesh); }
// Cut the face in two parts. Assumes that the face is convex // The new face is always created as the one that contains vertices between v1 and v2 public Face Cut(Vertex v1, Vertex v2) { Debug.Assert(v1.hmesh == hmesh); Debug.Assert(v2.hmesh == hmesh); Debug.Assert(v1.halfedge != null); Debug.Assert(v2.halfedge != null); Debug.Assert(v1 != v2); Halfedge v1He = null; Halfedge v2He = null; var edges = Circulate(); Debug.Assert(edges.Count > 3); foreach (var he in edges) { if (he.vert == v1) { v1He = he; } else if (he.vert == v2) { v2He = he; } } if (v1He == null || v2He == null) { if (v1He == null) { Debug.Log("Could not find first parameter"); } if (v2He == null) { Debug.Log("Could not find second parameter"); } return(null); } Debug.Assert(v1He != v2He); if (v1He.prev.vert == v2) { Debug.LogWarning("face " + id + " cut adjacent vertices " + v1 + " to " + v2); return(this); } if (v2He.prev.vert == v1) { Debug.LogWarning("face " + id + " cut adjacent vertices " + v1 + " to " + v2); return(this); } Halfedge v1HeNext = v1He.next; Halfedge v2HeNext = v2He.next; Face f = hmesh.CreateFace(); Halfedge he1 = hmesh.CreateHalfedge(); Halfedge he2 = hmesh.CreateHalfedge(); he1.Glue(he2); v1He.Link(he1); he1.Link(v2HeNext); v2He.Link(he2); he2.Link(v1HeNext); he1.vert = v2; he2.vert = v1; halfedge = he1; ReassignFaceToEdgeLoop(); f.halfedge = he2; f.ReassignFaceToEdgeLoop(); return(f); }
public HMesh Copy() { List <Vertex> fromVert = new List <Vertex>(); List <Face> fromFaces = new List <Face>(); List <Halfedge> fromHalfedge = new List <Halfedge>(); List <Vertex> toVert = new List <Vertex>(); List <Face> toFace = new List <Face>(); List <Halfedge> toHalfedge = new List <Halfedge>(); HMesh newMesh = new HMesh(); int index = 0; foreach (var v in vertices) { v.label = index; fromVert.Add(v); var nv = newMesh.CreateVertex(v.positionD); nv.uv1 = v.uv1; nv.uv2 = v.uv2; toVert.Add(nv); index++; } index = 0; foreach (var f in faces) { f.label = index; fromFaces.Add(f); var nf = newMesh.CreateFace(); nf.label = f.label; toFace.Add(nf); index++; } index = 0; foreach (var e in halfedges) { e.label = index; fromHalfedge.Add(e); toHalfedge.Add(newMesh.CreateHalfedge()); index++; } foreach (var from in faces) { Face to = toFace[from.label]; if (from.halfedge != null) { to.halfedge = toHalfedge[from.halfedge.label]; } } foreach (var from in halfedges) { Halfedge to = toHalfedge[from.label]; if (from.face != null) { to.face = toFace[from.face.label]; } if (from.opp != null) { to.opp = toHalfedge[from.opp.label]; } if (from.next != null) { to.next = toHalfedge[from.next.label]; } if (from.prev != null) { to.prev = toHalfedge[from.prev.label]; } if (from.vert != null) { to.vert = toVert[from.vert.label]; } } return(newMesh); }
/// <summary> /// Split edges (and vertices) if /// angle between faces is less than sharpEdgeAngle /// or if face ids are different (when splitByFaceId is true) /// Note that this will not preserve the edge labels nor face labels /// </summary> /// <param name="sharpEdgeAngle"></param> /// <param name="splitByFaceId"></param> // Creates a new HMesh where sharp edges and materials (defined by face labels) results in edge splits public HMesh Split(bool splitByFaceLabel = true, double sharpEdgeAngle = 360) { MarkSharpEdges(sharpEdgeAngle); if (splitByFaceLabel) { MarkSharpEdgesByLabel(); } Halfedge[] oldIdToNewEdge = new Halfedge[halfedgeMaxId + 1]; // main concept: // halfedges with label != 0 should not be glued together // A vertex should be split into multiple vertices and assigned to regions of halfedges. // a pair of the max outgoing he id for a single side and the vertex id Vertex[] splitVertex = new Vertex[halfedgeMaxId + 1]; HMesh newHMesh = new HMesh(); var findOrCreateVertex = new Func <Halfedge, Vertex>(delegate(Halfedge he){ // find maximum ingoing he var h = he; // rewind while (h.opp != null && h.label == 0 && h.opp.prev != he) { h = h.opp.prev; } int maxId = h.id; var first = h; while (h.next.opp != null && h.next.label == 0 && h.next.opp != first) { h = h.next.opp; maxId = Mathf.Max(h.id, maxId); } Vertex res = splitVertex[maxId]; if (res == null) { res = newHMesh.CreateVertex(he.vert.positionD); res.label = he.vert.label; res.uv1 = he.vert.uv1; res.uv2 = he.vert.uv2; splitVertex[maxId] = res; } return(res); }); foreach (var face in GetFacesRaw()) { // copy the face and half edges Face newFace = newHMesh.CreateFace(); newFace.label = face.label; var edges = face.Circulate(); var edgeList = new Halfedge[edges.Count]; var vertexList = new Vertex[edges.Count]; for (int i = 0; i < edges.Count; i++) { var newEdge = newHMesh.CreateHalfedge(); oldIdToNewEdge[edges[i].id] = newEdge; var newVertex = findOrCreateVertex(edges[i]); edgeList[i] = newEdge; vertexList[i] = newVertex; if (i > 0) { edgeList[i - 1].Link(edgeList[i]); } if (i == edges.Count - 1) { edgeList[i].Link(edgeList[0]); } newEdge.Link(newFace); } for (int i = 0; i < edgeList.Length; i++) { edgeList[i].vert = vertexList[i]; } } foreach (var oldHE in GetHalfedgesRaw()) { if (oldHE.opp == null || oldHE.label != 0) { continue; } if (oldHE.opp.id < oldHE.id) { continue; // only glue one way } var newHe = oldIdToNewEdge[oldHE.id]; var newHeOpp = oldIdToNewEdge[oldHE.opp.id]; newHe.Glue(newHeOpp); } return(newHMesh); }
public HMesh Copy() { List<Vertex> fromVert = new List<Vertex>(); List<Face> fromFaces = new List<Face>(); List<Halfedge> fromHalfedge = new List<Halfedge>(); List<Vertex> toVert = new List<Vertex>(); List<Face> toFace = new List<Face>(); List<Halfedge> toHalfedge = new List<Halfedge>(); HMesh newMesh = new HMesh(); int index = 0; foreach (var v in vertices){ v.label = index; fromVert.Add(v); var nv = newMesh.CreateVertex(v.position); nv.uv1 = v.uv1; nv.uv2 = v.uv2; toVert.Add(nv); index++; } index = 0; foreach (var f in faces){ f.label = index; fromFaces.Add(f); var nf = newMesh.CreateFace(); nf.label = f.label; toFace.Add(nf); index++; } index = 0; foreach (var e in halfedges){ e.label = index; fromHalfedge.Add(e); toHalfedge.Add(newMesh.CreateHalfedge()); index++; } // copy references foreach (var from in vertices){ Vertex to = toVert[from.label]; if (from.halfedge != null){to.halfedge = toHalfedge[from.halfedge.label];} } foreach (var from in faces){ Face to = toFace[from.label]; if (from.halfedge != null){to.halfedge = toHalfedge[from.halfedge.label];} } foreach (var from in halfedges){ Halfedge to = toHalfedge[from.label]; if (from.face != null){to.face = toFace[from.face.label];} if (from.opp != null){to.opp = toHalfedge[from.opp.label];} if (from.next != null){to.next = toHalfedge[from.next.label];} if (from.prev != null){to.prev = toHalfedge[from.prev.label];} if (from.vert != null){to.vert = toVert[from.vert.label];} } return newMesh; }