X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=blobdiff_plain;f=src%2Fmeshload.c;h=5abd96e3304a9763c563f51269c79be0101dde5a;hp=61cf12886f78277d410e961eb4cf31b9562b58a2;hb=d956a9d9273eebfacfda58cb3bafff017269d5dc;hpb=8001fafbf699a4048046d4393377e3ec83480b95 diff --git a/src/meshload.c b/src/meshload.c index 61cf128..5abd96e 100644 --- a/src/meshload.c +++ b/src/meshload.c @@ -1,16 +1,21 @@ #include #include #include +#include #include "mesh.h" #include "dynarr.h" #include "rbtree.h" #include "vmath.h" #include "3dgfx.h" +#include "util.h" +struct vertex_pos_color { + float x, y, z; + float r, g, b, a; +}; struct facevertex { int vidx, tidx, nidx; - int myidx; }; static char *clean_line(char *s); @@ -18,20 +23,31 @@ static char *parse_face_vert(char *ptr, struct facevertex *fv, int numv, int num static int cmp_facevert(const void *ap, const void *bp); static void free_rbnode_key(struct rbnode *n, void *cls); - +/* merge of different indices per attribute happens during face processing. + * + * A triplet of (vertex index/texcoord index/normal index) is used as the key + * to search in a balanced binary search tree for vertex buffer index assigned + * to the same triplet if it has been encountered before. That index is + * appended to the index buffer. + * + * If a particular triplet has not been encountered before, a new g3d_vertex is + * appended to the vertex buffer. The index of this new vertex is appended to + * the index buffer, and also inserted into the tree for future searches. + */ int load_mesh(struct g3d_mesh *mesh, const char *fname) { int i, line_num = 0, result = -1; int found_quad = 0; - FILE *fp; + FILE *fp = 0; char buf[256]; - vec3_t *varr = 0, *narr = 0; + struct vertex_pos_color *varr = 0; + vec3_t *narr = 0; vec2_t *tarr = 0; - struct rbtree *rbtree; + struct rbtree *rbtree = 0; if(!(fp = fopen(fname, "rb"))) { fprintf(stderr, "load_mesh: failed to open file: %s\n", fname); - return -1; + goto err; } if(!(rbtree = rb_create(cmp_facevert))) { @@ -62,11 +78,24 @@ int load_mesh(struct g3d_mesh *mesh, const char *fname) case 'v': if(isspace(line[1])) { /* vertex */ - vec3_t v; - if(sscanf(line + 2, "%f %f %f", &v.x, &v.y, &v.z) != 3) { + struct vertex_pos_color v; + int num; + + num = sscanf(line + 2, "%f %f %f %f %f %f %f", &v.x, &v.y, &v.z, &v.r, &v.g, &v.b, &v.a); + if(num < 3) { fprintf(stderr, "%s:%d: invalid vertex definition: \"%s\"\n", fname, line_num, line); goto err; } + switch(num) { + case 3: + v.r = 1.0f; + case 4: + v.g = 1.0f; + case 5: + v.b = 1.0f; + case 6: + v.a = 1.0f; + } if(!(varr = dynarr_push(varr, &v))) { fprintf(stderr, "load_mesh: failed to resize vertex buffer\n"); goto err; @@ -125,7 +154,7 @@ int load_mesh(struct g3d_mesh *mesh, const char *fname) goto err; } } else { - uint16_t idx = dynarr_size(mesh->varr); + uint16_t newidx = dynarr_size(mesh->varr); struct g3d_vertex v; struct facevertex *newfv; @@ -133,6 +162,10 @@ int load_mesh(struct g3d_mesh *mesh, const char *fname) v.y = varr[fv.vidx].y; v.z = varr[fv.vidx].z; v.w = 1.0f; + v.r = cround64(varr[fv.vidx].r * 255.0); + v.g = cround64(varr[fv.vidx].g * 255.0); + v.b = cround64(varr[fv.vidx].b * 255.0); + v.a = cround64(varr[fv.vidx].a * 255.0); if(fv.tidx >= 0) { v.u = tarr[fv.tidx].x; v.v = tarr[fv.tidx].y; @@ -148,13 +181,12 @@ int load_mesh(struct g3d_mesh *mesh, const char *fname) v.nx = v.ny = 0.0f; v.nz = 1.0f; } - v.r = v.g = v.b = v.a = 255; if(!(mesh->varr = dynarr_push(mesh->varr, &v))) { fprintf(stderr, "load_mesh: failed to resize combined vertex array\n"); goto err; } - if(!(mesh->iarr = dynarr_push(mesh->iarr, &idx))) { + if(!(mesh->iarr = dynarr_push(mesh->iarr, &newidx))) { fprintf(stderr, "load_mesh: failed to resize index array\n"); goto err; } @@ -162,13 +194,13 @@ int load_mesh(struct g3d_mesh *mesh, const char *fname) if((newfv = malloc(sizeof *newfv))) { *newfv = fv; } - if(!newfv || rb_insert(rbtree, newfv, &idx) == -1) { + if(!newfv || rb_insert(rbtree, newfv, (void*)(intptr_t)newidx) == -1) { fprintf(stderr, "load_mesh: failed to insert facevertex to the binary search tree\n"); goto err; } } } - if(i >= 3) found_quad = 1; + if(i > 3) found_quad = 1; } break; @@ -200,6 +232,46 @@ err: return result; } +int save_mesh(struct g3d_mesh *mesh, const char *fname) +{ + int i, fvcount; + FILE *fp; + + if(!(fp = fopen(fname, "wb"))) { + fprintf(stderr, "save_mesh: failed to open %s for writing\n", fname); + return -1; + } + fprintf(fp, "# Wavefront OBJ file shoved in your FACE by Mindlapse. Deal with it\n"); + + for(i=0; ivcount; i++) { + struct g3d_vertex *v = mesh->varr + i; + fprintf(fp, "v %f %f %f %f %f %f %f\n", v->x, v->y, v->z, v->r / 255.0f, v->g / 255.0f, + v->b / 255.0f, v->a / 255.0f); + } + for(i=0; ivcount; i++) { + fprintf(fp, "vn %f %f %f\n", mesh->varr[i].nx, mesh->varr[i].ny, mesh->varr[i].nz); + } + for(i=0; ivcount; i++) { + fprintf(fp, "vt %f %f\n", mesh->varr[i].u, mesh->varr[i].v); + } + + fvcount = mesh->prim; + for(i=0; iicount; i++) { + int idx = mesh->iarr[i] + 1; + + if(fvcount == mesh->prim) { + fprintf(fp, "\nf"); + fvcount = 0; + } + fprintf(fp, " %d/%d/%d", idx, idx, idx); + ++fvcount; + } + fprintf(fp, "\n"); + + fclose(fp); + return 0; +} + static char *clean_line(char *s) { char *end;