# HG changeset patch # User John Tsiombikas # Date 1322544237 -7200 # Node ID cb676ff89e69cb454ffff967c008bfcab8b39721 # Parent 4a0e9ab12ad0f8bde8517bc3482a6a0c5409b351 added missing cvec and scene files diff -r 4a0e9ab12ad0 -r cb676ff89e69 src/cvec.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cvec.c Tue Nov 29 07:23:57 2011 +0200 @@ -0,0 +1,68 @@ +#include +#include +#include +#include "cvec.h" + +struct vector { + int elem_sz; + int size, used; + char data[1]; +}; + +#define HDRSZ offsetof(struct vector, data) +#define VECTOR(p) ((struct vector*)((char*)(p) - HDRSZ)) + +void *cvec_alloc(int cnt, int esz) +{ + struct vector *vec; + + if(!(vec = malloc(HDRSZ + esz * cnt))) { + return 0; + } + vec->elem_sz = esz; + vec->size = cnt; + vec->used = cnt; + return vec->data; +} + +void cvec_free(void *cvec) +{ + free(VECTOR(cvec)); +} + +void *cvec_resize(void *cvec, int newsz) +{ + struct vector *newvec, *vec = VECTOR(cvec); + + if(!(newvec = realloc(vec, newsz * vec->elem_sz + HDRSZ))) { + return 0; + } + newvec->size = newvec->used = newsz; + return newvec->data; +} + +void *cvec_append(void *cvec, void *data) +{ + struct vector *vec = VECTOR(cvec); + + if(vec->used >= vec->size) { + int used = vec->used; + void *tmp; + + if(!(tmp = cvec_resize(cvec, vec->size ? vec->size * 2 : 1))) { + return cvec; + } + cvec = tmp; + vec = VECTOR(tmp); + vec->used = used; + } + + memcpy(vec->data + vec->used * vec->elem_sz, data, vec->elem_sz); + vec->used++; + return cvec; +} + +int cvec_size(void *cvec) +{ + return VECTOR(cvec)->used; +} diff -r 4a0e9ab12ad0 -r cb676ff89e69 src/cvec.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cvec.h Tue Nov 29 07:23:57 2011 +0200 @@ -0,0 +1,20 @@ +#ifndef CVEC_H_ +#define CVEC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void *cvec_alloc(int cnt, int esz); +void cvec_free(void *cvec); + +void *cvec_resize(void *cvec, int newsz); +void *cvec_append(void *cvec, void *data); + +int cvec_size(void *cvec); + +#ifdef __cplusplus +} +#endif + +#endif /* CVEC_H_ */ diff -r 4a0e9ab12ad0 -r cb676ff89e69 src/scene.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/scene.c Tue Nov 29 07:23:57 2011 +0200 @@ -0,0 +1,379 @@ +#include +#include +#include +#include +#include +#include "scene.h" +#include "cvec.h" +#include "mingl.h" + + +struct face { + int v[3], n[3], t[3]; +}; + +static int load_materials(struct scene *scn, const char *fname); +static int parse_face(struct face *face, char *buf); + + +/* --- scene --- */ +int scn_init(struct scene *scn) +{ + memset(scn, 0, sizeof *scn); + return 0; +} + +void scn_destroy(struct scene *scn) +{ + while(scn->matlist) { + struct material *tmp = scn->matlist; + scn->matlist = scn->matlist->next; + + mtl_destroy(tmp); + free(tmp); + } + while(scn->meshlist) { + struct mesh *tmp = scn->meshlist; + scn->meshlist = scn->meshlist->next; + + mesh_destroy(tmp); + free(tmp); + } +} + + +void scn_add_mesh(struct scene *scn, struct mesh *m) +{ + printf("adding mesh: %d faces\n", m->nface); + m->next = scn->meshlist; + scn->meshlist = m; +} + +void scn_add_material(struct scene *scn, struct material *m) +{ + printf("adding material: %s\n", m->name); + m->next = scn->matlist; + scn->matlist = m; +} + +struct material *scn_find_material(struct scene *scn, const char *name) +{ + struct material *mtl = scn->matlist; + + while(mtl) { + if(strcmp(mtl->name, name) == 0) { + break; + } + mtl = mtl->next; + } + return mtl; +} + +#define SEP " \t\n\r" +int scn_load(struct scene *scn, const char *fname) +{ + FILE *fp; + char buf[256]; + struct mesh *m; + vec3_t *varr, *vnarr; + vec2_t *vtarr; + + if(!(fp = fopen(fname, "rb"))) { + fprintf(stderr, "failed to open scene file: %s: %s\n", fname, strerror(errno)); + return -1; + } + + varr = cvec_alloc(0, sizeof *varr); + vnarr = cvec_alloc(0, sizeof *vnarr); + vtarr = cvec_alloc(0, sizeof *vtarr); + + if(!(m = malloc(sizeof *m)) || mesh_init(m) == -1) { + fprintf(stderr, "meshed up\n"); + fclose(fp); + return -1; + } + + while(fgets(buf, sizeof buf, fp)) { + char *line = buf; + char *tok, *rest, *tmp; + + while(*line && isspace(*line)) { + line++; + } + if(*line == 0 || *line == '#') { + continue; + } + + if(!(tok = strtok(line, SEP))) { + continue; + } + rest = tok + strlen(tok) + 1; + + if((tmp = strchr(rest, '\r')) || (tmp = strchr(rest, '\n'))) { + *tmp = 0; + } + + if(strcmp(tok, "mtllib") == 0) { + if(!rest) { + fprintf(stderr, "invalid mtllib directive\n"); + continue; + } + load_materials(scn, rest); + + } else if(strcmp(tok, "usemtl") == 0) { + if(rest) { + m->mtl = scn_find_material(scn, rest); + } + + } else if(strcmp(tok, "o") == 0 || strcmp(tok, "g") == 0) { + if(cvec_size(m->vert) > 0) { + scn_add_mesh(scn, m); + + if(!(m = malloc(sizeof *m)) || mesh_init(m) == -1) { + fprintf(stderr, "meshed up\n"); + fclose(fp); + return -1; + } + } + + } else if(strcmp(tok, "v") == 0) { + vec3_t v; + + if(!rest || sscanf(rest, "%f %f %f\n", &v.x, &v.y, &v.z) != 3) { + continue; + } + varr = cvec_append(varr, &v); + + } else if(strcmp(tok, "vn") == 0) { + vec3_t v; + + if(!rest || sscanf(rest, "%f %f %f\n", &v.x, &v.y, &v.z) != 3) { + continue; + } + vnarr = cvec_append(vnarr, &v); + + } else if(strcmp(tok, "vt") == 0) { + vec3_t v; + + if(!rest || sscanf(rest, "%f %f %f\n", &v.x, &v.y, &v.z) != 3) { + continue; + } + vtarr = cvec_append(vtarr, &v); + + } else if(strcmp(tok, "f") == 0) { + int i; + struct face face; + + if(!rest || parse_face(&face, rest) == -1) { + continue; + } + + for(i=0; i<3; i++) { + int vidx = face.v[i]; + int nidx = face.n[i]; + int tidx = face.t[i]; + + mesh_add_vertex(m, varr[vidx]); + if(nidx >= 0) { + mesh_add_normal(m, vnarr[nidx]); + } + if(tidx >= 0) { + mesh_add_texcoord(m, vtarr[tidx]); + } + m->nface++; + } + } + + } + fclose(fp); + + if(cvec_size(m->vert) > 0) { + scn_add_mesh(scn, m); + } + + cvec_free(varr); + cvec_free(vnarr); + cvec_free(vtarr); + + return 0; +} + +static int load_materials(struct scene *scn, const char *fname) +{ + FILE *fp; + struct material *m = 0; + char buf[256]; + + if(!(fp = fopen(fname, "r"))) { + fprintf(stderr, "failed to load material file: %s: %s\n", fname, strerror(errno)); + return -1; + } + + while(fgets(buf, sizeof buf, fp)) { + char *line = buf; + char *tok, *rest, *tmp; + + while(*line && isspace(*line)) { + line++; + } + if(*line == 0 || *line == '#') { + continue; + } + + if(!(tok = strtok(line, SEP))) { + continue; + } + rest = tok + strlen(tok) + 1; + + if((tmp = strchr(rest, '\r')) || (tmp = strchr(rest, '\n'))) { + *tmp = 0; + } + + if(strcmp(tok, "newmtl") == 0) { + if(m) { + scn_add_material(scn, m); + } + if(!(m = malloc(sizeof *m)) || mtl_init(m) == -1) { + continue; + } + mtl_set_name(m, rest); + + } else if(strcmp(tok, "Kd") == 0) { + if(sscanf(rest, "%f %f %f", &m->kd.x, &m->kd.y, &m->kd.z) != 3) { + continue; + } + } else if(strcmp(tok, "map_Kd") == 0) { + printf("ignoring texture: `%s'\n", rest); + } + } + + if(m) { + scn_add_material(scn, m); + } + + fclose(fp); + return 0; +} + +static int parse_face(struct face *face, char *buf) +{ + int i, found; + char *tok; + + for(i=0; i<3; i++) { + tok = strtok(i > 0 ? 0 : buf, SEP); + found = sscanf(tok, "%d/%d/%d", &face->v[i], &face->t[i], &face->n[i]); + + face->v[i]--; + + if(found > 1) { + face->t[i]--; + } else { + face->t[i] = -1; + } + if(found > 2) { + face->n[i]--; + } else { + face->n[i] = -1; + } + } + return 0; +} + +void scn_render(struct scene *scn) +{ + struct mesh *m = scn->meshlist; + + while(m) { + mesh_draw(m); + m = m->next; + } +} + +/* --- material --- */ +int mtl_init(struct material *mtl) +{ + memset(mtl, 0, sizeof *mtl); + return 0; +} + +void mtl_destroy(struct material *mtl) +{ + free(mtl->name); + + if(mtl->tex) { + free_texture(mtl->tex); + } +} + + +int mtl_set_name(struct material *mtl, const char *name) +{ + char *tmp; + int len = strlen(name); + + if(!(tmp = malloc(len + 1))) { + perror("failed to allocate material name"); + return -1; + } + memcpy(tmp, name, len); + tmp[len] = 0; + + free(mtl->name); + mtl->name = tmp; + return 0; +} + + +/* --- mesh --- */ +int mesh_init(struct mesh *m) +{ + memset(m, 0, sizeof *m); + + m->vert = cvec_alloc(0, sizeof *m->vert); + m->norm = cvec_alloc(0, sizeof *m->norm); + m->texcoord = cvec_alloc(0, sizeof *m->texcoord); + + if(!m->vert || !m->norm || !m->texcoord) { + return -1; + } + return 0; +} + +void mesh_destroy(struct mesh *m) +{ + cvec_free(m->vert); + cvec_free(m->norm); + cvec_free(m->texcoord); +} + +void mesh_add_vertex(struct mesh *m, vec3_t v) +{ + m->vert = cvec_append(m->vert, &v); +} + +void mesh_add_normal(struct mesh *m, vec3_t n) +{ + m->norm = cvec_append(m->norm, &n); +} + +void mesh_add_texcoord(struct mesh *m, vec2_t tc) +{ + m->texcoord = cvec_append(m->texcoord, &tc); +} + +void mesh_draw(struct mesh *m) +{ + int i, numv; + + mgl_begin(MGL_TRIANGLES); + + numv = cvec_size(m->vert); + for(i=0; inorm[i].x, m->norm[i].y, m->norm[i].z); + mgl_texcoord2f(m->texcoord[i].x, m->texcoord[i].y); + mgl_vertex3f(m->vert[i].x, m->vert[i].y, m->vert[i].z); + } + + mgl_end(); +} diff -r 4a0e9ab12ad0 -r cb676ff89e69 src/scene.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/scene.h Tue Nov 29 07:23:57 2011 +0200 @@ -0,0 +1,69 @@ +#ifndef SCENE_H_ +#define SCENE_H_ + +#include "vmath.h" +#include "texture.h" + + +struct material { + char *name; + vec3_t kd; + int kd_base; + struct texture *tex; + + struct material *next; +}; + +struct mesh { + int nface; + vec3_t *vert; + vec3_t *norm; + vec2_t *texcoord; + struct material *mtl; + + struct mesh *next; +}; + +struct scene { + struct material *matlist; + struct mesh *meshlist; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/* --- scene --- */ +int scn_init(struct scene *scn); +void scn_destroy(struct scene *scn); + +void scn_add_mesh(struct scene *scn, struct mesh *m); +void scn_add_material(struct scene *scn, struct material *m); + +struct material *scn_find_material(struct scene *scn, const char *name); + +int scn_load(struct scene *scn, const char *fname); + +void scn_render(struct scene *scn); + +/* --- material --- */ +int mtl_init(struct material *mtl); +void mtl_destroy(struct material *mtl); + +int mtl_set_name(struct material *mtl, const char *name); + +/* --- mesh --- */ +int mesh_init(struct mesh *m); +void mesh_destroy(struct mesh *m); + +void mesh_add_vertex(struct mesh *m, vec3_t v); +void mesh_add_normal(struct mesh *m, vec3_t n); +void mesh_add_texcoord(struct mesh *m, vec2_t tc); + +void mesh_draw(struct mesh *m); + +#ifdef __cplusplus +} +#endif + +#endif /* SCENE_H_ */