Skip to content

Instantly share code, notes, and snippets.

@kdrnic
Last active March 23, 2018 23:23
Show Gist options
  • Select an option

  • Save kdrnic/a659bd81cfed31c736bfdb26809120cc to your computer and use it in GitHub Desktop.

Select an option

Save kdrnic/a659bd81cfed31c736bfdb26809120cc to your computer and use it in GitHub Desktop.
#include <allegro.h>
#include <stdio.h>
#include <string.h>
typedef int face[3];
typedef char texture[64];
typedef struct mesh
{
V3D *verts;
V3D_f *verts_f;
texture *textures;
int num_verts, num_faces, num_textures;
face *faces;
} mesh;
void unpack_faces(face *uv_faces, face *pos_faces, int num_faces, V3D_f *uv_verts, V3D_f *pos_verts, face *out_faces, V3D_f **out_verts, int *num_verts_out)
{
int vuv[99999], vpos[99999];
int i, j, k;
*num_verts_out = 0;
for(i = 0; i < num_faces; i++)
{
for(j = 0; j < 3; j++)
{
for(k = 0; k < *num_verts_out; k++)
{
if(uv_faces[i][j] == vuv[k] && pos_faces[i][j] == vpos[k])
{
out_faces[i][j] = k;
break;
}
}
if(k == *num_verts_out)
{
vuv[*num_verts_out] = uv_faces[i][j];
vpos[*num_verts_out] = pos_faces[i][j];
out_faces[i][j] = *num_verts_out;
(*num_verts_out)++;
}
}
}
*out_verts = malloc(sizeof(V3D_f) * *num_verts_out);
for(k = 0; k < *num_verts_out; k++)
{
(*out_verts)[k].x = pos_verts[vpos[k]].x;
(*out_verts)[k].y = pos_verts[vpos[k]].y;
(*out_verts)[k].z = pos_verts[vpos[k]].z;
(*out_verts)[k].u = uv_verts[vuv[k]].u;
(*out_verts)[k].v = uv_verts[vuv[k]].v;
}
}
#define VPICK(a,b) ((b) == 0 ? (&a.x) : (b) == 1 ? (&a.y) : (&a.z))
#define VTPICK(a,b) ((b) == 0 ? (&a.u) : (&a.v))
mesh load_obj(const char *fn)
{
char lin[1024];
char *tok;
FILE *obj = fopen(fn, "r");
int n_v, n_vt, n_f, n_mtl;
int i;
int pass;
mesh m;
V3D_f *uv_verts, *pos_verts;
int n_faces;
face *uv_faces, *pos_faces;
for(pass = 0; pass < 2; pass++, fseek(obj, 0, SEEK_SET))
{
if(pass)
{
uv_verts = malloc(sizeof(V3D_f) * n_vt);
pos_verts = malloc(sizeof(V3D_f) * n_v);
uv_faces = malloc(sizeof(face) * n_f);
pos_faces = malloc(sizeof(face) * n_f);
m.faces = malloc(sizeof(face) * n_f);
n_faces = n_f;
m.num_faces = n_f;
m.num_textures = n_mtl;
m.textures = malloc(sizeof(texture) * n_mtl);
}
n_v = 0; n_vt = 0; n_f = 0; n_mtl = 0;
while(fgets(lin, 1024, obj))
{
int cmd = 0;
if(!strlen(lin)) continue;
for(tok = strtok(lin, " "); tok; tok = strtok(0, " "))
{
if(cmd && !pass) break;
switch(cmd)
{
case 0:
if(!strcmp(tok, "#")) goto nxl;
if(!strcmp(tok, "v"))
{
cmd = 1;
n_v++;
i = 0;
}
if(!strcmp(tok, "vt"))
{
cmd = 2;
n_vt++;
i = 0;
}
if(!strcmp(tok, "vn")) cmd = 3;
if(!strcmp(tok, "f"))
{
cmd = 4;
n_f++;
i = 0;
}
if(!strcmp(tok, "g")) cmd = 5;
if(!strcmp(tok, "usemtl"))
{
cmd = 6;
n_mtl++;
}
if(!strcmp(tok, "s")) cmd = 7;
if(!cmd) goto nxl;
break;
case 1:
*VPICK(pos_verts[n_v - 1], i) = atof(tok);
i++;
break;
case 2:
*VTPICK(uv_verts[n_vt - 1], i) = atof(tok);
i++;
break;
case 4:
*strchr(tok, '/') = 0;
pos_faces[n_f - 1][i] = atoi(tok);
tok[strlen(tok)] = '/';
uv_faces[n_f - 1][i] = atoi(strchr(tok, '/') + 1);
i++;
break;
case 6:
strcpy(m.textures[n_mtl - 1], tok);
break;
}
}
nxl:
continue;
}
}
unpack_faces(uv_faces, pos_faces, n_faces, uv_verts, pos_verts, m.faces, &m.verts_f, &m.num_verts);
free(uv_verts);
free(pos_verts);
free(uv_faces);
free(pos_faces);
return m;
}
int main()
{
allegro_init();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
install_keyboard();
install_mouse();
mesh m = load_obj("data/level.obj");
while(!key[KEY_ESC])
{
vsync();
}
return 0;
}
END_OF_MAIN()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment