Created
October 30, 2023 14:21
-
-
Save ancientstraits/bc4da4b6dd63e14cf0b82cb16570cad9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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