]> Dogcows Code - chaz/rasterize/blobdiff - scene.c
add geometry caching and a rotation script
[chaz/rasterize] / scene.c
diff --git a/scene.c b/scene.c
index 940767d4f339b6ea44478a8821c1cd6e4f7bd49f..3e0010fa399cb4c016a365e88cfbd700785c845d 100644 (file)
--- a/scene.c
+++ b/scene.c
 #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;
This page took 0.024861 seconds and 4 git commands to generate.