X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffrac.c;h=4263c6573e466b4879793c7b79a6c08f303fab30;hb=59a8deae3d561aa3797a6bf25c76803fe098cdf0;hp=048b8a04df5b887f9192c88a6fb4cda6d98e580c;hpb=47382e57c60544c263e6822ea8d76025c758c7b2;p=meshfrac diff --git a/src/frac.c b/src/frac.c index 048b8a0..4263c65 100644 --- a/src/frac.c +++ b/src/frac.c @@ -132,17 +132,19 @@ static int build_cell(struct fracture *frac, int cellidx) } cmesh_bsphere(frac->mesh, 0, &bsize); - bsize *= 2; + bsize *= 8; num = dynarr_size(frac->cells); for(i=0; ipt, &frac->cells[i].pt); - plane_poly(&plane, &poly, bsize); - if(!(pptr = dynarr_push(polys, &poly))) { - return -1; + midplane(&plane, &frac->cells[i].pt, &cell->pt, frac->cell_gap); + if(plane_sdist(&plane, &cell->pt) > 0.0f) { + plane_poly(&plane, &poly, bsize); + if(!(pptr = dynarr_push(polys, &poly))) { + return -1; + } + polys = pptr; } - polys = pptr; } num = dynarr_size(polys); @@ -191,7 +193,7 @@ static int build_cell(struct fracture *frac, int cellidx) static int mesh_poly(struct poly *poly, const struct cmesh *mesh, int faceidx) { int i, vsz, nsz, uvsz; - struct vertex vert, *tmpvert; + struct vertex *tmpvert, vert = {0}; const float *varr, *narr, *uvarr; unsigned int vidx; @@ -215,11 +217,15 @@ static int mesh_poly(struct poly *poly, const struct cmesh *mesh, int faceidx) vert.pos.x = varr[vidx * vsz]; vert.pos.y = varr[vidx * vsz + 1]; vert.pos.z = varr[vidx * vsz + 2]; - vert.norm.x = narr[vidx * nsz]; - vert.norm.y = narr[vidx * nsz + 1]; - vert.norm.z = narr[vidx * nsz + 2]; - vert.uv.x = uvarr[vidx * uvsz]; - vert.uv.y = uvarr[vidx * uvsz + 1]; + if(narr) { + vert.norm.x = narr[vidx * nsz]; + vert.norm.y = narr[vidx * nsz + 1]; + vert.norm.z = narr[vidx * nsz + 2]; + } + if(uvarr) { + vert.uv.x = uvarr[vidx * uvsz]; + vert.uv.y = uvarr[vidx * uvsz + 1]; + } if(!(tmpvert = dynarr_push(poly->verts, &vert))) { destroy_poly(poly); @@ -241,12 +247,28 @@ 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); + /* flip the plane normal towards the inside of the cell, to clip everything + * outside the cell + */ + cgm_vcons(&cplanes[i].norm, -cplanes[i].norm.x, -cplanes[i].norm.y, -cplanes[i].norm.z); + } 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; + destroy_poly(&wallclipped); + } else if(clipres == 0) { + destroy_poly(cell->polys + j); + cell->polys[j] = wallclipped; + } else { + destroy_poly(&wallclipped); + } + } + destroy_poly(&poly); poly = clipped; } @@ -272,13 +318,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; }