1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
/*
* 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 = "FMD002\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];
unsigned long midx;
midx = betoul(f);
m->midx = midx == 0xffffffff ? -1 : (int)midx;
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);
}
|