summaryrefslogtreecommitdiff
path: root/convmesh.c
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2024-07-13 23:46:14 +1000
committerquou <quou@disroot.org>2024-07-13 23:46:31 +1000
commitd7160d62b5d78e9191b4d61d7f491deb728cb478 (patch)
tree0bbb087df0fa32b2e47f00d8fc602f4921eec5a7 /convmesh.c
parenta43eb70ebe7844db0a4ffece47c22ae12384781b (diff)
Model loading and basic lighting.
Diffstat (limited to 'convmesh.c')
-rw-r--r--convmesh.c267
1 files changed, 267 insertions, 0 deletions
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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* 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;
+}