7 VertexBuffer vertexbuffer_create()
9 return (VertexBuffer) {
10 .faces = array_create(sizeof(Face)),
14 void vertexbuffer_set_texture(VertexBuffer *buffer, GLuint texture)
16 if (buffer->current && buffer->current->texture == texture)
20 .vertices = array_create(sizeof(Vertex)),
22 array_append(&buffer->faces, &face);
23 buffer->current = &((Face *) buffer->faces.ptr)[buffer->faces.siz - 1];
26 void vertexbuffer_add_vertex(VertexBuffer *buffer, Vertex *vertex)
28 array_append(&buffer->current->vertices, vertex);
31 static int qsort_compare_faces(const void *f1, const void *f2)
33 return ((Face *) f1)->texture - ((Face *) f2)->texture;
36 static void add_mesh(Array *meshes, Array *vertices, GLuint texture)
38 if (vertices->siz > 0) {
39 Mesh *mesh = malloc(sizeof(Mesh));
40 mesh->VAO = mesh->VBO = 0;
41 // the reason the vertices are not copied and then free'd like anything else is that the vertices will be deleted after the first render anyway
42 mesh->vertices = vertices->ptr;
43 mesh->vertices_count = vertices->siz;
44 mesh->texture = texture;
46 array_append(meshes, &mesh);
49 *vertices = array_create(sizeof(Vertex));
52 MeshObject *meshobject_create(VertexBuffer buffer, struct Scene *scene, v3f pos)
54 if (buffer.faces.siz == 0)
57 MeshObject *obj = malloc(sizeof(MeshObject));
61 obj->rot = (v3f) {0.0f, 0.0f, 0.0f};
62 obj->scale = (v3f) {1.0f, 1.0f, 1.0f};
65 meshobject_transform(obj);
67 qsort(buffer.faces.ptr, buffer.faces.siz, sizeof(Face), &qsort_compare_faces);
69 Array meshes = array_create(sizeof(Mesh *));
70 Array vertices = array_create(sizeof(Vertex));
73 for (size_t f = 0; f < buffer.faces.siz; f++) {
74 Face *face = &((Face *) buffer.faces.ptr)[f];
76 if (face->texture != texture) {
77 add_mesh(&meshes, &vertices, texture);
78 texture = face->texture;
81 for (size_t v = 0; v < face->vertices.siz; v++)
82 array_append(&vertices, &((Vertex *) face->vertices.ptr)[v]);
83 free(face->vertices.ptr);
85 add_mesh(&meshes, &vertices, texture);
86 free(buffer.faces.ptr);
88 array_copy(&meshes, (void *) &obj->meshes, &obj->meshes_count);
91 scene_add_object(scene, obj);
96 #pragma GCC diagnostic push
97 #pragma GCC diagnostic ignored "-Wpedantic"
99 void meshobject_transform(MeshObject *obj)
101 mat4x4_translate(obj->transform, obj->pos.x, obj->pos.y, obj->pos.z);
102 mat4x4_rotate(obj->transform, obj->transform, obj->rot.x, obj->rot.y, obj->rot.z, obj->angle);
103 mat4x4_scale_aniso(obj->transform, obj->transform, obj->scale.x, obj->scale.y, obj->scale.z);
106 #pragma GCC diagnostic pop
108 void meshobject_delete(MeshObject *obj)
110 for (size_t i = 0; i < obj->meshes_count; i++) {
111 Mesh *mesh = obj->meshes[i];
114 free(mesh->vertices);
116 glDeleteVertexArrays(1, &mesh->VAO);
118 glDeleteBuffers(1, &mesh->VAO);
124 static void mesh_configure(Mesh *mesh)
126 glGenVertexArrays(1, &mesh->VAO);
127 glGenBuffers(1, &mesh->VBO);
129 glBindVertexArray(mesh->VAO);
130 glBindBuffer(GL_ARRAY_BUFFER, mesh->VBO);
132 glBufferData(GL_ARRAY_BUFFER, mesh->vertices_count * sizeof(Vertex), mesh->vertices, GL_STATIC_DRAW);
135 glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(Vertex), (GLvoid *) offsetof(Vertex, x));
136 glEnableVertexAttribArray(0);
138 glVertexAttribPointer(1, 2, GL_FLOAT, false, sizeof(Vertex), (GLvoid *) offsetof(Vertex, s));
139 glEnableVertexAttribArray(1);
142 glBindBuffer(GL_ARRAY_BUFFER, 0);
143 glBindVertexArray(0);
145 free(mesh->vertices);
146 mesh->vertices = NULL;
149 void meshobject_render(MeshObject *obj, ShaderProgram *prog)
154 glUniformMatrix4fv(prog->loc_model, 1, GL_FALSE, obj->transform[0]);
156 glActiveTexture(GL_TEXTURE0);
158 for (size_t i = 0; i < obj->meshes_count; i++) {
159 Mesh *mesh = obj->meshes[i];
162 mesh_configure(mesh);
164 glBindTexture(GL_TEXTURE_2D, mesh->texture);
165 glBindVertexArray(mesh->VAO);
167 glDrawArrays(GL_TRIANGLES, 0, mesh->vertices_count);
170 glBindTexture(GL_TEXTURE_2D, 0);
171 glBindVertexArray(0);