6 #define GL_GLEXT_PROTOTYPES 1
11 static int update_mesh_vbo(struct mesh *m);
12 static int update_meshgroup_vbo(struct meshgroup *mg);
14 void init_mesh(struct mesh *m)
16 memset(m, 0, sizeof *m);
19 void destroy_mesh(struct mesh *m)
25 glDeleteBuffers(1, &m->vbo);
28 glDeleteBuffers(1, &m->ibo);
32 void clear_mesh(struct mesh *m)
39 m->num_verts = m->max_verts = m->num_idx = m->max_idx = 0;
41 m->bbvalid = m->vbovalid = 0;
44 void init_meshgroup(struct meshgroup *mg)
46 memset(mg, 0, sizeof *mg);
49 void destroy_meshgroup(struct meshgroup *mg)
54 glDeleteBuffers(1, &mg->vbo);
57 glDeleteBuffers(1, &mg->ibo);
61 void clear_meshgroup(struct meshgroup *mg)
67 mg->num_verts = mg->num_idx = 0;
69 mg->bbvalid = mg->vbovalid = 0;
72 void calc_mesh_bounds(struct mesh *m)
75 struct vertex *vptr = m->varr;
77 m->bb.vmin.x = m->bb.vmin.y = m->bb.vmin.z = FLT_MAX;
78 m->bb.vmax.x = m->bb.vmax.y = m->bb.vmax.z = -FLT_MAX;
80 for(i=0; i<m->num_verts; i++) {
81 if(vptr->pos.x < m->bb.vmin.x) m->bb.vmin.x = vptr->pos.x;
82 if(vptr->pos.y < m->bb.vmin.y) m->bb.vmin.y = vptr->pos.y;
83 if(vptr->pos.z < m->bb.vmin.z) m->bb.vmin.z = vptr->pos.z;
84 if(vptr->pos.x > m->bb.vmax.x) m->bb.vmax.x = vptr->pos.x;
85 if(vptr->pos.y > m->bb.vmax.y) m->bb.vmax.y = vptr->pos.y;
86 if(vptr->pos.z > m->bb.vmax.z) m->bb.vmax.z = vptr->pos.z;
93 void calc_meshgroup_bounds(struct meshgroup *mg)
98 mg->bb.vmin.x = mg->bb.vmin.y = mg->bb.vmin.z = FLT_MAX;
99 mg->bb.vmax.x = mg->bb.vmax.y = mg->bb.vmax.z = -FLT_MAX;
101 for(i=0; i<mg->num_meshes; i++) {
107 if(m->bb.vmin.x < mg->bb.vmin.x) mg->bb.vmin.x = m->bb.vmin.x;
108 if(m->bb.vmin.y < mg->bb.vmin.y) mg->bb.vmin.y = m->bb.vmin.y;
109 if(m->bb.vmin.z < mg->bb.vmin.z) mg->bb.vmin.z = m->bb.vmin.z;
110 if(m->bb.vmax.x > mg->bb.vmax.x) mg->bb.vmax.x = m->bb.vmax.x;
111 if(m->bb.vmax.y > mg->bb.vmax.y) mg->bb.vmax.y = m->bb.vmax.y;
112 if(m->bb.vmax.z > mg->bb.vmax.z) mg->bb.vmax.z = m->bb.vmax.z;
118 int add_mesh_vertex(struct mesh *m, struct vertex *v)
123 if(m->num_verts >= m->max_verts) {
124 newmax = m->max_verts ? m->max_verts * 2 : 16;
125 if(!(tmp = realloc(m->varr, newmax * sizeof *m->varr))) {
129 m->max_verts = newmax;
132 m->varr[m->num_verts++] = *v;
136 int add_mesh_index(struct mesh *m, int idx)
141 if(m->num_idx >= m->max_idx) {
142 newmax = m->max_idx ? m->max_idx * 2 : 16;
143 if(!(tmp = realloc(m->iarr, newmax * sizeof *m->iarr))) {
150 m->iarr[m->num_idx++] = idx;
154 int add_mesh_face(struct mesh *m, int va, int vb, int vc)
156 if(add_mesh_index(m, va) == -1) return -1;
157 if(add_mesh_index(m, vb) == -1) {
161 if(add_mesh_index(m, vc) == -1) {
168 int add_meshgroup_mesh(struct meshgroup *mg, struct mesh *m)
173 if(mg->num_meshes >= mg->max_meshes) {
174 newmax = mg->max_meshes ? mg->max_meshes * 2 : 16;
175 if(!(tmp = realloc(mg->meshes, newmax * sizeof *mg->meshes))) {
179 mg->max_meshes = newmax;
182 mg->meshes[mg->num_meshes++] = m;
186 void draw_mesh(struct mesh *m)
189 if(update_mesh_vbo(m) == -1) {
194 glEnableVertexAttribArray(MESH_ATTR_VERTEX);
195 glEnableVertexAttribArray(MESH_ATTR_NORMAL);
196 glEnableVertexAttribArray(MESH_ATTR_TANGENT);
197 glEnableVertexAttribArray(MESH_ATTR_TEXCOORD);
199 glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
200 glVertexAttribPointer(MESH_ATTR_VERTEX, 3, GL_FLOAT, 0, sizeof *m->varr, 0);
201 glVertexAttribPointer(MESH_ATTR_NORMAL, 3, GL_FLOAT, 0, sizeof *m->varr, (void*)offsetof(struct vertex, norm));
202 glVertexAttribPointer(MESH_ATTR_TANGENT, 3, GL_FLOAT, 0, sizeof *m->varr, (void*)offsetof(struct vertex, tang));
203 glVertexAttribPointer(MESH_ATTR_TEXCOORD, 2, GL_FLOAT, 0, sizeof *m->varr, (void*)offsetof(struct vertex, tex));
204 glBindBuffer(GL_ARRAY_BUFFER, 0);
207 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
208 glDrawElements(GL_TRIANGLES, m->num_idx, GL_UNSIGNED_INT, 0);
209 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
211 glDrawArrays(GL_TRIANGLES, 0, m->num_verts);
214 glDisableVertexAttribArray(MESH_ATTR_VERTEX);
215 glDisableVertexAttribArray(MESH_ATTR_NORMAL);
216 glDisableVertexAttribArray(MESH_ATTR_TANGENT);
217 glDisableVertexAttribArray(MESH_ATTR_TEXCOORD);
220 void draw_meshgroup(struct meshgroup *mg)
223 if(update_meshgroup_vbo(mg) == -1) {
228 glEnableVertexAttribArray(MESH_ATTR_VERTEX);
229 glEnableVertexAttribArray(MESH_ATTR_NORMAL);
230 glEnableVertexAttribArray(MESH_ATTR_TANGENT);
231 glEnableVertexAttribArray(MESH_ATTR_TEXCOORD);
233 glBindBuffer(GL_ARRAY_BUFFER, mg->vbo);
234 glVertexAttribPointer(MESH_ATTR_VERTEX, 3, GL_FLOAT, 0, sizeof(struct vertex), 0);
235 glVertexAttribPointer(MESH_ATTR_NORMAL, 3, GL_FLOAT, 0, sizeof(struct vertex), (void*)offsetof(struct vertex, norm));
236 glVertexAttribPointer(MESH_ATTR_TANGENT, 3, GL_FLOAT, 0, sizeof(struct vertex), (void*)offsetof(struct vertex, tang));
237 glVertexAttribPointer(MESH_ATTR_TEXCOORD, 2, GL_FLOAT, 0, sizeof(struct vertex), (void*)offsetof(struct vertex, tex));
238 glBindBuffer(GL_ARRAY_BUFFER, 0);
241 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mg->ibo);
242 glDrawElements(GL_TRIANGLES, mg->num_idx, GL_UNSIGNED_INT, 0);
243 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
245 glDrawArrays(GL_TRIANGLES, 0, mg->num_verts);
248 glDisableVertexAttribArray(MESH_ATTR_VERTEX);
249 glDisableVertexAttribArray(MESH_ATTR_NORMAL);
250 glDisableVertexAttribArray(MESH_ATTR_TANGENT);
251 glDisableVertexAttribArray(MESH_ATTR_TEXCOORD);
254 static int update_mesh_vbo(struct mesh *m)
256 if(m->num_verts <= 0) return -1;
259 glGenBuffers(1, &m->vbo);
261 glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
262 glBufferData(GL_ARRAY_BUFFER, m->num_verts * sizeof *m->varr, m->varr, GL_STATIC_DRAW);
263 glBindBuffer(GL_ARRAY_BUFFER, 0);
267 glGenBuffers(1, &m->ibo);
269 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
270 glBufferData(GL_ELEMENT_ARRAY_BUFFER, m->num_idx * sizeof *m->iarr,
271 m->iarr, GL_STATIC_DRAW);
272 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
277 static int update_meshgroup_vbo(struct meshgroup *mg)
280 struct vertex *varr, *vptr;
281 unsigned int *iarr = 0, *iptr;
284 mg->num_verts = mg->num_idx = 0;
286 for(i=0; i<mg->num_meshes; i++) {
287 mg->num_verts += mg->meshes[i]->num_verts;
288 mg->num_idx += mg->meshes[i]->num_idx;
291 if(mg->num_verts <= 0) return -1;
293 if(!(varr = malloc(mg->num_verts * sizeof *varr))) {
294 fprintf(stderr, "update_meshgroup_vbo: failed to allocate vertex array with %d vertices\n", mg->num_verts);
297 if(mg->num_idx > 0) {
298 if(!(iarr = malloc(mg->num_idx * sizeof *iarr))) {
299 fprintf(stderr, "update_meshgroup_vbo: failed to allocate index array with %d indices\n", mg->num_idx);
308 for(i=0; i<mg->num_meshes; i++) {
310 memcpy(vptr, m->varr, m->num_verts * sizeof *vptr);
311 vptr += m->num_verts;
314 memcpy(iptr, m->iarr, m->num_idx * sizeof *iptr);
320 glGenBuffers(1, &mg->vbo);
322 glBindBuffer(GL_ARRAY_BUFFER, mg->vbo);
323 glBufferData(GL_ARRAY_BUFFER, mg->num_verts * sizeof *varr, varr, GL_STATIC_DRAW);
324 glBindBuffer(GL_ARRAY_BUFFER, 0);
327 glGenBuffers(1, &mg->ibo);
329 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mg->ibo);
330 glBufferData(GL_ELEMENT_ARRAY_BUFFER, mg->num_idx * sizeof *iarr, iarr, GL_STATIC_DRAW);
331 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);