6 static void destroy_cell(struct frac_cell *cell);
7 static int build_cell(struct fracture *frac, int cellidx);
9 int frac_init(struct fracture *frac)
13 if(!(frac->cells = dynarr_alloc(0, sizeof *frac->cells))) {
19 void frac_destroy(struct fracture *frac)
26 num = dynarr_size(frac->cells);
27 for(i=0; i<num; i++) {
28 destroy_cell(frac->cells + i);
30 dynarr_free(frac->cells);
34 static void destroy_cell(struct frac_cell *cell)
38 cmesh_free(cell->mesh);
39 dynarr_free(cell->planes);
42 void frac_mesh(struct fracture *frac, const struct cmesh *m)
44 frac->mesh = (struct cmesh*)m;
47 int frac_point(struct fracture *frac, float x, float y, float z)
49 struct frac_cell cell;
50 struct frac_cell *tmp;
52 cgm_vcons(&cell.pt, x, y, z);
53 if(!(cell.mesh = cmesh_alloc())) {
56 if(!(cell.planes = dynarr_alloc(0, sizeof *cell.planes))) {
57 cmesh_free(cell.mesh);
60 if(!(tmp = dynarr_push(frac->cells, &cell))) {
61 cmesh_free(cell.mesh);
62 dynarr_free(cell.planes);
69 int frac_num_cells(struct fracture *frac)
71 return dynarr_size(frac->cells);
74 /* --- step 1: generate a bunch of points (or let the user add them manually) */
76 int frac_gen_points(struct fracture *frac, int num)
80 cgm_vec3 bbmin, bbmax, delta;
82 if(!frac || !frac->mesh) return -1;
83 if(!cmesh_poly_count(frac->mesh)) {
87 cmesh_aabbox(frac->mesh, &bbmin, &bbmax);
89 cgm_vsub(&delta, &bbmin);
91 for(i=0; i<num; i++) {
92 x = (float)rand() / RAND_MAX * delta.x + bbmin.x;
93 y = (float)rand() / RAND_MAX * delta.y + bbmin.y;
94 z = (float)rand() / RAND_MAX * delta.z + bbmin.z;
96 if(frac_point(frac, x, y, z) == -1) {
104 /* --- step 2: construct voronoi cells bounded by planes */
106 int frac_build_cells(struct fracture *frac)
110 for(i=0; i<dynarr_size(frac->cells); i++) {
111 if(build_cell(frac, i) == -1) {
119 static int build_cell(struct fracture *frac, int cellidx)
121 int i, j, num, clipres;
123 struct frac_cell *cell = frac->cells + cellidx;
124 struct poly poly, clipped, *polys, *pptr;
127 if(!(polys = dynarr_alloc(0, sizeof *polys))) {
131 cmesh_bsphere(frac->mesh, 0, &bsize);
134 num = dynarr_size(frac->cells);
135 for(i=0; i<num; i++) {
136 if(i == cellidx) continue;
137 midplane(&plane, &cell->pt, &frac->cells[i].pt);
138 plane_poly(&plane, &poly, bsize);
139 if(!(pptr = dynarr_push(polys, &poly))) {
145 num = dynarr_size(polys);
146 valid_planes = alloca(num * sizeof *valid_planes);
147 memset(valid_planes, 0xff, num * sizeof *valid_planes);
149 /* clip all planes against each other to end up with a convex cell */
150 cell->num_polys = num;
151 for(i=0; i<num; i++) {
152 for(j=0; j<num; j++) {
153 if(i == j || !valid_planes[j]) {
157 /* clip plane polygon i with plane j */
158 poly_plane(polys + j, &plane);
160 if((clipres = clip_poly(&clipped, polys + i, &plane)) < 0) {
161 /* completely clipped, mark it for removal */
169 if(!(cell->polys = malloc(cell->num_polys * sizeof *cell->polys))) {
173 for(i=0; i<num; i++) {
174 if(valid_planes[i]) {
175 assert(pptr - cell->polys < cell->num_polys);
178 destroy_poly(polys + i);
185 int frac_build_shell(struct fracture *frac)
190 int frac_build_walls(struct fracture *frac)
195 int frac_build(struct fracture *frac)
197 if(frac_build_cells(frac) == -1) {
200 if(frac_build_shell(frac) == -1) {
203 if(frac_build_walls(frac) == -1) {