X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Frasterize;a=blobdiff_plain;f=scene.c;fp=scene.c;h=3e0010fa399cb4c016a365e88cfbd700785c845d;hp=940767d4f339b6ea44478a8821c1cd6e4f7bd49f;hb=b0a8ea303e942930350bf85c860afc969442c7a4;hpb=c875478cdd823c7df8fdc859941bd9e5948c9315 diff --git a/scene.c b/scene.c index 940767d..3e0010f 100644 --- a/scene.c +++ b/scene.c @@ -16,7 +16,13 @@ #include "tri.h" -#if FIND_NORMALS == 2 +#if RENDER_PROGRESS +#define IF_RENDER_PROGRESS(X) X +#else +#define IF_RENDER_PROGRESS(X) +#endif + +#if PRE_NORMALS >= 2 #include "map.h" DECLARE_AND_DEFINE_MAP_TYPE3(vec_t, list_t*, vnorm, vec_compare(*a, *b)); @@ -45,7 +51,6 @@ static void _find_normals_add_triangle(map_t* m, tri_t* t) _find_normals_add_vertex(m, t->c.v, t); } - /* * Calculate an averaged normal from a list of triangles that share a common * vertex. @@ -76,7 +81,7 @@ static void _find_normals_average(const vec_t* v, list_t** l) } } -#endif // FIND_NORMALS +#endif // PRE_NORMALS /* @@ -86,36 +91,135 @@ struct _group { list_t* triangles; mat_t model; -#if RENDER_PROGRESS char* name; int count; -#define IF_RENDER_PROGRESS(X) X -#else -#define IF_RENDER_PROGRESS(X) -#endif }; typedef struct _group _group_t; + +#define _CHECK_IO(X) if ((X) <= 0) goto fail + /* - * Allocate a group by reading raw triangle coordinates from a file. + * Try to read the triangle geometry from the cache file. */ -static _group_t* _group_alloc(const char* filename) +static int _group_try_read_cache(const char* filename, list_t** l) { - FILE* file = fopen(filename, "r"); + char* cachename = mem_strcat(".", filename); + FILE* file = fopen(cachename, "rb"); if (file == NULL) { - fprintf(stderr, "Cannot read %s: %s\n", filename, strerror(errno)); - return NULL; + return 0; + } + + int count = 0; + _CHECK_IO(fread(&count, sizeof(count), 1, file)); + + float x1, y1, z1, x2, y2, z2, x3, y3, z3; + for (int i = 0; i < count; ++i) { + _CHECK_IO(fread(&x1, sizeof(float), 1, file)); + _CHECK_IO(fread(&y1, sizeof(float), 1, file)); + _CHECK_IO(fread(&z1, sizeof(float), 1, file)); + _CHECK_IO(fread(&x2, sizeof(float), 1, file)); + _CHECK_IO(fread(&y2, sizeof(float), 1, file)); + _CHECK_IO(fread(&z2, sizeof(float), 1, file)); + _CHECK_IO(fread(&x3, sizeof(float), 1, file)); + _CHECK_IO(fread(&y3, sizeof(float), 1, file)); + _CHECK_IO(fread(&z3, sizeof(float), 1, file)); + tri_t* t = tri_alloc( + vert_new2((scal_t)x1, (scal_t)y1, (scal_t)z1), + vert_new2((scal_t)x2, (scal_t)y2, (scal_t)z2), + vert_new2((scal_t)x3, (scal_t)y3, (scal_t)z3) + ); + _CHECK_IO(fread(&x1, sizeof(float), 1, file)); + _CHECK_IO(fread(&y1, sizeof(float), 1, file)); + _CHECK_IO(fread(&z1, sizeof(float), 1, file)); + _CHECK_IO(fread(&x2, sizeof(float), 1, file)); + _CHECK_IO(fread(&y2, sizeof(float), 1, file)); + _CHECK_IO(fread(&z2, sizeof(float), 1, file)); + _CHECK_IO(fread(&x3, sizeof(float), 1, file)); + _CHECK_IO(fread(&y3, sizeof(float), 1, file)); + _CHECK_IO(fread(&z3, sizeof(float), 1, file)); + t->a.n = vec_new((scal_t)x1, (scal_t)y1, (scal_t)z1); + t->b.n = vec_new((scal_t)x2, (scal_t)y2, (scal_t)z2); + t->c.n = vec_new((scal_t)x3, (scal_t)y3, (scal_t)z3); + + list_push2(l, t, mem_free); } +fail: + fclose(file); + mem_free(cachename); + + return count; +} + +/* + * Write the triangle data to the cache. + */ +static void _group_write_cache(const char* filename, int count, list_t* l) +{ + char* cachename = mem_strcat(".", filename); + FILE* file = fopen(cachename, "wb"); + if (file == NULL) { + fprintf(stderr, "Cannot write %s: %s\n", cachename, strerror(errno)); + return; + } + + _CHECK_IO(fwrite(&count, sizeof(count), 1, file)); + for (list_t* i = l; i; i = i->link) { + tri_t* t = (tri_t*)i->val; + _CHECK_IO(fwrite(&t->a.v.x, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->a.v.y, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->a.v.z, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->b.v.x, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->b.v.y, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->b.v.z, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->c.v.x, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->c.v.y, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->c.v.z, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->a.n.x, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->a.n.y, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->a.n.z, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->b.n.x, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->b.n.y, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->b.n.z, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->c.n.x, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->c.n.y, sizeof(float), 1, file)); + _CHECK_IO(fwrite(&t->c.n.z, sizeof(float), 1, file)); + } + +fail: + mem_free(cachename); +} + +#undef _CHECK_IO + + +/* + * Allocate a group by reading raw triangle coordinates from a file. + */ +static _group_t* _group_alloc(const char* filename) +{ _group_t* g = (_group_t*)mem_alloc(sizeof(_group_t)); g->triangles = NULL; g->model = MAT_IDENTITY; -#if RENDER_PROGRESS g->name = mem_strdup(filename); g->count = 0; + +#if PRE_NORMALS == 3 + int r = _group_try_read_cache(filename, &g->triangles); + if (0 < r) { + g->count = r; + return g; + } #endif -#if FIND_NORMALS == 2 + FILE* file = fopen(filename, "r"); + if (file == NULL) { + fprintf(stderr, "Cannot read %s: %s\n", filename, strerror(errno)); + return NULL; + } + +#if PRE_NORMALS >= 2 map_t* m = map_vnorm_alloc(); #endif @@ -128,21 +232,25 @@ static _group_t* _group_alloc(const char* filename) vert_new2((scal_t)x3, (scal_t)y3, (scal_t)z3) ); list_push2(&g->triangles, t, mem_free); - IF_RENDER_PROGRESS(++g->count); + ++g->count; -#if FIND_NORMALS == 1 +#if PRE_NORMALS == 1 vec_t n = vec_normalize(tri_normal(*t)); t->a.n = n; t->b.n = n; t->c.n = n; -#elif FIND_NORMALS == 2 +#elif PRE_NORMALS >= 2 _find_normals_add_triangle(m, t); #endif } -#if FIND_NORMALS == 2 +#if PRE_NORMALS >= 2 map_vnorm_call(m, _find_normals_average); rbtree_destroy(m); +#if PRE_NORMALS == 3 + list_reverse(&g->triangles); + _group_write_cache(filename, g->count, g->triangles); +#endif #endif fclose(file); @@ -161,7 +269,7 @@ static _group_t* _group_alloc(const char* filename) */ static void _group_destroy(_group_t* g) { - IF_RENDER_PROGRESS(mem_free(g->name)); + mem_free(g->name); list_destroy(g->triangles); mem_free(g); } @@ -243,7 +351,13 @@ struct scene scene_t* scene_alloc(const char* filename) { - FILE* file = fopen(filename, "r"); + FILE* file; + if (strcmp(filename, "-") == 0) { + file = stdin; + } + else { + file = fopen(filename, "r"); + } if (file == NULL) { fprintf(stderr, "Cannot read %s: %s\n", filename, strerror(errno)); return NULL;