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); }