88 lines
2.3 KiB
C
88 lines
2.3 KiB
C
#include "obj.h"
|
|
#include "mem_arena.h"
|
|
#include "pam.h"
|
|
#include "typed_list.h"
|
|
#include "vec.h"
|
|
#include <stdio.h>
|
|
|
|
Model load_obj_file(Arena *arena, const char *filename, const char *diffuse, const char *tangent) {
|
|
if (!arena) {
|
|
return INVALID_MODEL;
|
|
}
|
|
|
|
FILE *fp = fopen(filename, "r");
|
|
if (!fp) {
|
|
return INVALID_MODEL;
|
|
}
|
|
|
|
Model model = (Model){
|
|
.vertices = list_create(V3f, arena),
|
|
.normals = list_create(V3f, arena),
|
|
.texture_coordinates = list_create(V2f, arena),
|
|
.triangles = list_create(Triangle, arena),
|
|
};
|
|
if (!(model.vertices) || !(model.normals) || !(model.texture_coordinates) || !(model.triangles)) {
|
|
return INVALID_MODEL;
|
|
}
|
|
|
|
char line[8192];
|
|
char identifier[8];
|
|
V3f vertex;
|
|
V3f normal;
|
|
V2f coord;
|
|
Triangle triangle;
|
|
f32 vx, vy, vz;
|
|
f32 nx, ny, nz;
|
|
f32 u, v;
|
|
u64 fp0, fp1, fp2;
|
|
u64 vn0, vn1, vn2;
|
|
u64 tx0, tx1, tx2;
|
|
while (fgets(line, 8191, fp) != NULL) {
|
|
sscanf(line, "%s", identifier);
|
|
if (strncmp(identifier, "v", 8) == 0) {
|
|
sscanf(line + 2, "%f %f %f", &vx, &vy, &vz);
|
|
vertex.x = vx;
|
|
vertex.y = vy;
|
|
vertex.z = vz;
|
|
list_append(V3f, arena, model.vertices, vertex);
|
|
} else if (strncmp(identifier, "vn", 8) == 0) {
|
|
sscanf(line + 2, "%f %f %f", &nx, &ny, &nz);
|
|
normal.x = nx;
|
|
normal.y = ny;
|
|
normal.z = nz;
|
|
list_append(V3f, arena, model.normals, normal);
|
|
} else if (strncmp(identifier, "vt", 8) == 0) {
|
|
sscanf(line + 2, "%f %f", &u, &v);
|
|
coord.u = u;
|
|
coord.v = 1.0f - v;
|
|
list_append(V2f, arena, model.texture_coordinates, coord);
|
|
} else if (strncmp(identifier, "f", 8) == 0) {
|
|
sscanf(line + 2, "%lu/%lu/%lu %lu/%lu/%lu %lu/%lu/%lu",
|
|
&fp0, &tx0, &vn0,
|
|
&fp1, &tx1, &vn1,
|
|
&fp2, &tx2, &vn2);
|
|
// OBJ indices start from 1
|
|
triangle.p0 = fp0 - 1;
|
|
triangle.p1 = fp1 - 1;
|
|
triangle.p2 = fp2 - 1;
|
|
triangle.tx0 = tx0 - 1;
|
|
triangle.tx1 = tx1 - 1;
|
|
triangle.tx2 = tx2 - 1;
|
|
triangle.n0 = vn0 - 1;
|
|
triangle.n1 = vn1 - 1;
|
|
triangle.n2 = vn2 - 1;
|
|
list_append(Triangle, arena, model.triangles, triangle);
|
|
}
|
|
}
|
|
|
|
if (diffuse) {
|
|
model.texture = load_p6_image(arena, diffuse);
|
|
}
|
|
|
|
if (tangent) {
|
|
model.normal = load_p6_image(arena, tangent);
|
|
}
|
|
|
|
return model;
|
|
}
|