From: John Tsiombikas Date: Sun, 29 Jan 2023 12:48:27 +0000 (+0200) Subject: foo X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=meshfrac;a=commitdiff_plain;h=34e07fdc87e289e9ce574df7755e5e781136c20b foo --- diff --git a/src/frac.c b/src/frac.c index 8a6bcae..071b5c2 100644 --- a/src/frac.c +++ b/src/frac.c @@ -4,6 +4,7 @@ #include "dynarr.h" static void destroy_cell(struct frac_cell *cell); +static int build_cell(struct fracture *frac, int cellidx); int frac_init(struct fracture *frac) { @@ -70,6 +71,8 @@ int frac_num_cells(struct fracture *frac) return dynarr_size(frac->cells); } +/* --- step 1: generate a bunch of points (or let the user add them manually) */ + int frac_gen_points(struct fracture *frac, int num) { int i; @@ -97,11 +100,49 @@ int frac_gen_points(struct fracture *frac, int num) return 0; } + +/* --- step 2: construct voronoi cells bounded by planes */ + int frac_build_cells(struct fracture *frac) { + int i; + + for(i=0; icells); i++) { + if(build_cell(frac, i) == -1) { + return -1; + } + } + return -1; } +static int build_cell(struct fracture *frac, int cellidx) +{ + int i, j, num; + struct plane plane, *pptr; + struct frac_cell *cell = frac->cells + cellidx; + + num = dynarr_size(frac->cells); + for(i=0; ipt, &frac->cells[i].pt); + if(!(pptr = dynarr_push(cell->planes, &plane))) { + return -1; + } + cell->planes = pptr; + } + + /* clip all planes against each other to end up with a convex cell */ + num = dynarr_size(cell->planes); + for(i=0; inorm); } +int plane_poly(const struct plane *plane, struct poly *poly, float size) +{ + static const float corn[][2] = {{1,1}, {-1,1}, {-1,-1}, {1, -1}}; + int i; + cgm_vec3 pos, up, right, dir; + size *= 0.5f; + + if(!(poly->verts = dynarr_alloc(4, sizeof *poly->verts))) { + fprintf(stderr, "plane_poly: failed to allocate polygon vertices\n"); + return -1; + } + + cgm_vcons(&up, 0, 1, 0); + if(1.0f - fabs(cgm_vdot(&up, &plane->norm)) < 1e-2) { + cgm_vcons(&up, 0, 0, -1); + } + cgm_vcross(&right, &up, &plane->norm); + cgm_vnormalize(&right); + cgm_vcross(&up, &plane.norm, &right); + cgm_vnormalize(&up); + + for(i=0; i<4; i++) { + v.x = plane->pt.x + (right.x * corn[i][0] + up.x * corn[i][1]) * size; + v.y = plane->pt.y + (right.y * corn[i][0] + up.y * corn[i][1]) * size; + v.z = plane->pt.z + (right.z * corn[i][0] + up.z * corn[i][1]) * size; + + + + +} + float ray_plane(const cgm_ray *ray, const struct plane *plane) { float ndotdir, t; @@ -93,3 +124,91 @@ float ray_poly(const cgm_ray *ray, const struct poly *poly) } return t; } + + +/* returns: + * 1 -> both inside + * 0 -> straddling and clipped + * -1 -> both outside + */ +static int clip_edge(struct poly *pout, const struct vertex *v0, const struct vertex *v1, + const struct plane *plane) +{ + float d0, d1, t; + cgm_ray ray; + int i, vnum = dynarr_size(pout->verts); + struct vertex vnew; + + d0 = plane_sdist(plane, &v0->pos); + d1 = plane_sdist(plane, &v1->pos); + + ray.orig = v0->pos; + ray.dir = v1->pos; + cgm_vsub(&ray.dir, &v0->pos); + + for(i=0; i<3; i++) { + ray.origin[i] = pos0[i]; + ray.dir[i] = pos1[i] - pos0[i]; + } + + if(d0 >= 0.0) { + /* start inside */ + if(d1 >= 0.0) { + /* all inside */ + DYNARR_PUSH(pout->verts, v1); /* append v1 */ + return 1; + } else { + /* going out */ + t = ray_plane(&ray, plane); + cgm_raypos(&vnew->pos, &ray, t); + + cgm_vlerp(&vnew->norm, &v0->norm, &v1->norm, t); + vnew->uv.x = cgm_lerp(v0->uv.x, v1->uv.x, t); + vnew->uv.y = cgm_lerp(v0->uv.y, v1->uv.y, t); + /* append new vertex on the intersection point */ + DYNARR_PUSH(pout->verts, &vnew); + } + } else { + /* start outside */ + if(d1 >= 0) { + /* going in */ + t = ray_plane(&ray, plane); + cgm_raypos(&vnew->pos, &ray, t); + + cgm_vlerp(&vnew->norm, &v0->norm, &v1->norm, t); + vnew->uv.x = cgm_lerp(v0->uv.x, v1->uv.x, t); + vnew->uv.y = cgm_lerp(v0->uv.y, v1->uv.y, t); + /* append new vertex on the intersection point */ + DYNARR_PUSH(pout->verts, &vnew); + /* then append v1 ... */ + DYNARR_PUSH(pout->verts, v1); + } else { + /* all outside */ + return -1; + } + } + + return 0; +} + + +int clip_poly(struct poly *pout, const struct poly *pin, const struct plane *plane) +{ + int i, nextidx, res = 0, vnum; + int edges_clipped = 0; + + dynarr_clear(pout->verts); + + vnum = dynarr_size(pin->verts); + for(i=0; i= vnum) nextidx = 0; + res = clip_edge(pout, pin->verts + i, pin->verts + nextidx, plane); + if(res == 0) { + ++edges_clipped; + } + } + + return edges_clipped > 0 ? 0 : 1; + +} diff --git a/src/geom.h b/src/geom.h index 14faa82..ebb6659 100644 --- a/src/geom.h +++ b/src/geom.h @@ -21,9 +21,12 @@ float plane_sdist(const struct plane *p, const cgm_vec3 *pt); void midplane(struct plane *p, const cgm_vec3 *a, const cgm_vec3 *b); void poly_plane(const struct poly *poly, struct plane *plane); +int plane_poly(const struct plane *plane, struct poly *poly, float size); /* returns negative if there's no intersection, parametric distance if there is */ float ray_plane(const cgm_ray *ray, const struct plane *plane); float ray_poly(const cgm_ray *ray, const struct poly *poly); +int clip_poly(struct poly *pout, const struct poly *pin, const struct plane *plane); + #endif /* GEOM_H_ */