Created
January 12, 2018 14:22
-
-
Save kion-dgl/2b280fa2fcc26a7c406a800bb0f5c4d9 to your computer and use it in GitHub Desktop.
Short C code for exporting an embedded model from archive into an OBJ file
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 <stdint.h> | |
#include <stdbool.h> | |
struct MeshHeader { | |
uint8_t tri_count; | |
uint8_t quad_count; | |
uint8_t vertex_count; | |
uint8_t nop; | |
uint32_t tri_offset; | |
uint32_t quad_offset; | |
uint16_t texture_page; | |
uint16_t pallet_page; | |
uint32_t vertex_offset; | |
}; | |
struct Vertex { | |
int16_t x; | |
int16_t y; | |
int16_t z; | |
int16_t w; | |
}; | |
struct TextureCoord { | |
uint8_t u,v; | |
}; | |
struct Face { | |
struct TextureCoord coord[4]; | |
uint8_t indice[4]; | |
}; | |
struct Mesh { | |
struct MeshHeader header; | |
struct Vertex *vertex_list; | |
struct Face *tri_list; | |
struct Face *quad_list; | |
}; | |
struct DashMesh { | |
uint32_t vert_count; | |
uint32_t face_count; | |
float *vert_list; | |
uint16_t *face_list; | |
}; | |
void print_mesh_header(struct MeshHeader mh); | |
int main() { | |
uint32_t i, j, k; | |
uint32_t memory_offset; | |
struct Mesh mesh; | |
struct DashMesh dash; | |
FILE *fp = fopen("ST03_00.BIN", "r"); | |
if(fp == NULL) { | |
fprintf(stderr, "Unable to open ST03_00.BIN\n"); | |
return 1; | |
} | |
// Read Memory Offset | |
fseek(fp, 0x0c, SEEK_SET); | |
fread(&memory_offset, sizeof(uint32_t), 1, fp); | |
memory_offset -= 0x800; | |
// Seek to Data | |
fseek(fp, 0x1db58, SEEK_SET); | |
fread(&mesh.header, sizeof(struct MeshHeader), 1, fp); | |
mesh.header.tri_offset -= memory_offset; | |
mesh.header.quad_offset -= memory_offset; | |
mesh.header.vertex_offset -= memory_offset; | |
// Debug file pointer position | |
printf("File Position: 0x%08lx\n", ftell(fp)); | |
print_mesh_header(mesh.header); | |
mesh.vertex_list = malloc(sizeof(struct Vertex) * mesh.header.vertex_count); | |
mesh.tri_list = malloc(sizeof(struct Face) * mesh.header.tri_count); | |
mesh.quad_list = malloc(sizeof(struct Face) * mesh.header.quad_count); | |
// Read Vertex List | |
fseek(fp, mesh.header.vertex_offset, SEEK_SET); | |
fread(mesh.vertex_list, sizeof(struct Vertex), mesh.header.vertex_count, fp); | |
fseek(fp, mesh.header.tri_offset, SEEK_SET); | |
fread(mesh.tri_list, sizeof(struct Face), mesh.header.tri_count, fp); | |
fseek(fp, mesh.header.quad_offset, SEEK_SET); | |
fread(mesh.quad_list, sizeof(struct Face), mesh.header.quad_count, fp); | |
// Close File | |
fclose(fp); | |
// Convert Mesh to DashMesh | |
dash.vert_count = 0; | |
dash.face_count = 0; | |
dash.vert_list = malloc(sizeof(float) * 5 * 1024); | |
dash.face_list = malloc(sizeof(uint16_t) * 3 * 1024); | |
// Convert Triangle List | |
uint16_t indice[4]; | |
uint16_t index; | |
float x,y,z,u,v; | |
bool found; | |
for(i = 0; i < mesh.header.tri_count; i++) { | |
for(j = 0; j < 3; j++) { | |
index = mesh.tri_list[i].indice[j]; | |
x = -1.0f * (float)mesh.vertex_list[index].x; | |
y = -1.0f * (float)mesh.vertex_list[index].y; | |
z = -1.0f * (float)mesh.vertex_list[index].z; | |
u = (float)mesh.tri_list[i].coord[j].u / 256.0f; | |
v = (float)mesh.tri_list[i].coord[j].v / 128.0f; | |
found = false; | |
for(k = 0; k < dash.vert_count; k++) { | |
if(dash.vert_list[k*5+0] != x) { | |
continue; | |
} | |
if(dash.vert_list[k*5+1] != y) { | |
continue; | |
} | |
if(dash.vert_list[k*5+2] != z) { | |
continue; | |
} | |
if(dash.vert_list[k*5+3] != u) { | |
continue; | |
} | |
if(dash.vert_list[k*5+4] != v) { | |
continue; | |
} | |
indice[j] = k; | |
found = true; | |
break; | |
} | |
if(found) { | |
continue; | |
} | |
dash.vert_list[dash.vert_count*5+0] = x; | |
dash.vert_list[dash.vert_count*5+1] = y; | |
dash.vert_list[dash.vert_count*5+2] = z; | |
dash.vert_list[dash.vert_count*5+3] = u; | |
dash.vert_list[dash.vert_count*5+4] = v; | |
indice[j] = dash.vert_count; | |
dash.vert_count++; | |
} | |
dash.face_list[dash.face_count*3+0] = indice[0]; | |
dash.face_list[dash.face_count*3+1] = indice[1]; | |
dash.face_list[dash.face_count*3+2] = indice[2]; | |
dash.face_count++; | |
} | |
for(i = 0; i < mesh.header.quad_count; i++) { | |
for(j = 0; j < 4; j++) { | |
index = mesh.quad_list[i].indice[j]; | |
x = -1.0f * (float)mesh.vertex_list[index].x; | |
y = -1.0f * (float)mesh.vertex_list[index].y; | |
z = -1.0f * (float)mesh.vertex_list[index].z; | |
u = (float)mesh.quad_list[i].coord[j].u / 256.0f; | |
v = (float)mesh.quad_list[i].coord[j].v / 128.0f; | |
found = false; | |
for(k = 0; k < dash.vert_count; k++) { | |
if(dash.vert_list[k*5+0] != x) { | |
continue; | |
} | |
if(dash.vert_list[k*5+1] != y) { | |
continue; | |
} | |
if(dash.vert_list[k*5+2] != z) { | |
continue; | |
} | |
if(dash.vert_list[k*5+3] != u) { | |
continue; | |
} | |
if(dash.vert_list[k*5+4] != v) { | |
continue; | |
} | |
indice[j] = k; | |
found = true; | |
break; | |
} | |
if(found) { | |
continue; | |
} | |
dash.vert_list[dash.vert_count*5+0] = x; | |
dash.vert_list[dash.vert_count*5+1] = y; | |
dash.vert_list[dash.vert_count*5+2] = z; | |
dash.vert_list[dash.vert_count*5+3] = u; | |
dash.vert_list[dash.vert_count*5+4] = v; | |
indice[j] = dash.vert_count; | |
dash.vert_count++; | |
} | |
dash.face_list[dash.face_count*3+0] = indice[0]; | |
dash.face_list[dash.face_count*3+1] = indice[1]; | |
dash.face_list[dash.face_count*3+2] = indice[2]; | |
dash.face_count++; | |
dash.face_list[dash.face_count*3+0] = indice[1]; | |
dash.face_list[dash.face_count*3+1] = indice[3]; | |
dash.face_list[dash.face_count*3+2] = indice[2]; | |
dash.face_count++; | |
} | |
fp = fopen("support_car.obj", "w"); | |
fprintf(fp, "mtllib support_car.mtl\n\n"); | |
for(i = 0; i < dash.vert_count; i++) { | |
fprintf(fp, "v %.02f %.02f %.02f\n", | |
dash.vert_list[i*5+0] / 100.0f, | |
dash.vert_list[i*5+1] / 100.0f, | |
dash.vert_list[i*5+2] / 100.0f | |
); | |
} | |
fprintf(fp, "\n"); | |
for(i = 0; i < dash.vert_count; i++) { | |
fprintf(fp, "vt %.02f %.02f \n", | |
dash.vert_list[i*5+3], | |
1.0f - dash.vert_list[i*5+4] | |
); | |
} | |
fprintf(fp, "\n"); | |
fprintf(fp, "usemtl material0\n\n"); | |
for(i = 0; i < dash.face_count; i++) { | |
fprintf(fp, "f %d/%d %d/%d %d/%d\n", | |
dash.face_list[i*3+0] + 1, | |
dash.face_list[i*3+0] + 1, | |
dash.face_list[i*3+1] + 1, | |
dash.face_list[i*3+1] + 1, | |
dash.face_list[i*3+2] + 1, | |
dash.face_list[i*3+2] + 1 | |
); | |
} | |
fclose(fp); | |
free(dash.vert_list); | |
free(dash.face_list); | |
free(mesh.vertex_list); | |
free(mesh.tri_list); | |
free(mesh.quad_list); | |
return 0; | |
} | |
void print_mesh_header(struct MeshHeader mh) { | |
printf("Triangle Offset: 0x%08x\n", mh.tri_offset); | |
printf("Quad Offset: 0x%08x\n", mh.quad_offset); | |
printf("Vertex Offset: 0x%08x\n", mh.vertex_offset); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment