engine

game engine on C
git clone git://git.evenfri.pw/engine.git
Log | Files | Refs | README

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 }