polyadvent

A game engine from scratch in C
git clone git://jb55.com/polyadvent
Log | Files | Refs | README

geometry.c (6522B)


      1 
      2 #include "geometry.h"
      3 #include "util.h"
      4 #include "resource.h"
      5 #include "debug.h"
      6 #include "static_resources.h"
      7 #include <assert.h>
      8 
      9 struct resource_manager geom_manager;
     10 
     11 void
     12 destroy_buffer_geometry(geometry_id *geom_id) {
     13     struct geometry *geom = get_geometry(geom_id);
     14     gpu_addr buffers[n_vertex_attrs];
     15 
     16     for (int i = 0; i < n_vertex_attrs; i++)
     17         buffers[i] = geom->vbos[i].handle;
     18     /* void glDeleteVertexArrays(GLsizei n, const GLuint *arrays); */
     19     /* glDisableVertexAttribArray(geom->buffer.vertex_buffer.handle); */
     20     /* check_gl(); */
     21     /* glDisableVertexAttribArray(geom->buffer.normal_buffer.handle); */
     22     /* check_gl(); */
     23     /* glDisableVertexAttribArray(geom->buffer.index_buffer.handle); */
     24     /* check_gl(); */
     25     check_gl();
     26     glDeleteBuffers(ARRAY_SIZE(buffers), buffers);
     27     check_gl();
     28 
     29 
     30     geom->has_vbos = 0;
     31 }
     32 
     33 void bind_geometry(struct geometry *geom, gpu_addr *vertex_attrs) {
     34     struct vbo *vbo;
     35     for (int i = 0; i < n_vertex_attrs; i++) {
     36         vbo = &geom->vbos[i];
     37         if (vbo->handle && vertex_attrs[i] != 0xFFFFFFFF) {
     38             bind_vbo(vbo, vertex_attrs[i], vbo->component_type);
     39             check_gl();
     40         }
     41     }
     42 }
     43 
     44 static void check_for_patches(struct gpu_program *program, int *type) {
     45     int has_tess_shader =
     46         get_program_shader(program, GL_TESS_EVALUATION_SHADER) != NULL;
     47 
     48     if (has_tess_shader) {
     49         glPatchParameteri(GL_PATCH_VERTICES, 3);
     50         *type = GL_PATCHES;
     51     }
     52 }
     53 
     54 
     55 void render_geometry(struct geometry *geom, gpu_addr *vertex_attrs,
     56                      struct gpu_program *program)
     57 {
     58     int type = GL_TRIANGLES;
     59     //check_for_patches(program, &type);
     60     bind_geometry(geom, vertex_attrs);
     61     if (geom->num_indices) {
     62         glDrawElements(type,
     63                        geom->num_indices, /* count */
     64                        GL_UNSIGNED_INT,    /* type */
     65                        (void*)0            /* element array buffer offset */
     66                        );
     67         check_gl();
     68     }
     69     else {
     70         /* printf("nverts %d\n", geom->num_verts); */
     71         glDrawArrays(type, 0, geom->num_verts);
     72         check_gl();
     73     }
     74 }
     75 
     76 void init_make_geometry(struct make_geometry *mkgeom) {
     77     *mkgeom = (struct make_geometry){
     78       .colors = NULL,
     79       .normals = NULL,
     80       .indices = NULL,
     81       .vertices = NULL,
     82       .tex_coords = NULL,
     83       .joint_ids = NULL,
     84       .joint_weights = NULL,
     85       .num_uv_components = 2,
     86       .num_verts = 0,
     87       .num_indices = 0,
     88     };
     89 }
     90 
     91 void init_geometry(struct geometry *geom) {
     92     geom->has_vbos = 0;
     93 
     94     for (int i = 0; i < n_vertex_attrs; i++)
     95         init_vbo(&geom->vbos[i]);
     96 
     97     geom->num_uv_components = 2;
     98 }
     99 
    100 void make_buffer_geometry(struct make_geometry *mkgeom, struct geometry *geom)
    101 {
    102     init_geometry(geom);
    103 
    104     // VBOs
    105     geom->num_uv_components = mkgeom->num_uv_components;
    106     geom->num_verts = mkgeom->num_verts;
    107     geom->num_indices = mkgeom->num_indices;
    108 
    109     assert(mkgeom->num_verts);
    110     assert(mkgeom->vertices);
    111     /* assert(geom->normals); */
    112     /* assert(geom->indices); */
    113     /* assert(geom->num_indices >= 1); */
    114 
    115     /* printf("making vertex buffer\n"); */
    116     make_float_vertex_buffer(&geom->vbos[va_position],
    117                              mkgeom->vertices,
    118                              mk_num_elements(mkgeom->num_verts),
    119                              mk_components(3)
    120                              );
    121 
    122     /* printf("making normal buffer\n"); */
    123     // cube normals
    124     if (mkgeom->normals) {
    125         make_float_vertex_buffer(&geom->vbos[va_normal],
    126                                  mkgeom->normals,
    127                                  mk_num_elements(mkgeom->num_verts),
    128                                  mk_components(3)
    129                                  );
    130     }
    131     if (mkgeom->joint_ids) {
    132         make_int_vertex_buffer(&geom->vbos[va_joint_ids],
    133                                mkgeom->joint_ids,
    134                                mk_num_elements(mkgeom->num_verts),
    135                                mk_components(3)
    136                                );
    137     }
    138 
    139     // vertex colors
    140     if (mkgeom->colors) {
    141         make_float_vertex_buffer(&geom->vbos[va_color],
    142                                  mkgeom->colors,
    143                                  mk_num_elements(mkgeom->num_verts),
    144                                  mk_components(3)
    145                                  );
    146     }
    147 
    148     if (mkgeom->tex_coords != NULL) {
    149         assert(geom->num_uv_components);
    150 
    151         make_uv_buffer(&geom->vbos[va_tex_coord],
    152                        mkgeom->tex_coords,
    153                        mk_num_elements(geom->num_verts),
    154                        mk_components(geom->num_uv_components)
    155                        );
    156     }
    157 
    158     /* printf("making index buffer\n"); */
    159     // cube indices
    160     if (mkgeom->indices)
    161         make_index_buffer(&geom->vbos[va_index],
    162                           mkgeom->indices,
    163                           mk_num_elements(mkgeom->num_indices)
    164                           );
    165 
    166     geom->has_vbos = 1;
    167 }
    168 
    169 
    170 void geometry_centroid(struct geometry *geom, float *dest) {
    171     vec3_subtract(geom->max, geom->min, dest);
    172     vec3_scale(dest, 0.5, dest);
    173 };
    174 
    175 
    176 void init_geometry_manager() {
    177     init_resource_manager(&geom_manager, sizeof(struct geometry),
    178                           DEF_NUM_GEOMETRY, MAX_GEOMETRY, "geometry",
    179                           NUM_STATIC_MODELS);
    180 
    181     for (int i = 0; i < NUM_STATIC_MODELS; i++) {
    182         init_geometry(&static_geometry()[i]);
    183     }
    184 }
    185 
    186 struct geometry *get_geometry(geometry_id *geom_id) {
    187     return get_resource(&geom_manager, geom_id);
    188 }
    189 
    190 
    191 struct geometry *new_geometry(geometry_id *geom_id) {
    192     struct geometry *geom = new_resource(&geom_manager, geom_id);
    193     /* debug("new geometry %llu\n", geom_id->uuid); */
    194     return geom;
    195 }
    196 
    197 struct geometry *get_all_geometry(u32 *count, geometry_id **ids) {
    198     return get_all_resources(&geom_manager, count, ids);
    199 }
    200 
    201 void destroy_geometry(geometry_id *geom_id)
    202 {
    203     struct geometry *geom = get_geometry(geom_id); assert(geom);
    204     struct vbo *vbo;
    205 
    206     for (int i = 0; i < n_vertex_attrs; i++) {
    207         vbo = &geom->vbos[i];
    208         if (vbo->handle)
    209             glDeleteBuffers(1, &vbo->handle);
    210     }
    211 
    212     destroy_resource(&geom_manager, geom_id);
    213 }
    214 
    215 void free_make_geometry(struct make_geometry *mkgeom)
    216 {
    217     if (mkgeom->vertices)
    218         free(mkgeom->vertices);
    219 
    220     if (mkgeom->normals)
    221         free(mkgeom->normals);
    222 
    223     if (mkgeom->colors)
    224         free(mkgeom->colors);
    225 
    226     if (mkgeom->indices)
    227         free(mkgeom->indices);
    228 }