aboutsummaryrefslogtreecommitdiffstats
path: root/fmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'fmd.c')
-rw-r--r--fmd.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/fmd.c b/fmd.c
new file mode 100644
index 0000000..4d71f0d
--- /dev/null
+++ b/fmd.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com>
+ * SPDX-License-Identifier: MIT
+ */
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "eprintf.h"
+#include "fmd.h"
+#include "ieee754.h"
+#include "nelem.h"
+
+static const char *MAGIC = "FMD001\r\n";
+
+static void checkmagic(FILE *f)
+{
+ for (size_t i = 0; i < strlen(MAGIC); i++)
+ assert(fgetc(f) == MAGIC[i]);
+}
+
+static inline unsigned long betoul(FILE *src)
+{
+ unsigned long ret = 0;
+
+ assert(src != NULL);
+
+ for (int i = 0; i < 4; i++) {
+ int c = fgetc(src);
+ assert(c != EOF);
+ ret += (unsigned long)(c & 0xff) << (3 - i) * 8;
+ }
+
+ return ret;
+}
+
+void readfloats(float *dest, int count, FILE *src)
+{
+ assert(dest != NULL);
+ assert(src != NULL);
+
+ for (int i = 0; i < count; i++)
+ dest[i] = ieee754f(betoul(src));
+}
+
+void fmd_load(struct fmd *fmd, FILE *f)
+{
+ assert(fmd != NULL);
+ assert(f != NULL);
+
+ checkmagic(f);
+
+ fmd->nverts = betoul(f);
+ if (fmd->nverts > 0)
+ fmd->verts = emalloc(fmd->nverts * sizeof *fmd->verts);
+ else
+ fmd->verts = NULL;
+ for (int i = 0; i < fmd->nverts; i++) {
+ struct vertex *v = &fmd->verts[i];
+ readfloats(v->pos, 3, f);
+ readfloats(v->norm, 3, f);
+ readfloats(v->uv, 2, f);
+ }
+ fmd->ntris = betoul(f);
+ if (fmd->ntris > 0)
+ fmd->tris = emalloc(fmd->ntris * sizeof *fmd->tris);
+ else
+ fmd->tris = NULL;
+ for (int i = 0; i < fmd->ntris; i++)
+ for (size_t j = 0; j < NELEM(fmd->tris[j]); j++)
+ fmd->tris[i][j] = betoul(f);
+
+ fmd->nmtls = betoul(f);
+ if (fmd->nmtls > 0)
+ fmd->mtls = emalloc(fmd->nmtls * sizeof *fmd->mtls);
+ else
+ fmd->mtls = NULL;
+ for (int i = 0; i < fmd->nmtls; i++) {
+ unsigned long len = betoul(f);
+ char **m = &fmd->mtls[i];
+ size_t ret;
+
+ *m = emalloc(len + 1);
+
+ ret = fread(*m, len, 1, f);
+ assert(ret == 1);
+ *m[len] = '\0';
+ }
+
+ fmd->nmeshes = betoul(f);
+ if (fmd->nmeshes > 0)
+ fmd->meshes = emalloc(fmd->nmeshes * sizeof *fmd->meshes);
+ else
+ fmd->meshes = NULL;
+ for (int i = 0; i < fmd->nmeshes; i++) {
+ struct fmd_mesh *m = &fmd->meshes[i];
+ m->midx = betoul(f);
+ m->tidx = betoul(f);
+ m->tcnt = betoul(f);
+ }
+}
+
+void fmd_free(struct fmd *fmd)
+{
+ assert(fmd);
+
+ free(fmd->verts);
+ free(fmd->tris);
+ for (int i = 0; i < fmd->nmtls; i++)
+ free(fmd->mtls[i]);
+ free(fmd->mtls);
+ free(fmd->meshes);
+}