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)
24 glDeleteBuffers(1, &m->vbo);
27 glDeleteBuffers(1, &m->ibo);
31 void clear_mesh(struct mesh *m)
40 m->num_verts = m->max_verts = m->num_idx = m->max_idx = 0;
42 m->bbvalid = m->vbovalid = 0;
45 int copy_mesh(struct mesh *dest, struct mesh *src)
50 dest->name = strdup(src->name);
53 if(src->max_verts && !(dest->varr = malloc(src->max_verts * sizeof *dest->varr))) {
56 if(src->max_idx && !(dest->iarr = malloc(src->max_idx * sizeof *dest->iarr))) {
62 dest->num_verts = src->num_verts;
63 dest->max_verts = src->max_verts;
65 memcpy(dest->varr, src->varr, src->num_verts * sizeof *dest->varr);
68 dest->num_idx = src->num_idx;
69 dest->max_idx = src->max_idx;
71 memcpy(dest->iarr, src->iarr, src->num_idx * sizeof *dest->iarr);
77 void init_meshgroup(struct meshgroup *mg)
79 memset(mg, 0, sizeof *mg);
82 void destroy_meshgroup(struct meshgroup *mg)
87 glDeleteBuffers(1, &mg->vbo);
90 glDeleteBuffers(1, &mg->ibo);
94 void clear_meshgroup(struct meshgroup *mg)
100 mg->num_verts = mg->num_idx = 0;
102 mg->bbvalid = mg->vbovalid = 0;
105 void calc_mesh_bounds(struct mesh *m)
108 struct vertex *vptr = m->varr;
110 m->bb.vmin.x = m->bb.vmin.y = m->bb.vmin.z = FLT_MAX;
111 m->bb.vmax.x = m->bb.vmax.y = m->bb.vmax.z = -FLT_MAX;
113 for(i=0; i<m->num_verts; i++) {
114 if(vptr->pos.x < m->bb.vmin.x) m->bb.vmin.x = vptr->pos.x;
115 if(vptr->pos.y < m->bb.vmin.y) m->bb.vmin.y = vptr->pos.y;
116 if(vptr->pos.z < m->bb.vmin.z) m->bb.vmin.z = vptr->pos.z;
117 if(vptr->pos.x > m->bb.vmax.x) m->bb.vmax.x = vptr->pos.x;
118 if(vptr->pos.y > m->bb.vmax.y) m->bb.vmax.y = vptr->pos.y;
119 if(vptr->pos.z > m->bb.vmax.z) m->bb.vmax.z = vptr->pos.z;
126 void calc_meshgroup_bounds(struct meshgroup *mg)
131 mg->bb.vmin.x = mg->bb.vmin.y = mg->bb.vmin.z = FLT_MAX;
132 mg->bb.vmax.x = mg->bb.vmax.y = mg->bb.vmax.z = -FLT_MAX;
134 for(i=0; i<mg->num_meshes; i++) {
140 if(m->bb.vmin.x < mg->bb.vmin.x) mg->bb.vmin.x = m->bb.vmin.x;
141 if(m->bb.vmin.y < mg->bb.vmin.y) mg->bb.vmin.y = m->bb.vmin.y;
142 if(m->bb.vmin.z < mg->bb.vmin.z) mg->bb.vmin.z = m->bb.vmin.z;
143 if(m->bb.vmax.x > mg->bb.vmax.x) mg->bb.vmax.x = m->bb.vmax.x;
144 if(m->bb.vmax.y > mg->bb.vmax.y) mg->bb.vmax.y = m->bb.vmax.y;
145 if(m->bb.vmax.z > mg->bb.vmax.z) mg->bb.vmax.z = m->bb.vmax.z;
151 int add_mesh_vertex(struct mesh *m, struct vertex *v)
156 if(m->num_verts >= m->max_verts) {
157 newmax = m->max_verts ? m->max_verts * 2 : 16;
158 if(!(tmp = realloc(m->varr, newmax * sizeof *m->varr))) {
162 m->max_verts = newmax;
165 m->varr[m->num_verts++] = *v;
169 int add_mesh_index(struct mesh *m, int idx)
174 if(m->num_idx >= m->max_idx) {
175 newmax = m->max_idx ? m->max_idx * 2 : 16;
176 if(!(tmp = realloc(m->iarr, newmax * sizeof *m->iarr))) {
183 m->iarr[m->num_idx++] = idx;
187 int add_mesh_face(struct mesh *m, int va, int vb, int vc)
189 if(add_mesh_index(m, va) == -1) return -1;
190 if(add_mesh_index(m, vb) == -1) {
194 if(add_mesh_index(m, vc) == -1) {
201 int add_meshgroup_mesh(struct meshgroup *mg, struct mesh *m)
206 if(mg->num_meshes >= mg->max_meshes) {
207 newmax = mg->max_meshes ? mg->max_meshes * 2 : 16;
208 if(!(tmp = realloc(mg->meshes, newmax * sizeof *mg->meshes))) {
212 mg->max_meshes = newmax;
215 mg->meshes[mg->num_meshes++] = m;
219 void draw_mesh(struct mesh *m)
222 if(update_mesh_vbo(m) == -1) {
227 glEnableVertexAttribArray(MESH_ATTR_VERTEX);
228 glEnableVertexAttribArray(MESH_ATTR_NORMAL);
229 glEnableVertexAttribArray(MESH_ATTR_TANGENT);
230 glEnableVertexAttribArray(MESH_ATTR_TEXCOORD);
232 glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
233 glVertexAttribPointer(MESH_ATTR_VERTEX, 3, GL_FLOAT, 0, sizeof *m->varr, 0);
234 glVertexAttribPointer(MESH_ATTR_NORMAL, 3, GL_FLOAT, 0, sizeof *m->varr, (void*)offsetof(struct vertex, norm));
235 glVertexAttribPointer(MESH_ATTR_TANGENT, 3, GL_FLOAT, 0, sizeof *m->varr, (void*)offsetof(struct vertex, tang));
236 glVertexAttribPointer(MESH_ATTR_TEXCOORD, 2, GL_FLOAT, 0, sizeof *m->varr, (void*)offsetof(struct vertex, tex));
237 glBindBuffer(GL_ARRAY_BUFFER, 0);
240 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
241 glDrawElements(GL_TRIANGLES, m->num_idx, GL_UNSIGNED_INT, 0);
242 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
244 glDrawArrays(GL_TRIANGLES, 0, m->num_verts);
247 glDisableVertexAttribArray(MESH_ATTR_VERTEX);
248 glDisableVertexAttribArray(MESH_ATTR_NORMAL);
249 glDisableVertexAttribArray(MESH_ATTR_TANGENT);
250 glDisableVertexAttribArray(MESH_ATTR_TEXCOORD);
253 void draw_meshgroup(struct meshgroup *mg)
256 if(update_meshgroup_vbo(mg) == -1) {
261 glEnableVertexAttribArray(MESH_ATTR_VERTEX);
262 glEnableVertexAttribArray(MESH_ATTR_NORMAL);
263 glEnableVertexAttribArray(MESH_ATTR_TANGENT);
264 glEnableVertexAttribArray(MESH_ATTR_TEXCOORD);
266 glBindBuffer(GL_ARRAY_BUFFER, mg->vbo);
267 glVertexAttribPointer(MESH_ATTR_VERTEX, 3, GL_FLOAT, 0, sizeof(struct vertex), 0);
268 glVertexAttribPointer(MESH_ATTR_NORMAL, 3, GL_FLOAT, 0, sizeof(struct vertex), (void*)offsetof(struct vertex, norm));
269 glVertexAttribPointer(MESH_ATTR_TANGENT, 3, GL_FLOAT, 0, sizeof(struct vertex), (void*)offsetof(struct vertex, tang));
270 glVertexAttribPointer(MESH_ATTR_TEXCOORD, 2, GL_FLOAT, 0, sizeof(struct vertex), (void*)offsetof(struct vertex, tex));
271 glBindBuffer(GL_ARRAY_BUFFER, 0);
274 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mg->ibo);
275 glDrawElements(GL_TRIANGLES, mg->num_idx, GL_UNSIGNED_INT, 0);
276 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
278 glDrawArrays(GL_TRIANGLES, 0, mg->num_verts);
281 glDisableVertexAttribArray(MESH_ATTR_VERTEX);
282 glDisableVertexAttribArray(MESH_ATTR_NORMAL);
283 glDisableVertexAttribArray(MESH_ATTR_TANGENT);
284 glDisableVertexAttribArray(MESH_ATTR_TEXCOORD);
287 static int update_mesh_vbo(struct mesh *m)
289 if(m->num_verts <= 0) return -1;
292 glGenBuffers(1, &m->vbo);
294 glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
295 glBufferData(GL_ARRAY_BUFFER, m->num_verts * sizeof *m->varr, m->varr, GL_STATIC_DRAW);
296 glBindBuffer(GL_ARRAY_BUFFER, 0);
300 glGenBuffers(1, &m->ibo);
302 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
303 glBufferData(GL_ELEMENT_ARRAY_BUFFER, m->num_idx * sizeof *m->iarr,
304 m->iarr, GL_STATIC_DRAW);
305 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
310 static int update_meshgroup_vbo(struct meshgroup *mg)
313 struct vertex *varr, *vptr;
314 unsigned int *iarr = 0, *iptr;
317 mg->num_verts = mg->num_idx = 0;
319 for(i=0; i<mg->num_meshes; i++) {
320 mg->num_verts += mg->meshes[i]->num_verts;
321 mg->num_idx += mg->meshes[i]->num_idx;
324 if(mg->num_verts <= 0) return -1;
326 if(!(varr = malloc(mg->num_verts * sizeof *varr))) {
327 fprintf(stderr, "update_meshgroup_vbo: failed to allocate vertex array with %d vertices\n", mg->num_verts);
330 if(mg->num_idx > 0) {
331 if(!(iarr = malloc(mg->num_idx * sizeof *iarr))) {
332 fprintf(stderr, "update_meshgroup_vbo: failed to allocate index array with %d indices\n", mg->num_idx);
341 for(i=0; i<mg->num_meshes; i++) {
343 memcpy(vptr, m->varr, m->num_verts * sizeof *vptr);
344 vptr += m->num_verts;
347 for(j=0; j<m->num_idx; j++) {
348 *iptr++ = m->iarr[j] + idx0;
355 glGenBuffers(1, &mg->vbo);
357 glBindBuffer(GL_ARRAY_BUFFER, mg->vbo);
358 glBufferData(GL_ARRAY_BUFFER, mg->num_verts * sizeof *varr, varr, GL_STATIC_DRAW);
359 glBindBuffer(GL_ARRAY_BUFFER, 0);
362 glGenBuffers(1, &mg->ibo);
364 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mg->ibo);
365 glBufferData(GL_ELEMENT_ARRAY_BUFFER, mg->num_idx * sizeof *iarr, iarr, GL_STATIC_DRAW);
366 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
374 void xform_mesh(struct mesh *mesh, float *mat)
381 for(i=0; i<mesh->num_verts; i++) {
382 cgm_vmul_v3m4(&mesh->varr[i].pos, mat);
383 cgm_vmul_v3m3(&mesh->varr[i].norm, mat);
384 cgm_vmul_v3m3(&mesh->varr[i].tang, mat);