// // Triangulate a single face // // After the edges of a triangle have been split, // we need to connect the new (odd) vertices so each // face is split into four faces. The figure below shows // one step of that process by adding an edge connecting // vertices v1 and v3. Once this is complete we will // update f->e = enew and lather, rinse, repeat. // We're done when e = e->next->next->next; this // condition also prevents us from triangulating a // face that has already been triangulated. // // Interestingly enough, this routine will triangulate // any polygon whether the edges have been split or not. // // * : even vertex (old vertices from before edge splitt // o : odd vertex (created from edge split) // f : original face // e = f->e : edge emanating from even vertex // enew, esym : newly added edge and its symmetric edge // fnew : newly added face // // v2 // * // / \ . avoiding // / \ . backslash // e2 /fnew \ e1 = e->next . as // / esym \ . last // v3 o.........o v1 = e1->v . character // / enew \ . on // e3 / \ e = f->e . line // / f \ . // / \ . // v4 *---------o---------* v0 = e->v // v5 public void triangulate(Face f) { Edge e = E.get(f.e); Edge e1 = E.get(e.next); // check to make sure this face isn't already triangular if (e.i != E.get(E.get(e.next).next).next) { // done when e == e->next->next->next do { Edge e2 = E.get(e1.next); Edge e3 = E.get(e2.next); // Edge = {i, sym, v, f, prev, next} Edge enew = new Edge(); enew.i = E.size(); Edge esym = new Edge(); esym.i = enew.i + 1; // Face = {i, e} Face fnew = new Face(); fnew.i = F.size(); fnew.e = e1.i; // set up esym esym.sym = enew.i; esym.v = e3.v; esym.f = fnew.i; esym.prev = e2.i; esym.next = e1.i; // set up enew enew.sym = esym.i; enew.v = e1.v; enew.f = f.i; enew.prev = e1.prev; enew.next = e2.next; E.add(enew); E.add(esym); F.add(fnew); // clean up loose ends // e1.prev.next, e2.next.prev, e1.prev, e2.next, e1.f, e2.f E.get(e1.prev).next = enew.i; e3.prev = enew.i; e1.prev = esym.i; e2.next = esym.i; e1.f = fnew.i; e2.f = fnew.i; f.e = enew.i; // set e1 and e2 for next step e1 = e3; // e2 = E.get(e3.next); } while (e.i != E.get(E.get(e.next).next).next); } }
protected void splitEdge(int e, Vec3 newPos) { Edge edge = E.get(e); Edge sym = E.get(edge.sym); Edge e0 = new Edge(); Edge e1 = new Edge(); Vert v0 = new Vert(); // set indices of new edges + vert e0.i = E.size(); e1.i = e0.i + 1; // set up v0 v0.coord = newPos; v0.i = V.size(); v0.e = e0.i; V.add(v0); // set up e0 e0.v = v0.i; e0.f = edge.f; e0.next = edge.next; e0.prev = edge.i; e0.sym = edge.sym; // set up e1 e1.v = v0.i; e1.f = sym.f; e1.next = sym.next; e1.prev = edge.sym; e1.sym = edge.i; E.add(e0); E.add(e1); // clean up connections with e and e.sym E.get(edge.next).prev = e0.i; E.get(sym.next).prev = e1.i; edge.next = e0.i; sym.next = e1.i; sym.sym = e0.i; edge.sym = e1.i; }
public Mesh(Vec3 verts[], int faces[][]) { V = new Vector<Vert>(verts.length); for (int i = 0; i < verts.length; i++) V.addElement(null); F = new Vector<Face>(faces.length); for (int i = 0; i < faces.length; i++) F.addElement(null); int numEdges = 0; for (int f = 0; f < faces.length; f++) numEdges += faces[f].length; E = new Vector<Edge>(numEdges); for (int i = 0; i < numEdges; i++) E.addElement(null); originalFaceVerts = new Vector<Integer>(faces.length); originalFaceEdges = new Vector<Integer>(faces.length); Hashtable<IntPair, Edge> edgeTable = new Hashtable<IntPair, Edge>(); int ei = 0; // base index for group of edges for next face for (int f = 0; f < faces.length; f++) { int[] face = faces[f]; // current face final int N = face.length; // number of edges in face for (int i = 0; i < N; i++) { Edge edge = new Edge(); edge.i = ei + i; final int v = face[i]; final int vnext = face[(i + 1) % N]; IntPair key = new IntPair(vnext, v); Edge sym = edgeTable.get(key); if (sym == null) { key = new IntPair(v, vnext); edgeTable.put(key, edge); } else { edge.sym = sym.i; sym.sym = ei + i; } edge.v = v; if (V.get(v) == null) { Vert wvert = new Vert(); wvert.i = v; wvert.e = edge.i; wvert.coord = new Vec3(verts[v]); V.set(v, wvert); } edge.f = f; edge.next = ei + (i + 1) % N; edge.prev = ei + (i + N - 1) % N; E.set(edge.i, edge); } Face wface = new Face(); wface.i = f; wface.e = ei; F.set(f, wface); ei += N; } // ensure mesh is triangular triangulate(); // get number of original faces originalFaceCount = F.size(); // get one of each original face's vertices for (int i = 0; i < originalFaceCount; i++) originalFaceVerts.add(E.get(F.get(i).e).v); for (int i = 0; i < originalFaceCount; i++) originalFaceEdges.add(F.get(i).e); // set the normals for the mesh setNormals(); }