9 static int update_mesh_vbo(struct mesh *m);
10 static int update_meshgroup_vbo(struct meshgroup *mg);
12 void init_mesh(struct mesh *m)
14 memset(m, 0, sizeof *m);
17 void destroy_mesh(struct mesh *m)
23 glDeleteBuffers(1, &m->vbo);
26 glDeleteBuffers(1, &m->ibo);
30 void clear_mesh(struct mesh *m)
37 m->num_verts = m->max_verts = m->num_idx = m->max_idx = 0;
39 m->bbvalid = m->vbovalid = 0;
42 void init_meshgroup(struct meshgroup *mg)
44 memset(mg, 0, sizeof *mg);
47 void destroy_meshgroup(struct meshgroup *mg)
52 glDeleteBuffers(1, &mg->vbo);
55 glDeleteBuffers(1, &mg->ibo);
59 void clear_meshgroup(struct meshgroup *mg)
65 mg->num_verts = mg->num_idx = 0;
67 mg->bbvalid = mg->vbovalid = 0;
70 void calc_mesh_bounds(struct mesh *m)
73 struct vertex *vptr = m->varr;
75 m->bb.vmin.x = m->bb.vmin.y = m->bb.vmin.z = FLT_MAX;
76 m->bb.vmax.x = m->bb.vmax.y = m->bb.vmax.z = -FLT_MAX;
78 for(i=0; i<m->num_verts; i++) {
79 if(vptr->pos.x < m->bb.vmin.x) m->bb.vmin.x = vptr->pos.x;
80 if(vptr->pos.y < m->bb.vmin.y) m->bb.vmin.y = vptr->pos.y;
81 if(vptr->pos.z < m->bb.vmin.z) m->bb.vmin.z = vptr->pos.z;
82 if(vptr->pos.x > m->bb.vmax.x) m->bb.vmax.x = vptr->pos.x;
83 if(vptr->pos.y > m->bb.vmax.y) m->bb.vmax.y = vptr->pos.y;
84 if(vptr->pos.z > m->bb.vmax.z) m->bb.vmax.z = vptr->pos.z;
91 void calc_meshgroup_bounds(struct meshgroup *mg)
96 mg->bb.vmin.x = mg->bb.vmin.y = mg->bb.vmin.z = FLT_MAX;
97 mg->bb.vmax.x = mg->bb.vmax.y = mg->bb.vmax.z = -FLT_MAX;
99 for(i=0; i<mg->num_meshes; i++) {
105 if(m->bb.vmin.x < mg->bb.vmin.x) mg->bb.vmin.x = m->bb.vmin.x;
106 if(m->bb.vmin.y < mg->bb.vmin.y) mg->bb.vmin.y = m->bb.vmin.y;
107 if(m->bb.vmin.z < mg->bb.vmin.z) mg->bb.vmin.z = m->bb.vmin.z;
108 if(m->bb.vmax.x > mg->bb.vmax.x) mg->bb.vmax.x = m->bb.vmax.x;
109 if(m->bb.vmax.y > mg->bb.vmax.y) mg->bb.vmax.y = m->bb.vmax.y;
110 if(m->bb.vmax.z > mg->bb.vmax.z) mg->bb.vmax.z = m->bb.vmax.z;
116 int add_mesh_vertex(struct mesh *m, struct vertex *v)
121 if(m->num_verts >= m->max_verts) {
122 newmax = m->max_verts ? m->max_verts * 2 : 16;
123 if(!(tmp = realloc(m->varr, newmax * sizeof *m->varr))) {
127 m->max_verts = newmax;
130 m->varr[m->num_verts++] = *v;
134 int add_mesh_index(struct mesh *m, int idx)
139 if(m->num_idx >= m->max_idx) {
140 newmax = m->max_idx ? m->max_idx * 2 : 16;
141 if(!(tmp = realloc(m->iarr, newmax * sizeof *m->iarr))) {
148 m->iarr[m->num_idx++] = idx;
152 int add_mesh_face(struct mesh *m, int va, int vb, int vc)
154 if(add_mesh_index(m, va) == -1) return -1;
155 if(add_mesh_index(m, vb) == -1) {
159 if(add_mesh_index(m, vc) == -1) {
166 int add_meshgroup_mesh(struct meshgroup *mg, struct mesh *m)
171 if(mg->num_meshes >= mg->max_meshes) {
172 newmax = mg->max_meshes ? mg->max_meshes * 2 : 16;
173 if(!(tmp = realloc(mg->meshes, newmax * sizeof *mg->meshes))) {
177 mg->max_meshes = newmax;
180 mg->meshes[mg->num_meshes++] = m;
184 void draw_mesh(struct mesh *m)
187 if(update_mesh_vbo(m) == -1) {
192 glEnableVertexAttribArray(MESH_ATTR_VERTEX);
193 glEnableVertexAttribArray(MESH_ATTR_NORMAL);
194 glEnableVertexAttribArray(MESH_ATTR_TANGENT);
195 glEnableVertexAttribArray(MESH_ATTR_TEXCOORD);
197 glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
198 glVertexAttribPointer(MESH_ATTR_VERTEX, 3, GL_FLOAT, 0, sizeof *m->varr, 0);
199 glVertexAttribPointer(MESH_ATTR_NORMAL, 3, GL_FLOAT, 0, sizeof *m->varr, (void*)offsetof(struct vertex, norm));
200 glVertexAttribPointer(MESH_ATTR_TANGENT, 3, GL_FLOAT, 0, sizeof *m->varr, (void*)offsetof(struct vertex, tang));
201 glVertexAttribPointer(MESH_ATTR_TEXCOORD, 2, GL_FLOAT, 0, sizeof *m->varr, (void*)offsetof(struct vertex, tex));
202 glBindBuffer(GL_ARRAY_BUFFER, 0);
205 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
206 glDrawElements(GL_TRIANGLES, m->num_idx, GL_UNSIGNED_INT, 0);
207 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
209 glDrawArrays(GL_TRIANGLES, 0, m->num_verts);
212 glDisableVertexAttribArray(MESH_ATTR_VERTEX);
213 glDisableVertexAttribArray(MESH_ATTR_NORMAL);
214 glDisableVertexAttribArray(MESH_ATTR_TANGENT);
215 glDisableVertexAttribArray(MESH_ATTR_TEXCOORD);
218 void draw_meshgroup(struct meshgroup *mg)
221 if(update_meshgroup_vbo(mg) == -1) {
226 glEnableVertexAttribArray(MESH_ATTR_VERTEX);
227 glEnableVertexAttribArray(MESH_ATTR_NORMAL);
228 glEnableVertexAttribArray(MESH_ATTR_TANGENT);
229 glEnableVertexAttribArray(MESH_ATTR_TEXCOORD);
231 glBindBuffer(GL_ARRAY_BUFFER, mg->vbo);
232 glVertexAttribPointer(MESH_ATTR_VERTEX, 3, GL_FLOAT, 0, sizeof(struct vertex), 0);
233 glVertexAttribPointer(MESH_ATTR_NORMAL, 3, GL_FLOAT, 0, sizeof(struct vertex), (void*)offsetof(struct vertex, norm));
234 glVertexAttribPointer(MESH_ATTR_TANGENT, 3, GL_FLOAT, 0, sizeof(struct vertex), (void*)offsetof(struct vertex, tang));
235 glVertexAttribPointer(MESH_ATTR_TEXCOORD, 2, GL_FLOAT, 0, sizeof(struct vertex), (void*)offsetof(struct vertex, tex));
236 glBindBuffer(GL_ARRAY_BUFFER, 0);
239 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mg->ibo);
240 glDrawElements(GL_TRIANGLES, mg->num_idx, GL_UNSIGNED_INT, 0);
241 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
243 glDrawArrays(GL_TRIANGLES, 0, mg->num_verts);
246 glDisableVertexAttribArray(MESH_ATTR_VERTEX);
247 glDisableVertexAttribArray(MESH_ATTR_NORMAL);
248 glDisableVertexAttribArray(MESH_ATTR_TANGENT);
249 glDisableVertexAttribArray(MESH_ATTR_TEXCOORD);
252 static int update_mesh_vbo(struct mesh *m)
254 if(m->num_verts <= 0) return -1;
257 glGenBuffers(1, &m->vbo);
259 glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
260 glBufferData(GL_ARRAY_BUFFER, m->num_verts * sizeof *m->varr, m->varr, GL_STATIC_DRAW);
261 glBindBuffer(GL_ARRAY_BUFFER, 0);
265 glGenBuffers(1, &m->ibo);
267 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
268 glBufferData(GL_ELEMENT_ARRAY_BUFFER, m->num_idx * sizeof *m->iarr,
269 m->iarr, GL_STATIC_DRAW);
270 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
275 static int update_meshgroup_vbo(struct meshgroup *mg)
278 struct vertex *varr, *vptr;
279 unsigned int *iarr = 0, *iptr;
282 mg->num_verts = mg->num_idx = 0;
284 for(i=0; i<mg->num_meshes; i++) {
285 mg->num_verts += mg->meshes[i]->num_verts;
286 mg->num_idx += mg->meshes[i]->num_idx;
289 if(mg->num_verts <= 0) return -1;
291 if(!(varr = malloc(mg->num_verts * sizeof *varr))) {
292 fprintf(stderr, "update_meshgroup_vbo: failed to allocate vertex array with %d vertices\n", mg->num_verts);
295 if(mg->num_idx > 0) {
296 if(!(iarr = malloc(mg->num_idx * sizeof *iarr))) {
297 fprintf(stderr, "update_meshgroup_vbo: failed to allocate index array with %d indices\n", mg->num_idx);
306 for(i=0; i<mg->num_meshes; i++) {
308 memcpy(vptr, m->varr, m->num_verts * sizeof *vptr);
309 vptr += m->num_verts;
312 memcpy(iptr, m->iarr, m->num_idx * sizeof *iptr);
318 glGenBuffers(1, &mg->vbo);
320 glBindBuffer(GL_ARRAY_BUFFER, mg->vbo);
321 glBufferData(GL_ARRAY_BUFFER, mg->num_verts * sizeof *varr, varr, GL_STATIC_DRAW);
322 glBindBuffer(GL_ARRAY_BUFFER, 0);
325 glGenBuffers(1, &mg->ibo);
327 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mg->ibo);
328 glBufferData(GL_ELEMENT_ARRAY_BUFFER, mg->num_idx * sizeof *iarr, iarr, GL_STATIC_DRAW);
329 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);