diff options
Diffstat (limited to 'fmd.c')
-rw-r--r-- | fmd.c | 113 |
1 files changed, 113 insertions, 0 deletions
@@ -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); +} |