#include #include #include /* px py pz nx ny nz u v */ #define elpv 8 #define safe_malloc(p, s) \ p = malloc(s); \ if (!p) { \ fprintf( \ stderr, \ "Out of memory.\n" \ ); \ return 3; \ } typedef struct { unsigned short p, n, t; } Vert; typedef struct { int vc, pc, nc, tc; float* p, * n, * t; Vert* verts; } Model; int line_len(const char* line) { const char* c; int r = 0; for (c = line; *c && *c != '\n'; c++, r++); return r; } const char* next_line(const char* line) { const char* c; for (c = line; *c != '\n'; c++) { if (!*c) return 0; } return c + 1; } int read_model(Model* m, const char* src) { const char* line; int pc = 0, nc = 0, tc = 0, vc = 0; for (line = src; line; line = next_line(line)) { if (line_len(line) < 6) continue; if (!memcmp("vn", line, 2)) nc++; else if (!memcmp("vt", line, 2)) tc++; else if (!memcmp("v", line, 1)) pc++; else if (!memcmp("f", line, 1)) vc++; } safe_malloc(m->p, pc * 3 * sizeof *m->p); safe_malloc(m->n, nc * 3 * sizeof *m->n); safe_malloc(m->t, tc * 2 * sizeof *m->t); safe_malloc(m->verts, vc * 3 * sizeof *m->verts); pc = nc = tc = 0; m->vc = 0; for (line = src; line; line = next_line(line)) { int idx; char* end; if (!memcmp("vn", line, 2)) { idx = nc++; m->n[idx * 3 + 0] = (float)strtod(line + 3, &end); m->n[idx * 3 + 1] = (float)strtod(end, &end); m->n[idx * 3 + 2] = (float)strtod(end, &end); } else if (!memcmp("vt", line, 2)) { idx = tc++; m->t[idx * 2 + 0] = (float)strtod(line + 3, &end); m->t[idx * 2 + 1] = (float)strtod(end, &end); } else if (!memcmp("v", line, 1)) { idx = pc++; m->p[idx * 3 + 0] = (float)strtod(line + 2, &end); m->p[idx * 3 + 1] = (float)strtod(end, &end); m->p[idx * 3 + 2] = (float)strtod(end, &end); } else if (!memcmp("f", line, 1)) { idx = m->vc++; m->verts[idx].p = (int)strtol(line + 1, &end, 10) - 1; m->verts[idx].t = (int)strtol(end + 1, &end, 10) - 1; m->verts[idx].n = (int)strtol(end + 1, &end, 10) - 1; idx = m->vc++; m->verts[idx].p = (int)strtol(end + 1, &end, 10) - 1; m->verts[idx].t = (int)strtol(end + 1, &end, 10) - 1; m->verts[idx].n = (int)strtol(end + 1, &end, 10) - 1; idx = m->vc++; m->verts[idx].p = (int)strtol(end + 1, &end, 10) - 1; m->verts[idx].t = (int)strtol(end + 1, &end, 10) - 1; m->verts[idx].n = (int)strtol(end + 1, &end, 10) - 1; } } m->pc = pc; m->nc = nc; m->tc = tc; return 0; } /* int expand_model(Model* m, float** overt, int* ovc) { int i, c, o; float* v; c = m->vc; safe_malloc(v, c * elpv * sizeof *v); for (i = o = 0; i < m->vc; i++, o += elpv) { v[o + 0] = m->p[m->verts[i].p * 3 + 0]; v[o + 1] = m->p[m->verts[i].p * 3 + 1]; v[o + 2] = m->p[m->verts[i].p * 3 + 2]; v[o + 3] = m->n[m->verts[i].n * 3 + 0]; v[o + 4] = m->n[m->verts[i].n * 3 + 1]; v[o + 5] = m->n[m->verts[i].n * 3 + 2]; v[o + 6] = m->t[m->verts[i].t * 2 + 0]; v[o + 7] = m->t[m->verts[i].t * 2 + 1]; } *overt = v; *ovc = c; return 0; } void vert_cpy(float* dst, const float* src) { int i; for (i = 0; i < elpv; i++) dst[i] = src[i]; } int verts_eq(const float* a, const float* b) { int i; #define absf(v) \ ((v) < 0.0f? -(v): (v)) for (i = 0; i < elpv; i++) if (absf(a[i] - b[i]) > 0.0001f) return 0; return 1; #undef absf } int index_model( float* vert, int vc, float** overt, unsigned short** oind, int* ovc, int* oic ) { float* ivert; unsigned short* ind; int i, ic, ivc; safe_malloc(ivert, vc * elpv * sizeof *ivert); safe_malloc(ind, vc * sizeof *ind); for (i = ic = ivc = 0; i < vc; i++) { int j, idx; for (j = 0; j < ivc; j++) { if (verts_eq(&vert[i * elpv], &ivert[j * elpv])) { ind[ic++] = (unsigned short)j; goto cont; } } idx = ivc++; vert_cpy(&ivert[idx * elpv], &vert[i * elpv]); ind[ic++] = (unsigned short)idx; cont: continue; } *overt = ivert; *oind = ind; *ovc = ivc; *oic = ic; return 0; } int write_model( float* vert, unsigned short* ind, int vc, int ic, FILE* f ) { int i, c; #define write(b, s)\ if (fwrite(b, 1, s, f) != s) return 42; write(&vc, 4); write(&ic, 4); c = vc * elpv; for (i = 0; i < c; i++) { int fv = (int)(vert[i] * 512.0f); write(&fv, 4); } write(ind, ic * sizeof *ind); return 0; }*/ int write_model( Model* m, FILE* f ) { int i, c, pad[8] = { 0 }; #define write(b, s)\ if (fwrite(b, 1, s, f) != s) return 42; write(&m->vc, 4); write(&m->pc, 4); write(&m->nc, 4); write(&m->tc, 4); write(pad, 32); for (i = 0, c = m->pc * 3; i < c; i++) { int fv = (int)(m->p[i] * 512.0f); write(&fv, 4); } for (i = 0, c = m->nc * 3; i < c; i++) { int fv = (int)(m->n[i] * 512.0f); write(&fv, 4); } for (i = 0, c = m->tc * 2; i < c; i++) { int fv = (int)(m->t[i] * 512.0f); write(&fv, 4); } write(m->verts, m->vc * sizeof *m->verts); return 0; } int main(int argc, const char** argv) { FILE* infile, * outfile; char* src; Model m; int s, r; if (argc < 3) { fprintf( stderr, "Usage: %s infile outfile\n", argv[0] ); return 1; } infile = fopen(argv[1], "r"); if (!infile) { fprintf( stderr, "Can't open %s.\n", argv[1] ); return 2; } fseek(infile, 0, SEEK_END); s = ftell(infile); rewind(infile); safe_malloc(src, s + 1); s = fread(src, 1, s, infile); src[s] = 0; if ((r = read_model(&m, src))) return r; free(src); outfile = fopen(argv[2], "wb"); if (!outfile) { fprintf( stderr, "Can't open %s.\n", argv[2] ); return 2; } if ((r = write_model(&m, outfile))) return r; fclose(infile); fclose(outfile); return 0; }