summaryrefslogtreecommitdiff
path: root/prge_model.c
diff options
context:
space:
mode:
authorpryazha <pryadeiniv@mail.ru>2025-03-19 08:46:04 +0500
committerpryazha <pryadeiniv@mail.ru>2025-03-19 08:46:04 +0500
commitb1389bad67cccd3da6815c2d5a436c177f09594b (patch)
tree393dee77b5faef3cfd6e78eda8ac07273cdcc85e /prge_model.c
parent34821e9fefb0d7cbf9e72a2457b2901edbbe03bb (diff)
window, texture, model, camera and gui (silly button)
Diffstat (limited to 'prge_model.c')
-rw-r--r--prge_model.c212
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);
+}