aboutsummaryrefslogtreecommitdiffstats
path: root/fmd.c
diff options
context:
space:
mode:
authorTomasz Kramkowski <tk@the-tk.com>2018-04-27 20:56:00 +0100
committerTomasz Kramkowski <tk@the-tk.com>2018-04-27 20:56:00 +0100
commitbab0824608498d1079d4e9522f3014d3d538aabe (patch)
tree932f082b58fd48f85fbbdfa3f7419d2b3b03eedb /fmd.c
parent3d73622dbd5a9ddc687fe6f42268c760695d7226 (diff)
downloadfaqe-bab0824608498d1079d4e9522f3014d3d538aabe.tar.gz
faqe-bab0824608498d1079d4e9522f3014d3d538aabe.tar.xz
faqe-bab0824608498d1079d4e9522f3014d3d538aabe.zip
Implement basic model loading of FMD format.
The FMD (Faqe Model Data) format is a format designed for faqe. It stores vertex, element and material information and mesh information. This patch provides the basic implementation and use of this format. This patch also implements perspective projection, depth testing and view and model matrices. An example fmd file is provided.
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);
+}