mesh.c (3670B)
1 #include "engine.h" 2 3 Mesh_t mesh_load_obj(const char *path) { 4 FILE *f = fopen(path, "r"); 5 if (!f) { 6 printf("err: failed to open obj file: %s\n", path); 7 return (Mesh_t){0}; 8 } 9 10 Array_t positions, texcoords, final_vertices, final_indices; 11 array_init(&positions, sizeof(vec3)); 12 array_init(&texcoords, sizeof(TempVec2_t)); 13 array_init(&final_vertices, sizeof(float)); 14 array_init(&final_indices, sizeof(unsigned int)); 15 16 char line[256]; 17 while (fgets(line, sizeof(line), f)) { 18 if (line[0] == 'v' && line[1] == ' ') { 19 vec3 *v = array_push(&positions); 20 sscanf(line, "v %f %f %f", &v->x, &v->y, &v->z); 21 } else if (line[0] == 'v' && line[1] == 't') { 22 TempVec2_t *vt = array_push(&texcoords); 23 sscanf(line, "vt %f %f", &vt->x, &vt->y); 24 } else if (line[0] == 'v' && line[1] == 'n') { 25 /* normals: parsed only to skip them cleanly */ 26 float dummy[3]; 27 sscanf(line, "vn %f %f %f", &dummy[0], &dummy[1], &dummy[2]); 28 } else if (line[0] == 'f' && line[1] == ' ') { 29 int v[3] = {0}, vt[3] = {0}, vn[3] = {0}; 30 int matches = sscanf(line, "f %d/%d/%d %d/%d/%d %d/%d/%d", 31 &v[0], &vt[0], &vn[0], 32 &v[1], &vt[1], &vn[1], 33 &v[2], &vt[2], &vn[2]); 34 if (matches < 6) { 35 matches = sscanf(line, "f %d/%d %d/%d %d/%d", 36 &v[0], &vt[0], &v[1], &vt[1], &v[2], &vt[2]); 37 } 38 if (matches < 3) { 39 sscanf(line, "f %d %d %d", &v[0], &v[1], &v[2]); 40 } 41 42 for (int i = 0; i < 3; i++) { 43 int p_idx = v[i] - 1; 44 int t_idx = vt[i] - 1; 45 46 vec3 *pos = array_pop(&positions, (size_t)p_idx); 47 if (!pos) continue; 48 49 TempVec2_t uv_zero = {0.0f, 0.0f}; 50 TempVec2_t *uv = &uv_zero; 51 if (texcoords.count > 0 && t_idx >= 0) { 52 TempVec2_t *p = array_pop(&texcoords, (size_t)t_idx); 53 if (p) uv = p; 54 } 55 56 unsigned int cur_v_idx = (unsigned int)(final_vertices.count / 5); 57 58 *(float*)array_push(&final_vertices) = pos->x; 59 *(float*)array_push(&final_vertices) = pos->y; 60 *(float*)array_push(&final_vertices) = pos->z; 61 *(float*)array_push(&final_vertices) = uv->x; 62 *(float*)array_push(&final_vertices) = uv->y; 63 64 *(unsigned int*)array_push(&final_indices) = cur_v_idx; 65 } 66 } 67 } 68 fclose(f); 69 70 Mesh_t m = {0}; 71 m.vertex_count = (int)final_indices.count; 72 73 glGenVertexArrays(1, &m.vao); 74 glGenBuffers(1, &m.vbo); 75 glGenBuffers(1, &m.ebo); 76 glBindVertexArray(m.vao); 77 78 glBindBuffer(GL_ARRAY_BUFFER, m.vbo); 79 glBufferData(GL_ARRAY_BUFFER, 80 (GLsizeiptr)(final_vertices.count * sizeof(float)), 81 final_vertices.data, GL_STATIC_DRAW); 82 83 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m.ebo); 84 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 85 (GLsizeiptr)(final_indices.count * sizeof(unsigned int)), 86 final_indices.data, GL_STATIC_DRAW); 87 88 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); 89 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), 90 (void*)(3 * sizeof(float))); 91 glEnableVertexAttribArray(0); 92 glEnableVertexAttribArray(1); 93 94 glBindVertexArray(0); 95 96 printf("loaded obj: %s (indices: %d)\n", path, m.vertex_count); 97 98 array_free(&positions); 99 array_free(&texcoords); 100 array_free(&final_vertices); 101 array_free(&final_indices); 102 103 return m; 104 } 105 106 void mesh_draw(Mesh_t *mesh) { 107 glBindVertexArray(mesh->vao); 108 glDrawElements(GL_TRIANGLES, mesh->vertex_count, GL_UNSIGNED_INT, 0); 109 glBindVertexArray(0); 110 } 111 112 void mesh_destroy(Mesh_t *mesh) { 113 glDeleteVertexArrays(1, &mesh->vao); 114 glDeleteBuffers(1, &mesh->vbo); 115 glDeleteBuffers(1, &mesh->ebo); 116 }