Skip to content

Instantly share code, notes, and snippets.

@ancientstraits
Created October 30, 2023 14:21
Show Gist options
  • Save ancientstraits/bc4da4b6dd63e14cf0b82cb16570cad9 to your computer and use it in GitHub Desktop.
Save ancientstraits/bc4da4b6dd63e14cf0b82cb16570cad9 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <stdint.h>
#define ONE_LETTER_CMD(str, c) ((str[0] == c) && (str[1] == ' '))
#define TWO_LETTER_CMD(str, c0, c1) ((str[0] == c0) && (str[1] == c1) && (str[2] == ' '))
#define VCMD(str) ONE_LETTER_CMD(str, 'v')
#define FCMD(str) ONE_LETTER_CMD(str, 'f')
#define OCMD(str) ONE_LETTER_CMD(str, 'o')
#define VNCMD(str) TWO_LETTER_CMD(str, 'v', 'n')
typedef struct Vec3 {
double x, y, z;
} Vec3;
typedef struct IdxGroup {
long pos, norm;
} IdxGroup;
char* after_char(char* str, char c) {
while (*str != c) {
if (*str == '\0')
return str;
str++;
}
return str+1;
}
// returns 1 if `ig` not in `idxs`
int make_new_idx(IdxGroup* old_idxs, size_t n_old_idxs, IdxGroup ig, size_t* new_idxs, size_t new_idx_cur) {
for (size_t i = 0; i < n_old_idxs; i++) {
if ((old_idxs[i].pos == ig.pos) && (old_idxs[i].norm == ig.norm)) {
new_idxs[new_idx_cur] = i;
return 0;
}
}
new_idxs[new_idx_cur] = n_old_idxs;
old_idxs[n_old_idxs].pos = ig.pos;
old_idxs[n_old_idxs].norm = ig.norm;
return 1;
}
int main(int argc, char** argv) {
if (argc != 4) {
fprintf(stderr, "Usage: %s [OBJECT] [source/header] [FILE.obj]\n", argv[0]);
return 1;
}
FILE* fp = fopen(argv[3], "r");
if (!fp) {
fprintf(stderr, "Failed to open file '%s'n", argv[3]);
return 0;
}
char buf[256];
size_t n_verts = 0;
size_t n_norms = 0;
size_t n_tris = 0;
long obj_off = -1;
int in_obj = 0;
while (fgets(buf, 256, fp)) {
if (OCMD(buf)) {
if (strncmp(argv[1], after_char(buf, ' '), strlen(buf)) == 0) {
obj_off = ftell(fp);
in_obj = 1;
} else if (in_obj) break; // left obj
}
if (VCMD(buf)) n_verts++;
if (VNCMD(buf)) n_norms++;
if (FCMD(buf)) n_tris++;
}
if (obj_off = -1) {
fprintf(stderr, "obj '%s' not found\n", argv[1]);
}
Vec3* verts = malloc(n_verts * sizeof(Vec3));
size_t vert_cur = 0;
Vec3* norms = malloc(n_norms * sizeof(Vec3));
size_t norm_cur = 0;
IdxGroup* old_idxs = malloc(3 * n_tris * sizeof(IdxGroup));
size_t old_idx_cur = 0;
size_t* new_idxs = malloc(3 * n_tris * sizeof(size_t));
size_t new_idx_cur = 0;
fseek(fp, 0, SEEK_SET);
while (fgets(buf, 256, fp)) {
if (VCMD(buf)) {
char* iter = after_char(buf, ' ');
verts[vert_cur].x = strtod(iter, NULL);
iter = after_char(iter, ' ');
verts[vert_cur].y = strtod(iter, NULL);
iter = after_char(iter, ' ');
verts[vert_cur].z = strtod(iter, NULL);
vert_cur++;
}
if (VNCMD(buf)) {
char* iter = after_char(buf, ' ');
norms[norm_cur].x = strtod(iter, NULL);
iter = after_char(iter, ' ');
norms[norm_cur].y = strtod(iter, NULL);
iter = after_char(iter, ' ');
norms[norm_cur].z = strtod(iter, NULL);
norm_cur++;
}
if (FCMD(buf)) {
char* iter = buf;
// pos/tex/norm
for (int i = 0; i < 3; i++) {
IdxGroup ig = {};
iter = after_char(iter, ' ');
ig.pos = strtol(iter, NULL, 10) - 1;
iter = after_char(iter, '/');
iter = after_char(iter, '/');
ig.norm = strtol(iter, NULL, 10) - 1;
if (make_new_idx(old_idxs, old_idx_cur, ig, new_idxs, new_idx_cur)) {
old_idx_cur++;
}
new_idx_cur++;
}
}
if (
vert_cur == n_verts &&
norm_cur == n_norms &&
new_idx_cur == 3 * n_tris
) break;
}
fclose(fp);
// old_idx_cur is now number of old idxs
/*
for (size_t i = 0; i < (3*n_tris); i++) {
IdxGroup ig = old_idxs[new_idxs[i]];
printf("%lu: %ld %ld (%lu)\n", i, ig.pos+1, ig.norm+1, new_idxs[i]);
}
*/
// TODO this code is outputting doubles, then saying that they are floats!!!
if (strcmp(argv[2], "header") == 0) {
printf("#pragma once\n\n");
printf("extern const float vertex_array[%lu];\n", old_idx_cur*6);
printf("extern const u16 vertex_elements[%lu];\n", n_verts*3);
printf("#define vertex_element_count %lu\n", n_verts*3);
} else {
printf("#include <3ds.h>\n\n");
printf("const float vertex_array[%lu] = {\n", old_idx_cur*6);
for (size_t i = 0; i < old_idx_cur; i++) {
Vec3 p = verts[old_idxs[i].pos], n = norms[old_idxs[i].norm];
printf("\t%f, %f, %f, %f, %f, %f,\n",
(float)p.x, (float)p.y, (float)p.z,
(float)n.x, (float)n.y, (float)n.z);
}
printf("};\n\n");
printf("const u16 vertex_array[%lu] = {\n", n_verts*3);
for (size_t i = 0; i < (n_verts*3); i += 3) {
printf("\t%hu, %hu, %hu,\n",
(uint16_t)new_idxs[i],
(uint16_t)new_idxs[i+1],
(uint16_t)new_idxs[i+2]);
}
printf("};\n");
}
free(verts);
free(norms);
free(old_idxs);
free(new_idxs);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment