7 static char *parse_facev(char *s, int *vidx, int *nidx, int *tidx,
8 int nverts, int nnorm, int nuv);
9 static int resizearr(void **pptr, int *sz, int elemsz);
10 static char *clean_line(char *s);
12 int load_mesh(struct mesh *m, const char *fname)
17 struct g3d_vertex *vptr;
18 struct meshface *face;
19 int i, maxverts, maxfaces;
22 memset(m, 0, sizeof *m);
24 if(!(fp = fopen(fname, "rb"))) {
25 fprintf(stderr, "failed to open mesh: %s\n", fname);
29 printf("Loading mesh: %s\n", fname);
33 if(!(m->varr = malloc(maxverts * sizeof *m->varr))) {
34 fprintf(stderr, "failed to allocate vertex array\n");
40 if(!(m->faces = malloc(maxfaces * sizeof *m->faces))) {
41 fprintf(stderr, "failed to allocate mesh face array\n");
46 while(fgets(buf, sizeof buf, fp)) {
47 line = clean_line(buf);
52 if(!isspace(line[1])) continue;
53 if(sscanf(line + 2, "%f %f %f", &fx, &fy, &fz) != 3) {
56 if(m->nverts >= maxverts) {
57 if(resizearr(&m->varr, &maxverts, sizeof *m->varr) == -1) {
61 vptr = m->varr + m->nverts++;
62 vptr->x = (int32_t)(fx * 65536.0f);
63 vptr->y = (int32_t)(fy * 65536.0f);
64 vptr->z = (int32_t)(fz * 65536.0f);
66 putchar('v'); fflush(stdout);
70 if(m->nfaces >= maxfaces) {
71 if(resizearr(&m->faces, &maxfaces, sizeof *m->faces) == -1) {
77 face = m->faces + m->nfaces;
79 if(!(line = parse_facev(line, &vidx, &nidx, &tidx, m->nverts, 0, 0))) {
81 fprintf(stderr, "invalid face definition\n");
86 if(vidx < 0 || vidx >= m->nverts) {
87 fprintf(stderr, "invalid face definition, vertex out of range\n");
94 putchar('f'); fflush(stdout);
102 calc_face_normals(m);
104 for(i=0; i<m->nfaces; i++) {
107 dot = face->norm.z > 0 ? face->norm.z : 0;
108 face->color = dot >> 8;
123 static char *parse_idx(char *s, int *idx, int arrsz)
126 int val = strtol(s, &endp, 10);
127 if(endp == s) return 0;
129 if(val < 0) { /* convert negative indices */
132 *idx = val - 1; /* conv to 0-based */
137 static char *parse_facev(char *s, int *vidx, int *nidx, int *tidx,
138 int nverts, int nnorm, int nuv)
140 if(!(s = parse_idx(s, vidx, nverts))) {
143 if(*s != '/') return (!*s || isspace(*s)) ? s : 0;
145 if(*++s == '/') { /* no texcoord */
149 if(!(s = parse_idx(s, tidx, nuv))) {
152 if(*s != '/') return (!*s || isspace(*s)) ? s : 0;
156 if(!(s = parse_idx(s, nidx, nnorm))) {
159 return (!*s || isspace(*s)) ? s : 0;
162 static char *clean_line(char *s)
166 while(*s && isspace(*s)) s++;
168 if((endp = strchr(s, '#'))) {
171 endp = s + strlen(s) - 1;
173 while(endp > s && isspace(*endp)) {
179 static int resizearr(void **pptr, int *sz, int elemsz)
181 int newsz = *sz ? *sz * 2 : 16;
184 if(!(newarr = realloc(*pptr, newsz * elemsz))) {
185 fprintf(stderr, "failed to resize array to %d\n", newsz);
194 void destroy_mesh(struct mesh *m)
201 void flip_mesh_winding(struct mesh *m)
204 unsigned short buf[4];
205 struct meshface *face = m->faces;
207 for(i=0; i<m->nfaces; i++) {
208 for(j=0; j<face->prim; j++) {
209 buf[face->prim - j - 1] = face->vidx[j];
211 for(j=0; j<face->prim; j++) {
212 face->vidx[j] = buf[j];
218 int conv_nonidx_mesh(struct mesh *m)
220 struct g3d_vertex *varr, *vptr;
221 struct meshface *face;
224 nverts = m->nfaces * 3;
225 if(!(varr = malloc(nverts * sizeof *varr))) {
226 fprintf(stderr, "failed to allocate nonidx vertex array (%d)\n", nverts);
232 for(i=0; i<m->nfaces; i++) {
233 vptr[0] = m->varr[face->vidx[0]];
234 vptr[1] = m->varr[face->vidx[1]];
235 vptr[2] = m->varr[face->vidx[2]];
246 static float rsqrt(float x)
248 float xhalf = x * 0.5f;
249 int32_t i = *(int32_t*)&x;
250 i = 0x5f3759df - (i >> 1);
252 x = x * (1.5f - xhalf * x * x);
256 void calc_face_normals(struct mesh *m)
259 struct meshface *face;
260 struct g3d_vertex *va, *vb, *vc;
261 int32_t ax, ay, az, bx, by, bz, s;
265 for(i=0; i<m->nfaces; i++) {
266 va = m->varr + face->vidx[0];
267 vb = m->varr + face->vidx[1];
268 vc = m->varr + face->vidx[2];
270 ax = (vc->x - va->x) >> 8;
271 ay = (vc->y - va->y) >> 8;
272 az = (vc->z - va->z) >> 8;
273 bx = (vc->x - vb->x) >> 8;
274 by = (vc->y - vb->y) >> 8;
275 bz = (vc->z - vb->z) >> 8;
277 face->norm.x = ay * bz - az * by;
278 face->norm.y = az * bx - ax * bz;
279 face->norm.z = ax * by - ay * bx;
281 xsq = (float)face->norm.x; xsq *= xsq;
282 ysq = (float)face->norm.y; ysq *= ysq;
283 zsq = (float)face->norm.z; zsq *= zsq;
284 s = (int32_t)(rsqrt(xsq + ysq + zsq) * 256.0f);
285 face->norm.x = (face->norm.x >> 8) * s;
286 face->norm.y = (face->norm.y >> 8) * s;
287 face->norm.z = (face->norm.z >> 8) * s;
293 static struct mesh *smesh;
294 static const int32_t *smat;
296 static int zsortcmp(const void *a, const void *b)
298 unsigned short idxa, idxb;
299 struct meshface *fa, *fb;
300 struct g3d_vertex *va, *vb;
303 fa = smesh->faces + *(unsigned short*)a;
304 fb = smesh->faces + *(unsigned short*)b;
306 va = smesh->varr + fa->vidx[0];
307 vb = smesh->varr + fb->vidx[0];
309 za = (smat[8] >> 8) * (va->x >> 8) + (smat[9] >> 8) * (va->y >> 8) +
310 (smat[10] >> 8) * (va->z >> 8);
311 zb = (smat[8] >> 8) * (vb->x >> 8) + (smat[9] >> 8) * (vb->y >> 8) +
312 (smat[10] >> 8) * (vb->z >> 8);
317 void sort_mesh(struct mesh *m, const int32_t *mvmat)
322 if(!(m->zorder = malloc(m->nfaces * sizeof *m->zorder))) {
325 for(i=0; i<m->nfaces; i++) {
332 qsort(m->zorder, m->nfaces, sizeof *m->zorder, zsortcmp);
335 void draw_mesh(struct mesh *m)
338 struct meshface *face = m->faces;
339 for(i=0; i<m->nfaces; i++) {
340 g3d_color(face->color);
341 g3d_draw_indexed(face->prim, m->varr, face->vidx, face->prim);
346 void draw_mesh_zorder(struct mesh *m)
349 struct meshface *face;
351 for(i=0; i<m->nfaces; i++) {
352 face = m->faces + m->zorder[i];
353 g3d_color(face->color);
354 g3d_draw_indexed(face->prim, m->varr, face->vidx, face->prim);