Skip to content

Instantly share code, notes, and snippets.

@kion-dgl
Created January 12, 2018 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kion-dgl/2b280fa2fcc26a7c406a800bb0f5c4d9 to your computer and use it in GitHub Desktop.
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
#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