-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhaloo3d_obj.h
More file actions
197 lines (186 loc) · 6 KB
/
haloo3d_obj.h
File metadata and controls
197 lines (186 loc) · 6 KB
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#ifndef __HALOO3D_OBJ_H
#define __HALOO3D_OBJ_H
// Objects and functions for dealing with wavefront obj files.
// The haloo3d_obj struct is often used raw in various other places
// in the library
#include "haloo3d.h"
#include <stdio.h>
#include <string.h>
// #define H3D_OBJ_MAXVERTICES 8192
// #define H3D_OBJ_MAXFACES 8192
#define H3D_OBJ_MAXLINESIZE 1024
// A vertex which is made up of indexes into the obj
typedef struct {
uint32_t verti;
uint32_t texi;
uint32_t normi;
} h3d_objvert;
typedef h3d_objvert h3d_objface[3];
// An object definition, where every face is a simple
// index into the internal structures
typedef struct {
uint32_t numvertices;
uint32_t maxvertices;
uint32_t numvtextures;
uint32_t maxvtextures;
uint32_t numfaces;
uint32_t maxfaces;
uint32_t numvnormals;
uint32_t maxvnormals;
vec4 *vertices;
vec3 *vtexture;
vec3 *vnormals;
h3d_objface *faces;
} h3d_obj;
static inline int h3d_obj_addvertex(h3d_obj *obj, const vec4 vertex) {
if(obj->numvertices >= obj->maxvertices) {
return -1;
}
int vi = obj->numvertices++;
memcpy(obj->vertices[vi], vertex, sizeof(vec4));
return vi;
}
static inline int h3d_obj_addvtexture(h3d_obj *obj, const vec3 vtexture) {
if(obj->numvtextures >= obj->maxvtextures) {
return -1;
}
int vti = obj->numvtextures++;
memcpy(obj->vtexture[vti], vtexture, sizeof(vec3));
return vti;
}
static inline int h3d_obj_addface(h3d_obj *obj, const h3d_objface face) {
if(obj->numfaces >= obj->maxfaces) {
return -1;
}
int fi = obj->numfaces++;
memcpy(&obj->faces[fi], face, sizeof(h3d_objface));
return fi;
}
// Parse a single line of wavefront obj file (though not particularly well, mind
// you). We only support v, vt, vn, f
static inline int h3d_obj_parseline(h3d_obj *obj, char *line, char *errout,
int errlen) {
char tmp[H3D_OBJ_MAXLINESIZE]; tmp[0] = 0; // valgrind complains...
// Read the first sector, we only support some of them
int scanned = sscanf(line, "%s", tmp);
if (scanned == 0) { // empty line or something
return 0;
}
char * next = line + strlen(tmp);
if (strcmp(tmp, "v") == 0) {
if (obj->numvertices >= obj->maxvertices) {
snprintf(errout, errlen, "Too many object vertices (%d)!\n",
obj->numvertices);
return 1;
}
// v can have 3 or 4 floats. We try to read 4 floats
hfloat_t *v = (hfloat_t *)(obj->vertices + obj->numvertices);
scanned = sscanf(next, "%f %f %f %f", v, v + 1, v + 2, v + 3);
if (scanned < 4) {
v[H3DW] = 1.0; // default value for w
}
obj->numvertices++;
} else if (strcmp(tmp, "vt") == 0) {
if (obj->numvtextures >= obj->maxvtextures) {
snprintf(errout, errlen, "Too many object vtexture points (%d)!\n",
obj->numvtextures);
return 2;
}
// v can have 1 to 3 floats. Read all, and it's fine if we don't get them
hfloat_t *v = (hfloat_t *)(obj->vtexture + obj->numvtextures);
scanned = sscanf(next, "%f %f %f", v, v + 1, v + 2);
if (scanned < 3) {
v[H3DZ] = 0.0; // default value for z
}
if (scanned < 2) {
v[H3DY] = 0.0; // default value for y (v)
}
obj->numvtextures++;
} else if (strcmp(tmp, "vn") == 0) {
if (obj->numvnormals >= obj->maxvnormals) {
snprintf(errout, errlen, "Too many object vnormal points (%d)!\n",
obj->numvnormals);
return 3;
}
// vn must have 3 floats
hfloat_t *v = (hfloat_t *)(obj->vnormals + obj->numvnormals);
scanned = sscanf(next, "%f %f %f", v, v + 1, v + 2);
if (scanned < 3) {
snprintf(errout, errlen, "Vertex normal %d did not have enough arguments",
obj->numvnormals);
return 4;
}
obj->numvnormals++;
} else if (strcmp(tmp, "f") == 0) {
if (obj->numfaces >= obj->maxfaces) {
snprintf(errout, errlen, "Too many object faces! (%d)\n", obj->numfaces);
return 5;
}
h3d_objvert *f = (h3d_objvert *)(obj->faces + obj->numfaces);
uint8_t err = 0;
// We must read the 3 vertex information. We'll read them one
// at a time as a string, then parse them
for (int i = 0; i < 3; i++) {
scanned = sscanf(next, "%s", tmp);
if (scanned < 1) {
// This is some kinda weird error...
snprintf(errout, errlen, "Face %d did not have enough arguments\n",
obj->numfaces);
err = 1;
break;
}
int32_t vi, ti, ni; // the three numbers we're trying to parse
vi = ti = ni = 1;
// There are only 4 formats for the face: v, v/t, v/t/n, and v//n.
// Start with the weird format first.
scanned = sscanf(tmp, "%d//%d", &vi, &ni);
if (scanned < 2) { // if we did not specifically read the weird format
scanned = sscanf(tmp, "%d/%d/%d", &vi, &ti, &ni);
if (scanned == 0) {
snprintf(errout, errlen, "Could not parse face: %s | %s\n", tmp,
line);
err = 1;
break;
}
}
// Whatever was scanned up to this point is fine... we allow 0s
if (vi < 0) {
vi += obj->numvertices;
} else {
vi -= 1;
}
if (ti < 0) {
ti += obj->numvtextures;
} else {
ti -= 1;
}
if (ni < 0) {
ni += obj->numvnormals;
} else {
ni -= 1;
}
// Check each against the lists to make sure it's not out of whatever
if (vi < 0 || vi >= (int32_t)obj->numvertices || ti < 0 ||
(ti >= (int32_t)obj->numvtextures && obj->numvtextures) || ni < 0 ||
(ni >= (int32_t)obj->numvnormals && obj->numvnormals)) {
snprintf(errout, errlen, "Invalid face index: %s | %s\n", tmp, line);
err = 1;
break;
}
// Now we can assign the values
f[i].verti = vi;
f[i].texi = ti;
f[i].normi = ni;
next = strstr(next, tmp) + strlen(tmp);
}
// Don't increase numfaces if there was an error
if (!err) {
obj->numfaces++;
} else {
return 99;
}
}
// printf("Unrecognized line: %s", line);
return 0;
}
#endif