#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));
_find_normals_add_vertex(m, t->c.v, t);
}
-
/*
* Calculate an averaged normal from a list of triangles that share a common
* vertex.
}
}
-#endif // FIND_NORMALS
+#endif // PRE_NORMALS
/*
{
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
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);
*/
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);
}
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;