//Rudimentary plane class class Plane{ float A,B,C,D; Plane(final PVector p0, final PVector n){ PVector norm=n.get(); norm.normalize(); A=norm.x; B=norm.y; C=norm.z; D=-A*p0.x-B*p0.y-C*p0.z; } Plane(final PVector p0, final PVector p1, final PVector p2){ A=p0.y*(p1.z-p2.z)+p1.y*(p2.z-p0.z)+p2.y*(p0.z-p1.z); B=p0.z*(p1.x-p2.x)+p1.z*(p2.x-p0.x)+p2.z*(p0.x-p1.x); C=p0.x*(p1.y-p2.y)+p1.x*(p2.y-p0.y)+p2.x*(p0.y-p1.y); PVector norm=new PVector(A,B,C); norm.normalize(); A=norm.x; B=norm.y; C=norm.z; D=-A*p0.x-B*p0.y-C*p0.z; } void flipNormal(){ A*=-1; B*=-1; C*=-1; D*=-1; } //returns 1 if p is on same side as normal, -1 if on opposite side, 0 if on the plane float side(final PVector p){ float tmp=A*p.x+B*p.y+C*p.z+D; if(tmp<-0.001f){ tmp=-1f; } else if(tmp>0.001f){ tmp=1f; } else{ tmp=0f; } return tmp; } } //Half-Edge Mesh //Source: http://www.flipcode.com/archives/The_Half-Edge_Data_Structure.shtml class HE_Mesh{ ArrayList vertices; ArrayList faces; ArrayList halfEdges; ArrayList edges; HE_Mesh(){ vertices=new ArrayList(); faces=new ArrayList(); halfEdges=new ArrayList(); edges=new ArrayList(); } HE_Face getFace(int i){ return (HE_Face)faces.get(i); } HE_Vertex getVertex(int i){ return (HE_Vertex)vertices.get(i); } HE_HalfEdge getHalfEdge(int i){ return (HE_HalfEdge)halfEdges.get(i); } HE_Edge getEdge(int i){ return (HE_Edge)edges.get(i); } // draw as a triangular mesh. void draw(){ Iterator faceItr = faces.iterator(); while(faceItr.hasNext()){ HE_Face face=(HE_Face)faceItr.next(); HE_HalfEdge halfEdge=face.halfEdge; HE_Vertex midFace=new HE_Vertex(0,0,0,0); int c=0; do{ HE_Vertex v=halfEdge.vert; midFace.x+=v.x; midFace.y+=v.y; midFace.z+=v.z; halfEdge=halfEdge.next; c++; } while(halfEdge!=face.halfEdge); midFace.x/=c; midFace.y/=c; midFace.z/=c; halfEdge=face.halfEdge; //If face has three vertices, ignore the midface vertex and just draw the triangle. //If the face has more than three vertices, draw as a series of triangles connecting the edges to the midface vertex. if(c==3){ beginShape(); do{ HE_Vertex v=halfEdge.vert; vertex(v.x,v.y,v.z); halfEdge= halfEdge.next; } while(halfEdge!=face.halfEdge); endShape(); } else{ beginShape(TRIANGLE_STRIP); do{ HE_Vertex v=halfEdge.vert; vertex(v.x,v.y,v.z); vertex(midFace.x,midFace.y,midFace.z); halfEdge= halfEdge.next; //v=halfEdge.vert; //vertex(v.x,v.y,v.z); } while(halfEdge!=face.halfEdge); HE_Vertex v=halfEdge.vert; vertex(v.x,v.y,v.z); endShape(); } } } void drawVertices(){ Iterator vertexItr = vertices.iterator(); while(vertexItr.hasNext()){ HE_Vertex v=(HE_Vertex)vertexItr.next(); pushMatrix(); translate(v.x,v.y,v.z); box(5); popMatrix(); } noFill(); } void drawEdges(){ Iterator eItr = edges.iterator(); while(eItr.hasNext()){ HE_Edge e=(HE_Edge)eItr.next(); line(e.halfEdge.vert.x,e.halfEdge.vert.y,e.halfEdge.vert.z,e.halfEdge.pair.vert.x,e.halfEdge.pair.vert.y,e.halfEdge.pair.vert.z); } } void drawCurves(){ Iterator faceItr = faces.iterator(); while(faceItr.hasNext()){ HE_Face face=(HE_Face)faceItr.next(); HE_HalfEdge halfEdge=face.halfEdge; HE_Vertex u=halfEdge.vert; HE_Vertex v=halfEdge.next.vert; beginShape(); vertex(0.5*(u.x+v.x),0.5*(u.y+v.y),0.5*(u.z+v.z)); do{ u=halfEdge.next.vert; v=halfEdge.next.next.vert; bezierVertex(u.x,u.y,u.z,u.x,u.y,u.z,0.5*(u.x+v.x),0.5*(u.y+v.y),0.5*(u.z+v.z)); halfEdge=halfEdge.next; } while(halfEdge!=face.halfEdge); endShape(CLOSE); } } void buildMesh(float[][] simpleVertices, int[][] simpleFaces){ vertices=new ArrayList(); faces=new ArrayList(); halfEdges=new ArrayList(); edges=new ArrayList(); //Add all input vertices to the mesh, the original index of the vertex is stored as an id. for(int i=0;i=0f){ newFaceVertices1.add(halfEdge.vert); } if(sides[halfEdge.vert.id]*centerside<=0f){ newFaceVertices2.add(halfEdge.vert); } for(int j=0;j2){ HE_Face newFace=new HE_Face(); newFaces.add(newFace); ArrayList faceEdges=new ArrayList(); for(int j=0;j0){ //Create a closed loop out of the collection of unpaired halfedges and associate a new face with this. //Easy to explain with a drawing, beyond my skill with words. HE_Face cutFace = new HE_Face(); ArrayList faceEdges=new ArrayList(); HE_HalfEdge he =(HE_HalfEdge)unpairedEdges.get(0); HE_HalfEdge hen=he; do{ hen=he.next.pair.next; while(!unpairedEdges.contains(hen)) hen=hen.pair.next; HE_HalfEdge newhe=new HE_HalfEdge(); faceEdges.add(newhe); if(cutFace.halfEdge==null) cutFace.halfEdge=newhe; newhe.vert=hen.vert; newhe.pair=he; he.pair=newhe; HE_Edge e=new HE_Edge(); e.halfEdge=newhe; he.edge=e; newhe.edge=e; newEdges.add(e); newhe.face=cutFace; he=hen; } while(hen!=(HE_HalfEdge)unpairedEdges.get(0)); cycleHalfEdges(faceEdges, true); newHalfEdges.addAll(faceEdges); newFaces.add(cutFace); } // update the mesh vertices=newVertices; faces=newFaces; halfEdges=newHalfEdges; edges=newEdges; reindex(); } } void splitSurface(Plane P){ ArrayList newVertices=new ArrayList(); ArrayList newFaces=new ArrayList(); ArrayList newHalfEdges=new ArrayList(); ArrayList newEdges=new ArrayList(); // get all split edges ArrayList splitEdges=retrieveSplitEdges(P); //check if the plane cuts the mesh at all, at least one point should be on the other side of the plane. //compared to the first point float[] sides = new float[vertices.size()]; boolean cut=false; for(int i=0;i0){ newFace=new HE_Face(); newFaces.add(newFace); faceEdges=new ArrayList(); for(int j=0;jd){ float ratio = (distanceToVertex-d)/distanceToVertex; PVector origin=PVector.mult(n,ratio); origin.add(center); cutPlanes.add(new Plane(origin,n)); } } for(int i=0;id){ float ratio = (distanceToVertex-d)/distanceToVertex; PVector origin=PVector.mult(n,ratio); origin.add(center); cutPlanes.add(new Plane(origin,n)); } } for(int i=0;i-0.001f)) return null; float u=(P.A*p0.x+P.B*p0.y+P.C*p0.z+P.D)/denom; if ((u<0.00f)||(u>1.0f)) return null; return new PVector(p0.x+u*(p1.x-p0.x),p0.y+u*(p1.y-p0.y),p0.z+u*(p1.z-p0.z)); } class HE_Vertex extends PVector{ int id; HE_HalfEdge halfEdge; HE_Vertex(float x, float y, float z, int id){ super(x,y,z); this.id=id; } HE_Vertex get(){ return new HE_Vertex(x,y,z,id); } } class HE_Face{ int id; HE_HalfEdge halfEdge; HE_Face(){ } } class SplitEdge{ HE_Edge edge; HE_Vertex splitVertex; SplitEdge(){ } SplitEdge(HE_Edge e, PVector p){ edge=e; splitVertex=new HE_Vertex(p.x,p.y,p.z,0); } }