From 47382e57c60544c263e6822ea8d76025c758c7b2 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 8 Feb 2023 00:14:17 +0200 Subject: [PATCH] shell mesh --- main.c | 68 +++++++++++++++++++++++++--- src/cmesh.c | 145 +++++++++++++++++++++++++++++------------------------------ src/cmesh.h | 55 ++++++++++++----------- src/frac.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++------- src/frac.h | 2 + src/geom.c | 9 +++- 6 files changed, 296 insertions(+), 122 deletions(-) diff --git a/main.c b/main.c index 724fd70..2218f45 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,7 @@ #include "meshgen.h" #include "frac.h" #include "sdr.h" +#include "dynarr.h" static const char *vsdr_src = "varying vec3 v_norm, v_ldir, v_vdir;\n" @@ -57,7 +58,8 @@ static unsigned int sdr; static int cur, pending; static int show_orig = 1; -static int show_points; +static int show_points, show_planes, show_shell; +static int cur_cell; int main(int argc, char **argv) @@ -135,7 +137,8 @@ static void update(void) if(pending > cur) { switch(cur) { case 0: - if(frac_gen_points(&frac, 16) == -1) { + printf("Generate points...\n"); + if(frac_gen_points(&frac, 16) != -1) { cur++; } else { pending = cur; @@ -144,22 +147,28 @@ static void update(void) break; case 1: + printf("Build cells...\n"); if(frac_build_cells(&frac) != -1) { cur++; } else { pending = cur; } + show_planes = 1; break; case 2: + printf("Construct shell...\n"); if(frac_build_shell(&frac) != -1) { cur++; } else { pending = cur; } + show_orig = 0; + show_shell = 1; break; case 3: + printf("Construct walls...\n"); if(frac_build_walls(&frac) != -1) { cur++; } else { @@ -176,7 +185,8 @@ static void update(void) static void display(void) { - int i, num; + int i, j, num; + struct poly *poly; update(); @@ -198,15 +208,19 @@ static void display(void) bind_program(0); glPushAttrib(GL_ENABLE_BIT); - glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glPointSize(2.0f); glBegin(GL_POINTS); - glColor3f(0.1, 0.8, 0.1); for(i=0; iverts); j++) { + glVertex3fv(&poly->verts[j].pos.x); + } + glEnd(); + poly++; + } + + glPopAttrib(); + } + + if(show_shell) { + bind_program(sdr); + cmesh_draw(frac.cells[cur_cell].mesh); + } + assert(glGetError() == GL_NO_ERROR); glutSwapBuffers(); } @@ -247,6 +286,25 @@ static void keydown(unsigned char key, int x, int y) glutPostRedisplay(); break; + case 'P': + show_planes ^= 1; + glutPostRedisplay(); + break; + + case ']': + cur_cell = (cur_cell + 1) % frac_num_cells(&frac); + printf("current cell: %d\n", cur_cell); + glutPostRedisplay(); + break; + + case '[': + if(--cur_cell < 0) { + cur_cell = frac_num_cells(&frac) - 1; + printf("current cell: %d\n", cur_cell); + glutPostRedisplay(); + } + break; + default: if(key >= '1' && key <= '4') { n = key - '0'; diff --git a/src/cmesh.c b/src/cmesh.c index 71f58af..3492ef2 100644 --- a/src/cmesh.c +++ b/src/cmesh.c @@ -61,9 +61,9 @@ struct cmesh { }; -static int clone(struct cmesh *cmdest, struct cmesh *cmsrc, struct submesh *sub); -static int pre_draw(struct cmesh *cm); -static void post_draw(struct cmesh *cm, int cur_sdr); +static int clone(struct cmesh *cmdest, const struct cmesh *cmsrc, struct submesh *sub); +static int pre_draw(const struct cmesh *cm); +static void post_draw(const struct cmesh *cm, int cur_sdr); static void update_buffers(struct cmesh *cm); static void update_wire_ibo(struct cmesh *cm); static void calc_aabb(struct cmesh *cm); @@ -176,12 +176,12 @@ void cmesh_clear(struct cmesh *cm) cmesh_clear_submeshes(cm); } -int cmesh_clone(struct cmesh *cmdest, struct cmesh *cmsrc) +int cmesh_clone(struct cmesh *cmdest, const struct cmesh *cmsrc) { return clone(cmdest, cmsrc, 0); } -static int clone(struct cmesh *cmdest, struct cmesh *cmsrc, struct submesh *sub) +static int clone(struct cmesh *cmdest, const struct cmesh *cmsrc, struct submesh *sub) { int i, nelem, vstart, vcount, istart, icount; char *srcname, *name = 0; @@ -240,7 +240,8 @@ static int clone(struct cmesh *cmdest, struct cmesh *cmsrc, struct submesh *sub) free(cmdest->vattr[i].data); if(cmesh_has_attrib(cmsrc, i)) { - cmesh_attrib(cmsrc, i); /* force validation of the actual data on the source mesh */ + /* force validation of the actual data on the source mesh */ + cmesh_attrib((struct cmesh*)cmsrc, i); nelem = cmsrc->vattr[i].nelem; cmdest->vattr[i].nelem = nelem; @@ -256,7 +257,8 @@ static int clone(struct cmesh *cmdest, struct cmesh *cmsrc, struct submesh *sub) } if(cmesh_indexed(cmsrc)) { - cmesh_index(cmsrc); /* force validation .... */ + /* force validation .... */ + cmesh_index((struct cmesh*)cmsrc); cmdest->idata = iarr; cmdest->icount = icount; @@ -334,12 +336,12 @@ int cmesh_set_name(struct cmesh *cm, const char *name) return 0; } -const char *cmesh_name(struct cmesh *cm) +const char *cmesh_name(const struct cmesh *cm) { return cm->name; } -int cmesh_has_attrib(struct cmesh *cm, int attr) +int cmesh_has_attrib(const struct cmesh *cm, int attr) { if(attr < 0 || attr >= CMESH_NUM_ATTR) { return 0; @@ -347,7 +349,7 @@ int cmesh_has_attrib(struct cmesh *cm, int attr) return cm->vattr[attr].vbo_valid | cm->vattr[attr].data_valid; } -int cmesh_indexed(struct cmesh *cm) +int cmesh_indexed(const struct cmesh *cm) { return cm->ibo_valid | cm->idata_valid; } @@ -394,7 +396,7 @@ float *cmesh_attrib(struct cmesh *cm, int attr) return (float*)cmesh_attrib_ro(cm, attr); } -const float *cmesh_attrib_ro(struct cmesh *cm, int attr) +const float *cmesh_attrib_ro(const struct cmesh *cm, int attr) { void *tmp; int nelem; @@ -407,23 +409,25 @@ const float *cmesh_attrib_ro(struct cmesh *cm, int attr) #if GL_ES_VERSION_2_0 return 0; #else - if(!cm->vattr[attr].vbo_valid) { + struct cmesh *m = (struct cmesh*)cm; + + if(!m->vattr[attr].vbo_valid) { return 0; } /* local data copy unavailable, grab the data from the vbo */ - nelem = cm->vattr[attr].nelem; - if(!(cm->vattr[attr].data = malloc(cm->nverts * nelem * sizeof(float)))) { + nelem = m->vattr[attr].nelem; + if(!(m->vattr[attr].data = malloc(m->nverts * nelem * sizeof(float)))) { return 0; } - cm->vattr[attr].count = cm->nverts * nelem; + m->vattr[attr].count = m->nverts * nelem; - glBindBuffer(GL_ARRAY_BUFFER, cm->vattr[attr].vbo); + glBindBuffer(GL_ARRAY_BUFFER, m->vattr[attr].vbo); tmp = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); - memcpy(cm->vattr[attr].data, tmp, cm->nverts * nelem * sizeof(float)); + memcpy(m->vattr[attr].data, tmp, m->nverts * nelem * sizeof(float)); glUnmapBuffer(GL_ARRAY_BUFFER); - cm->vattr[attr].data_valid = 1; + m->vattr[attr].data_valid = 1; #endif } return cm->vattr[attr].data; @@ -435,17 +439,22 @@ float *cmesh_attrib_at(struct cmesh *cm, int attr, int idx) return vptr ? vptr + idx * cm->vattr[attr].nelem : 0; } -const float *cmesh_attrib_at_ro(struct cmesh *cm, int attr, int idx) +const float *cmesh_attrib_at_ro(const struct cmesh *cm, int attr, int idx) { const float *vptr = cmesh_attrib_ro(cm, attr); return vptr ? vptr + idx * cm->vattr[attr].nelem : 0; } -int cmesh_attrib_count(struct cmesh *cm, int attr) +int cmesh_attrib_count(const struct cmesh *cm, int attr) { return cmesh_has_attrib(cm, attr) ? cm->nverts : 0; } +int cmesh_attrib_nelem(const struct cmesh *cm, int attr) +{ + return cmesh_has_attrib(cm, attr) ? cm->vattr[attr].nelem : 0; +} + int cmesh_push_attrib(struct cmesh *cm, int attr, float *v) { float *vptr; @@ -549,7 +558,7 @@ unsigned int *cmesh_index(struct cmesh *cm) return (unsigned int*)cmesh_index_ro(cm); } -const unsigned int *cmesh_index_ro(struct cmesh *cm) +const unsigned int *cmesh_index_ro(const struct cmesh *cm) { int nidx; unsigned int *tmp; @@ -558,31 +567,33 @@ const unsigned int *cmesh_index_ro(struct cmesh *cm) #if GL_ES_VERSION_2_0 return 0; #else - if(!cm->ibo_valid) { + struct cmesh *m = (struct cmesh*)cm; + + if(!m->ibo_valid) { return 0; } /* local copy is unavailable, grab the data from the ibo */ - nidx = cm->nfaces * 3; - if(!(tmp = malloc(nidx * sizeof *cm->idata))) { + nidx = m->nfaces * 3; + if(!(tmp = malloc(nidx * sizeof *m->idata))) { return 0; } - free(cm->idata); - cm->idata = tmp; - cm->icount = nidx; + free(m->idata); + m->idata = tmp; + m->icount = nidx; - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cm->ibo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo); tmp = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY); - memcpy(cm->idata, tmp, nidx * sizeof *cm->idata); + memcpy(m->idata, tmp, nidx * sizeof *m->idata); glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); - cm->idata_valid = 1; + m->idata_valid = 1; #endif } return cm->idata; } -int cmesh_index_count(struct cmesh *cm) +int cmesh_index_count(const struct cmesh *cm) { return cm->nfaces * 3; } @@ -604,7 +615,7 @@ int cmesh_push_index(struct cmesh *cm, unsigned int idx) return 0; } -int cmesh_poly_count(struct cmesh *cm) +int cmesh_poly_count(const struct cmesh *cm) { if(cm->nfaces) { return cm->nfaces; @@ -638,7 +649,7 @@ void cmesh_invalidate_index(struct cmesh *cm) cm->ibo_valid = 0; } -int cmesh_append(struct cmesh *cmdest, struct cmesh *cmsrc) +int cmesh_append(struct cmesh *cmdest, const struct cmesh *cmsrc) { int i, nelem, newsz, origsz, srcsz; float *vptr; @@ -784,7 +795,7 @@ int cmesh_remove_submesh(struct cmesh *cm, int idx) return 0; } -int cmesh_find_submesh(struct cmesh *cm, const char *name) +int cmesh_find_submesh(const struct cmesh *cm, const char *name) { int idx = 0; struct submesh *sm = cm->sublist; @@ -799,12 +810,12 @@ int cmesh_find_submesh(struct cmesh *cm, const char *name) return -1; } -int cmesh_submesh_count(struct cmesh *cm) +int cmesh_submesh_count(const struct cmesh *cm) { return cm->subcount; } -static struct submesh *get_submesh(struct cmesh *m, int idx) +static struct submesh *get_submesh(const struct cmesh *m, int idx) { struct submesh *sm = m->sublist; while(sm && --idx >= 0) { @@ -813,7 +824,7 @@ static struct submesh *get_submesh(struct cmesh *m, int idx) return sm; } -int cmesh_clone_submesh(struct cmesh *cmdest, struct cmesh *cm, int subidx) +int cmesh_clone_submesh(struct cmesh *cmdest, const struct cmesh *cm, int subidx) { struct submesh *sub; @@ -827,28 +838,16 @@ int cmesh_clone_submesh(struct cmesh *cmdest, struct cmesh *cm, int subidx) /* assemble a complete vertex by adding all the useful attributes */ int cmesh_vertex(struct cmesh *cm, float x, float y, float z) { - int i, j; + int i; cgm_wcons(cm->cur_val + CMESH_ATTR_VERTEX, x, y, z, 1.0f); cm->vattr[CMESH_ATTR_VERTEX].data_valid = 1; cm->vattr[CMESH_ATTR_VERTEX].nelem = 3; for(i=0; ivattr[i].data_valid) { - int newsz = cm->vattr[i].count + cm->vattr[i].nelem; - float *tmp = realloc(cm->vattr[i].data, newsz * sizeof *tmp); - if(!tmp) return -1; - tmp += cm->vattr[i].count; - - cm->vattr[i].data = tmp; - cm->vattr[i].count = newsz; - - for(j=0; jvattr[i].nelem; j++) { - *tmp++ = *(&cm->cur_val[i].x + j); - } + if(cm->vattr[i].nelem > 0) { + cmesh_push_attrib(cm, i, &cm->cur_val[i].x); } - cm->vattr[i].vbo_valid = 0; - cm->vattr[i].data_valid = 1; } if(cm->idata_valid) { @@ -1066,13 +1065,13 @@ void cmesh_calc_face_normals(struct cmesh *cm) /* TODO */ } -static int pre_draw(struct cmesh *cm) +static int pre_draw(const struct cmesh *cm) { int i, loc, cur_sdr; glGetIntegerv(GL_CURRENT_PROGRAM, &cur_sdr); - update_buffers(cm); + update_buffers((struct cmesh*)cm); if(!cm->vattr[CMESH_ATTR_VERTEX].vbo_valid) { return -1; @@ -1125,7 +1124,7 @@ static int pre_draw(struct cmesh *cm) return cur_sdr; } -void cmesh_draw(struct cmesh *cm) +void cmesh_draw(const struct cmesh *cm) { int cur_sdr; @@ -1144,7 +1143,7 @@ void cmesh_draw(struct cmesh *cm) post_draw(cm, cur_sdr); } -void cmesh_draw_range(struct cmesh *cm, int start, int count) +void cmesh_draw_range(const struct cmesh *cm, int start, int count) { int cur_sdr; @@ -1163,7 +1162,7 @@ void cmesh_draw_range(struct cmesh *cm, int start, int count) post_draw(cm, cur_sdr); } -void cmesh_draw_submesh(struct cmesh *cm, int subidx) +void cmesh_draw_submesh(const struct cmesh *cm, int subidx) { struct submesh *sm = cm->sublist; @@ -1179,7 +1178,7 @@ void cmesh_draw_submesh(struct cmesh *cm, int subidx) } } -static void post_draw(struct cmesh *cm, int cur_sdr) +static void post_draw(const struct cmesh *cm, int cur_sdr) { int i; @@ -1211,14 +1210,14 @@ static void post_draw(struct cmesh *cm, int cur_sdr) } } -void cmesh_draw_wire(struct cmesh *cm, float linesz) +void cmesh_draw_wire(const struct cmesh *cm, float linesz) { int cur_sdr, nfaces; if((cur_sdr = pre_draw(cm)) == -1) { return; } - update_wire_ibo(cm); + update_wire_ibo((struct cmesh*)cm); nfaces = cmesh_poly_count(cm); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cm->wire_ibo); @@ -1228,7 +1227,7 @@ void cmesh_draw_wire(struct cmesh *cm, float linesz) post_draw(cm, cur_sdr); } -void cmesh_draw_vertices(struct cmesh *cm, float ptsz) +void cmesh_draw_vertices(const struct cmesh *cm, float ptsz) { int cur_sdr; if((cur_sdr = pre_draw(cm)) == -1) { @@ -1243,7 +1242,7 @@ void cmesh_draw_vertices(struct cmesh *cm, float ptsz) post_draw(cm, cur_sdr); } -void cmesh_draw_normals(struct cmesh *cm, float len) +void cmesh_draw_normals(const struct cmesh *cm, float len) { #ifndef GL_ES_VERSION_2_0 int i, cur_sdr, vert_nelem, norm_nelem; @@ -1287,7 +1286,7 @@ void cmesh_draw_normals(struct cmesh *cm, float len) #endif /* GL_ES_VERSION_2_0 */ } -void cmesh_draw_tangents(struct cmesh *cm, float len) +void cmesh_draw_tangents(const struct cmesh *cm, float len) { #ifndef GL_ES_VERSION_2_0 int i, cur_sdr, vert_nelem, tang_nelem; @@ -1432,10 +1431,10 @@ static void calc_aabb(struct cmesh *cm) cm->aabb_valid = 1; } -void cmesh_aabbox(struct cmesh *cm, cgm_vec3 *vmin, cgm_vec3 *vmax) +void cmesh_aabbox(const struct cmesh *cm, cgm_vec3 *vmin, cgm_vec3 *vmax) { if(!cm->aabb_valid) { - calc_aabb(cm); + calc_aabb((struct cmesh*)cm); } *vmin = cm->aabb_min; *vmax = cm->aabb_max; @@ -1475,13 +1474,13 @@ static void calc_bsph(struct cmesh *cm) cm->bsph_valid = 1; } -float cmesh_bsphere(struct cmesh *cm, cgm_vec3 *center, float *rad) +float cmesh_bsphere(const struct cmesh *cm, cgm_vec3 *center, float *rad) { if(!cm->bsph_valid) { - calc_bsph(cm); + calc_bsph((struct cmesh*)cm); } - *center = cm->bsph_center; - *rad = cm->bsph_radius; + if(center) *center = cm->bsph_center; + if(rad) *rad = cm->bsph_radius; return cm->bsph_radius; } @@ -1491,7 +1490,7 @@ void cmesh_texcoord_gen_plane(struct cmesh *cm, cgm_vec3 *norm, cgm_vec3 *tang); void cmesh_texcoord_gen_box(struct cmesh *cm); void cmesh_texcoord_gen_cylinder(struct cmesh *cm); -int cmesh_dump(struct cmesh *cm, const char *fname) +int cmesh_dump(const struct cmesh *cm, const char *fname) { FILE *fp = fopen(fname, "wb"); if(fp) { @@ -1502,7 +1501,7 @@ int cmesh_dump(struct cmesh *cm, const char *fname) return -1; } -int cmesh_dump_file(struct cmesh *cm, FILE *fp) +int cmesh_dump_file(const struct cmesh *cm, FILE *fp) { static const char *label[] = { "pos", "nor", "tan", "tex", "col", "bw", "bid", "tex2" }; static const char *elemfmt[] = { 0, " %s(%g)", " %s(%g, %g)", " %s(%g, %g, %g)", " %s(%g, %g, %g, %g)", 0 }; @@ -1543,7 +1542,7 @@ int cmesh_dump_file(struct cmesh *cm, FILE *fp) return 0; } -int cmesh_dump_obj(struct cmesh *cm, const char *fname) +int cmesh_dump_obj(const struct cmesh *cm, const char *fname) { FILE *fp = fopen(fname, "wb"); if(fp) { @@ -1557,7 +1556,7 @@ int cmesh_dump_obj(struct cmesh *cm, const char *fname) #define HAS_VN 1 #define HAS_VT 2 -int cmesh_dump_obj_file(struct cmesh *cm, FILE *fp, int voffs) +int cmesh_dump_obj_file(const struct cmesh *cm, FILE *fp, int voffs) { static const char *fmtstr[] = {" %u", " %u//%u", " %u/%u", " %u/%u/%u"}; int i, j, num, nelem; diff --git a/src/cmesh.h b/src/cmesh.h index 920e39d..9c12d01 100644 --- a/src/cmesh.h +++ b/src/cmesh.h @@ -32,13 +32,13 @@ int cmesh_init(struct cmesh *cm); void cmesh_destroy(struct cmesh *cm); void cmesh_clear(struct cmesh *cm); -int cmesh_clone(struct cmesh *cmdest, struct cmesh *cmsrc); +int cmesh_clone(struct cmesh *cmdest, const struct cmesh *cmsrc); int cmesh_set_name(struct cmesh *cm, const char *name); -const char *cmesh_name(struct cmesh *cm); +const char *cmesh_name(const struct cmesh *cm); -int cmesh_has_attrib(struct cmesh *cm, int attr); -int cmesh_indexed(struct cmesh *cm); +int cmesh_has_attrib(const struct cmesh *cm, int attr); +int cmesh_indexed(const struct cmesh *cm); /* vdata can be 0, in which case only memory is allocated * returns pointer to the attribute array @@ -46,10 +46,11 @@ int cmesh_indexed(struct cmesh *cm); float *cmesh_set_attrib(struct cmesh *cm, int attr, int nelem, unsigned int num, const float *vdata); float *cmesh_attrib(struct cmesh *cm, int attr); /* invalidates VBO */ -const float *cmesh_attrib_ro(struct cmesh *cm, int attr); /* doesn't invalidate */ +const float *cmesh_attrib_ro(const struct cmesh *cm, int attr); /* doesn't invalidate */ float *cmesh_attrib_at(struct cmesh *cm, int attr, int idx); -const float *cmesh_attrib_at_ro(struct cmesh *cm, int attr, int idx); -int cmesh_attrib_count(struct cmesh *cm, int attr); +const float *cmesh_attrib_at_ro(const struct cmesh *cm, int attr, int idx); +int cmesh_attrib_count(const struct cmesh *cm, int attr); +int cmesh_attrib_nelem(const struct cmesh *cm, int attr); int cmesh_push_attrib(struct cmesh *cm, int attr, float *v); int cmesh_push_attrib1f(struct cmesh *cm, int attr, float x); int cmesh_push_attrib2f(struct cmesh *cm, int attr, float x, float y); @@ -61,26 +62,26 @@ int cmesh_push_attrib4f(struct cmesh *cm, int attr, float x, float y, float z, f */ unsigned int *cmesh_set_index(struct cmesh *cm, int num, const unsigned int *indices); unsigned int *cmesh_index(struct cmesh *cm); /* invalidates IBO */ -const unsigned int *cmesh_index_ro(struct cmesh *cm); /* doesn't invalidate */ -int cmesh_index_count(struct cmesh *cm); +const unsigned int *cmesh_index_ro(const struct cmesh *cm); /* doesn't invalidate */ +int cmesh_index_count(const struct cmesh *cm); int cmesh_push_index(struct cmesh *cm, unsigned int idx); -int cmesh_poly_count(struct cmesh *cm); +int cmesh_poly_count(const struct cmesh *cm); /* attr can be -1 to invalidate all attributes */ void cmesh_invalidate_vbo(struct cmesh *cm, int attr); void cmesh_invalidate_ibo(struct cmesh *cm); -int cmesh_append(struct cmesh *cmdest, struct cmesh *cmsrc); +int cmesh_append(struct cmesh *cmdest, const struct cmesh *cmsrc); /* submeshes */ void cmesh_clear_submeshes(struct cmesh *cm); /* a submesh is defined as a consecutive range of faces */ int cmesh_submesh(struct cmesh *cm, const char *name, int fstart, int fcount); int cmesh_remove_submesh(struct cmesh *cm, int idx); -int cmesh_find_submesh(struct cmesh *cm, const char *name); -int cmesh_submesh_count(struct cmesh *cm); -int cmesh_clone_submesh(struct cmesh *cmdest, struct cmesh *cm, int subidx); +int cmesh_find_submesh(const struct cmesh *cm, const char *name); +int cmesh_submesh_count(const struct cmesh *cm); +int cmesh_clone_submesh(struct cmesh *cmdest, const struct cmesh *cm, int subidx); /* immediate-mode style mesh construction interface */ int cmesh_vertex(struct cmesh *cm, float x, float y, float z); @@ -102,22 +103,22 @@ int cmesh_explode(struct cmesh *cm); /* undo all vertex sharing */ /* this is only guaranteed to work on an exploded mesh */ void cmesh_calc_face_normals(struct cmesh *cm); -void cmesh_draw(struct cmesh *cm); -void cmesh_draw_range(struct cmesh *cm, int start, int count); -void cmesh_draw_submesh(struct cmesh *cm, int subidx); /* XXX only for indexed meshes currently */ -void cmesh_draw_wire(struct cmesh *cm, float linesz); -void cmesh_draw_vertices(struct cmesh *cm, float ptsz); -void cmesh_draw_normals(struct cmesh *cm, float len); -void cmesh_draw_tangents(struct cmesh *cm, float len); +void cmesh_draw(const struct cmesh *cm); +void cmesh_draw_range(const struct cmesh *cm, int start, int count); +void cmesh_draw_submesh(const struct cmesh *cm, int subidx); /* XXX only for indexed meshes currently */ +void cmesh_draw_wire(const struct cmesh *cm, float linesz); +void cmesh_draw_vertices(const struct cmesh *cm, float ptsz); +void cmesh_draw_normals(const struct cmesh *cm, float len); +void cmesh_draw_tangents(const struct cmesh *cm, float len); /* get the bounding box in local space. The result will be cached and subsequent * calls will return the same box. The cache gets invalidated by any functions that * can affect the vertex data */ -void cmesh_aabbox(struct cmesh *cm, cgm_vec3 *vmin, cgm_vec3 *vmax); +void cmesh_aabbox(const struct cmesh *cm, cgm_vec3 *vmin, cgm_vec3 *vmax); /* get the bounding sphere in local space. The result will be cached ... see above */ -float cmesh_bsphere(struct cmesh *cm, cgm_vec3 *center, float *rad); +float cmesh_bsphere(const struct cmesh *cm, cgm_vec3 *center, float *rad); /* texture coordinate manipulation */ void cmesh_texcoord_apply_xform(struct cmesh *cm, float *xform); @@ -128,10 +129,10 @@ void cmesh_texcoord_gen_cylinder(struct cmesh *cm); /* FILE I/O */ int cmesh_load(struct cmesh *cm, const char *fname); -int cmesh_dump(struct cmesh *cm, const char *fname); -int cmesh_dump_file(struct cmesh *cm, FILE *fp); -int cmesh_dump_obj(struct cmesh *cm, const char *fname); -int cmesh_dump_obj_file(struct cmesh *cm, FILE *fp, int voffs); +int cmesh_dump(const struct cmesh *cm, const char *fname); +int cmesh_dump_file(const struct cmesh *cm, FILE *fp); +int cmesh_dump_obj(const struct cmesh *cm, const char *fname); +int cmesh_dump_obj_file(const struct cmesh *cm, FILE *fp, int voffs); diff --git a/src/frac.c b/src/frac.c index 93cb963..048b8a0 100644 --- a/src/frac.c +++ b/src/frac.c @@ -1,5 +1,6 @@ #include #include +#include #include "frac.h" #include "dynarr.h" @@ -31,12 +32,20 @@ void frac_destroy(struct fracture *frac) } } +static int init_cell(struct frac_cell *cell) +{ + memset(cell, 0, sizeof *cell); + if(!(cell->mesh = cmesh_alloc())) { + return -1; + } + return 0; +} + static void destroy_cell(struct frac_cell *cell) { if(!cell) return; - + free(cell->polys); cmesh_free(cell->mesh); - dynarr_free(cell->planes); } void frac_mesh(struct fracture *frac, const struct cmesh *m) @@ -49,17 +58,10 @@ int frac_point(struct fracture *frac, float x, float y, float z) struct frac_cell cell; struct frac_cell *tmp; + init_cell(&cell); cgm_vcons(&cell.pt, x, y, z); - if(!(cell.mesh = cmesh_alloc())) { - return -1; - } - if(!(cell.planes = dynarr_alloc(0, sizeof *cell.planes))) { - cmesh_free(cell.mesh); - return -1; - } if(!(tmp = dynarr_push(frac->cells, &cell))) { - cmesh_free(cell.mesh); - dynarr_free(cell.planes); + destroy_cell(&cell); return -1; } frac->cells = tmp; @@ -113,12 +115,13 @@ int frac_build_cells(struct fracture *frac) } } - return -1; + return 0; } static int build_cell(struct fracture *frac, int cellidx) { int i, j, num, clipres; + int *valid_planes; struct plane plane; struct frac_cell *cell = frac->cells + cellidx; struct poly poly, clipped, *polys, *pptr; @@ -129,7 +132,7 @@ static int build_cell(struct fracture *frac, int cellidx) } cmesh_bsphere(frac->mesh, 0, &bsize); - size *= 2; + bsize *= 2; num = dynarr_size(frac->cells); for(i=0; inum_polys--; + destroy_poly(&clipped); break; } + destroy_poly(polys + i); + polys[i] = clipped; } } @@ -178,13 +184,116 @@ static int build_cell(struct fracture *frac, int cellidx) destroy_poly(polys + i); } } - darr_free(polys); + dynarr_free(polys); + return 0; +} + +static int mesh_poly(struct poly *poly, const struct cmesh *mesh, int faceidx) +{ + int i, vsz, nsz, uvsz; + struct vertex vert, *tmpvert; + const float *varr, *narr, *uvarr; + unsigned int vidx; + + if(init_poly(poly) == -1) { + return -1; + } + + varr = cmesh_attrib_ro(mesh, CMESH_ATTR_VERTEX); + narr = cmesh_attrib_ro(mesh, CMESH_ATTR_NORMAL); + uvarr = cmesh_attrib_ro(mesh, CMESH_ATTR_TEXCOORD); + vsz = cmesh_attrib_nelem(mesh, CMESH_ATTR_VERTEX); + nsz = cmesh_attrib_nelem(mesh, CMESH_ATTR_NORMAL); + uvsz = cmesh_attrib_nelem(mesh, CMESH_ATTR_TEXCOORD); + + for(i=0; i<3; i++) { + if(cmesh_indexed(mesh)) { + vidx = cmesh_index_ro(mesh)[faceidx * 3 + i]; + } else { + vidx = faceidx * 3 + i; + } + 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(!(tmpvert = dynarr_push(poly->verts, &vert))) { + destroy_poly(poly); + return -1; + } + poly->verts = tmpvert; + } + return 0; +} + +#define ADD_VERTEX(mesh, vert) \ + do { \ + cmesh_normal(mesh, (vert)->norm.x, (vert)->norm.y, (vert)->norm.z); \ + cmesh_texcoord(mesh, (vert)->uv.x, (vert)->uv.y, 0); \ + if(cmesh_vertex(mesh, (vert)->pos.x, (vert)->pos.y, (vert)->pos.z) == -1) { \ + fprintf(stderr, "SKATA\n"); \ + abort(); \ + } \ + } while(0) + +static int build_cell_shell(struct cmesh *mesh, const struct cmesh *orig, + const struct frac_cell *cell) +{ + int i, j, k, nfaces, clipres; + struct plane plane; + struct poly poly, clipped; + struct vertex *vert; + + 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) { + destroy_poly(&clipped); + break; + } + destroy_poly(&poly); + poly = clipped; + } + + if(j < cell->num_polys) { + continue; + } + + vert = poly.verts + 1; + for(k=0; kcells); + for(i=0; icells[i].mesh, frac->mesh, frac->cells + i) == -1) { + return -1; + } + } + + return 0; } int frac_build_walls(struct fracture *frac) diff --git a/src/frac.h b/src/frac.h index 8a7e022..7b08107 100644 --- a/src/frac.h +++ b/src/frac.h @@ -9,6 +9,8 @@ struct frac_cell { cgm_vec3 pt; struct poly *polys; int num_polys; + + struct cmesh *mesh; }; struct fracture { diff --git a/src/geom.c b/src/geom.c index 4e30628..67c3c31 100644 --- a/src/geom.c +++ b/src/geom.c @@ -32,7 +32,7 @@ void poly_normal(const struct poly *poly, cgm_vec3 *n) va = poly->verts[1].pos; cgm_vsub(&va, &poly->verts[0].pos); vb = poly->verts[2].pos; - cgm_vsub(&vb, &poly->verts[2].pos); + cgm_vsub(&vb, &poly->verts[0].pos); cgm_vcross(n, &va, &vb); cgm_vnormalize(n); @@ -138,6 +138,11 @@ int init_poly(struct poly *p) return p->verts ? 0 : -1; } +void destroy_poly(struct poly *p) +{ + dynarr_free(p->verts); +} + /* returns: * 1 -> both inside * 0 -> straddling and clipped @@ -203,7 +208,7 @@ int clip_poly(struct poly *pout, const struct poly *pin, const struct plane *pla int i, nextidx, res = 0, vnum; int edges_clipped = 0; - dynarr_clear(pout->verts); + DYNARR_CLEAR(pout->verts); vnum = dynarr_size(pin->verts); for(i=0; i