#include "obj.h" #include "mem_arena.h" #include "pam.h" #include "typed_list.h" #include "vec.h" #include 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; }