X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffrac.c;h=a6ce0a8f56ce4d8de9caa24cf94b24419b378606;hb=f1410762198ad4b0ca8c0b47bd484ff2d3e09ddd;hp=048b8a04df5b887f9192c88a6fb4cda6d98e580c;hpb=47382e57c60544c263e6822ea8d76025c758c7b2;p=meshfrac diff --git a/src/frac.c b/src/frac.c index 048b8a0..a6ce0a8 100644 --- a/src/frac.c +++ b/src/frac.c @@ -241,12 +241,24 @@ static int mesh_poly(struct poly *poly, const struct cmesh *mesh, int faceidx) } while(0) static int build_cell_shell(struct cmesh *mesh, const struct cmesh *orig, - const struct frac_cell *cell) + struct frac_cell *cell) { - int i, j, k, nfaces, clipres; + int i, j, nfaces, clipres; struct plane plane; - struct poly poly, clipped; + struct poly poly, clipped, wallclipped; struct vertex *vert; + int *delwall; + struct plane *cplanes; + + /* array for marking wall polygons for deletion when they get clipped entirely */ + delwall = alloca(cell->num_polys * sizeof *delwall); + memset(delwall, 0, cell->num_polys * sizeof *delwall); + + /* array for pre-constructing the voronoi clipping planes */ + cplanes = alloca(cell->num_polys * sizeof *cplanes); + for(i=0; inum_polys; i++) { + poly_plane(cell->polys + i, cplanes + i); + } nfaces = cmesh_poly_count(orig); for(i=0; inum_polys; j++) { - poly_plane(cell->polys + j, &plane); - init_poly(&clipped); - if((clipres = clip_poly(&clipped, &poly, &plane)) < 0) { + if((clipres = clip_poly(&clipped, &poly, cplanes + j)) < 0) { destroy_poly(&clipped); break; } + + /* if the plane clipped the polygon, and the two polygons intersect + * within their bounds, also clip the cell polygon by the original + * mesh polygon. + * + * TODO clipping with the polygon's plane is incorrect, and will lead + * to gaps in the cell walls when the surface is concave. We'll need + * to clip by the polygon itself, which can make the wall polygon + * concave, and will need to be split into multiple convex ones. + */ + if(clipres == 0 && poly_poly(&poly, cell->polys + j)) { + poly_plane(&poly, &plane); + init_poly(&wallclipped); + + if((clipres = clip_poly(&wallclipped, cell->polys + j, &plane)) < 0) { + /* mark for deletion */ + delwall[j] = 1; + } else if(clipres == 0) { + destroy_poly(cell->polys + j); + cell->polys[j] = wallclipped; + } else { + destroy_poly(&wallclipped); + } + } + destroy_poly(&poly); poly = clipped; } @@ -272,13 +307,33 @@ static int build_cell_shell(struct cmesh *mesh, const struct cmesh *orig, } vert = poly.verts + 1; - for(k=0; knum_polys; i++) { + if(delwall[i]) { + struct poly tmp = cell->polys[i]; + cell->polys[i] = cell->polys[--cell->num_polys]; + destroy_poly(&tmp); + } + } + + /* add wall polygons to the mesh */ + for(i=0; inum_polys; i++) { + vert = cell->polys[i].verts + 1; + for(j=0; jpolys[i].verts)-2; j++) { + ADD_VERTEX(mesh, cell->polys[i].verts); + ADD_VERTEX(mesh, vert); vert++; + ADD_VERTEX(mesh, vert); + } + } + return 0; }