+
+#define _CHECK_IO(X) if ((X) <= 0) goto fail
+
+/*
+ * Try to read the triangle geometry from the cache file.
+ */
+static int _group_try_read_cache(const char* filename, list_t** l)
+{
+ char* cachename = mem_strcat(".", filename);
+ FILE* file = fopen(cachename, "rb");
+ if (file == 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
+
+