From d7160d62b5d78e9191b4d61d7f491deb728cb478 Mon Sep 17 00:00:00 2001 From: quou Date: Sat, 13 Jul 2024 23:46:14 +1000 Subject: Model loading and basic lighting. --- convmesh.c | 267 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 convmesh.c (limited to 'convmesh.c') diff --git a/convmesh.c b/convmesh.c new file mode 100644 index 0000000..e559824 --- /dev/null +++ b/convmesh.c @@ -0,0 +1,267 @@ +#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; +} -- cgit v1.2.3-54-g00ecf