diff options
Diffstat (limited to 'prge_model.c')
-rw-r--r-- | prge_model.c | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/prge_model.c b/prge_model.c new file mode 100644 index 0000000..44ded76 --- /dev/null +++ b/prge_model.c @@ -0,0 +1,212 @@ +Vertex vert(V3 pos, V2 texc) +{ + Vertex v; + + v.pos = pos; + v.texc = texc; + + return v; +} + +void mesh_init_buffers(Mesh *mesh) +{ + Assert(mesh->verts); + Assert(mesh->nverts > 0); + + glGenVertexArrays(1, &mesh->vao); + glBindVertexArray(mesh->vao); + + glGenBuffers(1, &mesh->vbo); + glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo); + glBufferData(GL_ARRAY_BUFFER, mesh->nverts*sizeof(Vertex), mesh->verts, GL_STATIC_DRAW); + + if (mesh->indices && (mesh->nindices > 0)) { + glGenBuffers(1, &mesh->ebo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->ebo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh->nindices*sizeof(U32), mesh->indices, GL_STATIC_DRAW); + } + + glEnableVertexAttribArray(PRGE_SHADER_POS_LOC); + glVertexAttribPointer(PRGE_SHADER_POS_LOC, 3, GL_FLOAT, GL_FALSE, + sizeof(Vertex), OffsetOfMember(Vertex, pos)); + glEnableVertexAttribArray(PRGE_SHADER_TEXC_LOC); + glVertexAttribPointer(PRGE_SHADER_TEXC_LOC, 2, GL_FLOAT, GL_FALSE, + sizeof(Vertex), (void *)OffsetOfMember(Vertex, texc)); + glBindVertexArray(0); +} + +Mesh *mesh_init(Arena *arena, V3 origin, V3 rotate, Vertex *verts, U32 nverts, U32 *indices, U32 nindices) +{ + Mesh *mesh; + + mesh = arena_push(arena, sizeof(Mesh)); + + mesh->origin = origin; + mesh->rotate = rotate; + + mesh->verts = verts; + mesh->nverts = nverts; + + mesh->indices = indices; + mesh->nindices = nindices; + + mesh->ntextures = 0; + MemoryZeroArray(mesh->textures); + + mesh_init_buffers(mesh); + + return mesh; +} + +void mesh_add_texture(Mesh *mesh, Texture texture) +{ + Assert(mesh->ntextures+1 <= MAX_TEXTURE); + mesh->textures[mesh->ntextures++] = texture; +} + +void mesh_clear(Mesh *mesh) +{ + glBindVertexArray(mesh->vao); + glDisableVertexAttribArray(PRGE_SHADER_POS_LOC); + + glBindVertexArray(0); + glDeleteVertexArrays(1, &mesh->vao); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glDeleteBuffers(1, &mesh->vbo); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glDeleteBuffers(1, &mesh->ebo); +} + +void mesh_draw(Mesh *mesh) +{ + S32 i; + + Assert(mesh->vao); + + glBindVertexArray(mesh->vao); + + for (i = 0; i < mesh->ntextures; i++) { + glActiveTexture(GL_TEXTURE0+i); + glBindTexture(GL_TEXTURE_2D, mesh->textures[i].id); + } + + if (mesh->ebo) + glDrawElements(GL_TRIANGLES, mesh->nindices, GL_UNSIGNED_INT, 0); + else + glDrawArrays(GL_TRIANGLES, 0, mesh->nverts); + + glBindVertexArray(0); +} + +Mesh *mesh_gen_quad(Arena *arena, V3 origin, V3 rotate, F32 w, F32 h) +{ + Mesh *m; + Vertex *verts; + U32 *indices; + U32 nverts, nindices; + + nverts = 4; + verts = arena_push(arena, nverts*sizeof(Vertex)); + verts[0] = vert(v3(-w/2.0f, -h/2.0f, 0.0f), v2(0.0f, 0.0f)); + verts[1] = vert(v3(-w/2.0f, h/2.0f, 0.0f), v2(0.0f, 1.0f)); + verts[2] = vert(v3(w/2.0f, -h/2.0f, 0.0f), v2(1.0f, 0.0f)); + verts[3] = vert(v3(w/2.0f, h/2.0f, 0.0f), v2(1.0f, 1.0f)); + + nindices = 6; + indices = arena_push(arena, nindices*sizeof(U32)); + indices[0] = 0; + indices[1] = 1; + indices[2] = 3; + indices[3] = 0; + indices[4] = 2; + indices[5] = 3; + + m = mesh_init(arena, origin, rotate, verts, nverts, indices, nindices); + + return m; +} + +Mesh *mesh_gen_circle(Arena *arena, V3 origin, V3 rotate, F32 r, U32 nverts) +{ + Mesh *m; + Vertex *verts; + U32 *indices; + U32 nindices; + F32 angle, dangle; + U32 i, vi; + + if (nverts < 3) + nverts = 3; + + verts = arena_push(arena, nverts*sizeof(Vertex)); + + dangle = 2*F32_PI/(F32)nverts; + for (i = 0, angle = 0.0f; i < nverts; i++, angle += dangle) + verts[i] = vert(v3(f32cos(angle)*r, f32sin(angle)*r, 0.0f), V2_ZERO); + + nindices = nverts*3; + indices = arena_push(arena, nindices*sizeof(U32)); + for (i = 0, vi = 1; i < nindices; i += 3, vi++) { + indices[i] = 0; + indices[i+1] = vi; + indices[i+2] = (((vi+1) == (nverts)) ? 1 : (vi+1)); + } + + m = mesh_init(arena, origin, rotate, verts, nverts, indices, nindices); + + return m; +} + +Model *model_init(Arena *arena, V3 origin, V3 rotate, Mesh *meshes, U32 nmeshes) +{ + Model *res; + + res = arena_push(arena, sizeof(Model)); + + res->origin = origin; + res->rotate = rotate; + res->meshes = meshes; + res->nmeshes = nmeshes; + + return res; +} + +Model *model_load(Arena *arena, V3 origin, V3 rotate, Str8 filename) +{ + Model *res; + + res = 0; + + /* TODO(pryazha): Load models with assimp? */ + + return res; +} + +void model_draw(U32 shader, MAT4 *proj, MAT4 *view, Model *model) +{ + U32 i; + MAT4 modelmat, meshmodelmat, resmodelmat; + V3 resorigin, resrotate; + + glUseProgram(shader); + + shader_set_mat4fv(shader, PRGE_SHADER_PROJ_MAT, *proj); + shader_set_mat4fv(shader, PRGE_SHADER_VIEW_MAT, *view); + + modelmat = mat4rotate(MAT4_IDENTITY, model->rotate); + modelmat = mat4transl(modelmat, model->origin); + + for (i = 0; i < model->nmeshes; i++) { + meshmodelmat = mat4rotate(MAT4_IDENTITY, model->meshes[i].rotate); + meshmodelmat = mat4transl(meshmodelmat, model->meshes[i].origin); + + resmodelmat = mat4mul(modelmat, meshmodelmat); + + shader_set_mat4fv(shader, PRGE_SHADER_MODEL_MAT, resmodelmat); + mesh_draw(&model->meshes[i]); + } + + glUseProgram(0); +} |