X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Frasterize;a=blobdiff_plain;f=model.c;fp=model.c;h=f02e4c709c83471a1f872b8392023afda5fc2f53;hp=c136ae940ddf2200e80bd6134e4703884c8b279e;hb=a3ba0121189f38132480b0c0c4be96df3c93900b;hpb=143da66e7f625b7f195a115b9740a748ee003534 diff --git a/model.c b/model.c index c136ae9..f02e4c7 100644 --- a/model.c +++ b/model.c @@ -7,10 +7,15 @@ #include +#include "array.h" #include "tri.h" #include "model.h" +// create an interface for a vector array +DEFINE_ARRAY_TYPE(vec); + + struct model { list_t* triangles; @@ -142,7 +147,7 @@ void model_material(model_t* m, color_t specular, scal_t shininess) #if CALC_NORMALS #include "map.h" -DECLARE_AND_DEFINE_MAP_TYPE3(vec_t, list_t*, vnorm, vec_compare(*a, *b)); +DEFINE_MAP_TYPE3(vec_t, list_t*, vnorm, vec_compare(*a, *b)); /* @@ -249,6 +254,123 @@ static int _model_read_raw(model_t* m, const char* filename) static int _model_read_obj(model_t* m, const char* filename) { + FILE* file = fopen(filename, "r"); + if (file == NULL) { + fprintf(stderr, "Cannot read %s: %s\n", filename, strerror(errno)); + return -1; + } + +#if CALC_NORMALS + map_t* nlookup = map_vnorm_alloc(); +#endif + + array_t* v = array_vec_alloc(); + array_t* vt = array_vec_alloc(); + array_t* vn = array_vec_alloc(); + + array_vec_push(v, VEC_ZERO); + array_vec_push(vt, VEC_ZERO); + array_vec_push(vn, VEC_ZERO); + + char line[4096]; + while (fgets(line, 4096, file)) { + char name[4096]; + double f1, f2, f3, f4; + int meh; + int i1, i2, i3, i4, i5, i6, i7, i8, i9; + if (sscanf(line, "v %lf %lf %lf %lf ", &f1, &f2, &f3, &f4) == 4) { + array_vec_push(v, vec_new2((scal_t)f1, (scal_t)f2, (scal_t)f3, (scal_t)f4)); + } + else if (sscanf(line, "v %lf %lf %lf ", &f1, &f2, &f3) == 3) { + array_vec_push(v, vec_new((scal_t)f1, (scal_t)f2, (scal_t)f3)); + } + else if (sscanf(line, "vt %lf %lf ", &f1, &f2) == 2) { + array_vec_push(vt, vec_new((scal_t)f1, (scal_t)f2, S(0.0))); + } + else if (sscanf(line, "vn %lf %lf %lf ", &f1, &f2, &f3) == 3) { + array_vec_push(vn, vec_new((scal_t)f1, (scal_t)f2, (scal_t)f3)); + } + else if (sscanf(line, "f %d %d %d ", &i1, &i2, &i3) == 3) { + tri_t* t = tri_alloc( + vert_new(*array_vec_index(v, i1)), + vert_new(*array_vec_index(v, i2)), + vert_new(*array_vec_index(v, i3)) + ); + list_push2(&m->triangles, t, mem_free); + ++m->count; + +#if CALC_NORMALS + _find_normals_add_triangle(nlookup, t); +#else + vec_t n = vec_normalize(tri_normal(*t)); + t->a.n = n; + t->b.n = n; + t->c.n = n; +#endif + } + else if (sscanf(line, "f %d/%d %d/%d %d/%d ", &i1, &i4, &i2, &i4, &i3, &i4) == 6) { + tri_t* t = tri_alloc( + vert_new(*array_vec_index(v, i1)), + vert_new(*array_vec_index(v, i2)), + vert_new(*array_vec_index(v, i3)) + ); + list_push2(&m->triangles, t, mem_free); + ++m->count; + +#if CALC_NORMALS + _find_normals_add_triangle(nlookup, t); +#else + vec_t n = vec_normalize(tri_normal(*t)); + t->a.n = n; + t->b.n = n; + t->c.n = n; +#endif + } + else if (sscanf(line, "f %d//%d %d//%d %d//%d ", + &i1, &i2, &i3, &i4, &i5, &i6) == 6) { + tri_t* t = tri_alloc( + vert_new(*array_vec_index(v, i1)), + vert_new(*array_vec_index(v, i3)), + vert_new(*array_vec_index(v, i5)) + ); + list_push2(&m->triangles, t, mem_free); + ++m->count; + t->a.n = *array_vec_index(vn, i2); + t->b.n = *array_vec_index(vn, i4); + t->c.n = *array_vec_index(vn, i6); + } + else if (sscanf(line, "f %d/%d/%d %d/%d/%d %d/%d/%d ", + &i1, &meh, &i2, &i3, &meh, &i4, &i5, &meh, &i6) == 9) { + tri_t* t = tri_alloc( + vert_new(*array_vec_index(v, i1)), + vert_new(*array_vec_index(v, i3)), + vert_new(*array_vec_index(v, i5)) + ); + list_push2(&m->triangles, t, mem_free); + ++m->count; + t->a.n = *array_vec_index(vn, i2); + t->b.n = *array_vec_index(vn, i4); + t->c.n = *array_vec_index(vn, i6); + } + // f 1/2 3/4 5/6 + // f 1/2/3 4/5/6 7/8/9 + } + + array_destroy(v); + array_destroy(vt); + array_destroy(vn); + +#if CALC_NORMALS + map_vnorm_call(nlookup, _find_normals_average); + rbtree_destroy(nlookup); +#endif + + fclose(file); + if (m->triangles == NULL) { + fprintf(stderr, "No triangles read from %s\n", filename); + return -1; + } + return 0; }