9 struct g3d_vertex *varr;
13 static int zsort_cmp(const void *aptr, const void *bptr)
15 const float *m = zsort_cls.xform;
17 const struct g3d_vertex *va = (const struct g3d_vertex*)aptr;
18 const struct g3d_vertex *vb = (const struct g3d_vertex*)bptr;
20 float za = m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
21 float zb = m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
26 za += m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
27 zb += m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
32 static int zsort_indexed_cmp(const void *aptr, const void *bptr)
34 const uint16_t *a = (const uint16_t*)aptr;
35 const uint16_t *b = (const uint16_t*)bptr;
37 const float *m = zsort_cls.xform;
39 const struct g3d_vertex *va = zsort_cls.varr + a[0];
40 const struct g3d_vertex *vb = zsort_cls.varr + b[0];
42 float za = m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
43 float zb = m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
45 va = zsort_cls.varr + a[2];
46 vb = zsort_cls.varr + b[2];
48 za += m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
49 zb += m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
55 void zsort_mesh(struct g3d_mesh *m)
57 zsort_cls.varr = m->varr;
58 zsort_cls.xform = g3d_get_matrix(G3D_MODELVIEW, 0);
61 int nfaces = m->icount / m->prim;
62 qsort(m->iarr, nfaces, m->prim * sizeof *m->iarr, zsort_indexed_cmp);
64 int nfaces = m->vcount / m->prim;
65 qsort(m->varr, nfaces, m->prim * sizeof *m->varr, zsort_cmp);
70 void draw_mesh(struct g3d_mesh *mesh)
73 g3d_draw_indexed(mesh->prim, mesh->varr, mesh->vcount, mesh->iarr, mesh->icount);
75 g3d_draw(mesh->prim, mesh->varr, mesh->vcount);
79 void apply_mesh_xform(struct g3d_mesh *mesh, const float *xform)
82 struct g3d_vertex *v = mesh->varr;
84 for(i=0; i<mesh->vcount; i++) {
85 float x = xform[0] * v->x + xform[4] * v->y + xform[8] * v->z + xform[12];
86 float y = xform[1] * v->x + xform[5] * v->y + xform[9] * v->z + xform[13];
87 v->z = xform[2] * v->x + xform[6] * v->y + xform[10] * v->z + xform[14];
90 x = xform[0] * v->nx + xform[4] * v->ny + xform[8] * v->nz;
91 y = xform[1] * v->nx + xform[5] * v->ny + xform[9] * v->nz;
92 v->nz = xform[2] * v->nx + xform[6] * v->ny + xform[10] * v->nz;
99 int append_mesh(struct g3d_mesh *ma, struct g3d_mesh *mb)
101 int i, new_vcount, new_icount;
105 if(ma->prim != mb->prim) {
106 fprintf(stderr, "append_mesh failed, primitive mismatch\n");
110 if(ma->iarr || mb->iarr) {
112 if(indexify_mesh(ma) == -1) {
115 } else if(!mb->iarr) {
116 if(indexify_mesh(mb) == -1) {
121 new_icount = ma->icount + mb->icount;
122 if(!(iptr = realloc(ma->iarr, new_icount * sizeof *iptr))) {
123 fprintf(stderr, "append_mesh: failed to allocate combined index buffer (%d indices)\n", new_icount);
129 for(i=0; i<mb->icount; i++) {
130 *iptr++ = mb->iarr[i] + ma->vcount;
132 ma->icount = new_icount;
135 new_vcount = ma->vcount + mb->vcount;
136 if(!(tmp = realloc(ma->varr, new_vcount * sizeof *ma->varr))) {
137 fprintf(stderr, "append_mesh: failed to allocate combined vertex buffer (%d verts)\n", new_vcount);
141 memcpy(ma->varr + ma->vcount, mb->varr, mb->vcount * sizeof *ma->varr);
142 ma->vcount = new_vcount;
146 #define FEQ(a, b) ((a) - (b) < 1e-5 && (b) - (a) < 1e-5)
147 static int cmp_vertex(struct g3d_vertex *a, struct g3d_vertex *b)
149 if(!FEQ(a->x, b->x) || !FEQ(a->y, b->y) || !FEQ(a->z, b->z) || !FEQ(a->w, b->w))
151 if(!FEQ(a->nx, b->nx) || !FEQ(a->ny, b->ny) || !FEQ(a->nz, b->nz))
153 if(!FEQ(a->u, b->u) || !FEQ(a->v, b->v))
155 if(a->r != b->r || a->g != b->g || a->b != b->b || a->a != b->a)
160 static int find_existing(struct g3d_vertex *v, struct g3d_vertex *varr, int vcount)
163 for(i=0; i<vcount; i++) {
164 if(cmp_vertex(v, varr++) == 0) {
171 int indexify_mesh(struct g3d_mesh *mesh)
173 int i, j, nfaces, max_icount, idx;
175 struct g3d_vertex *vin, *vout;
179 fprintf(stderr, "indexify_mesh failed: already indexed\n");
183 nfaces = mesh->vcount / mesh->prim;
184 max_icount = mesh->vcount;
186 if(!(mesh->iarr = malloc(max_icount * sizeof *mesh->iarr))) {
187 fprintf(stderr, "indexify_mesh failed to allocate index buffer of %d indices\n", max_icount);
191 vin = vout = mesh->varr;
194 for(i=0; i<nfaces; i++) {
195 for(j=0; j<mesh->prim; j++) {
196 if((idx = find_existing(vin, mesh->varr, out_vcount)) >= 0) {
199 *iout++ = out_vcount++;
208 /* XXX also shrink buffers? I'll just leave them to max size for now */
212 void normalize_mesh_normals(struct g3d_mesh *mesh)
215 struct g3d_vertex *v = mesh->varr;
217 for(i=0; i<mesh->vcount; i++) {
218 float mag = sqrt(v->nx * v->nx + v->ny * v->ny + v->nz * v->nz);
219 float s = (mag == 0.0f) ? 1.0f : 1.0f / mag;
227 int gen_plane_mesh(struct g3d_mesh *m, float width, float height, int usub, int vsub)
230 int nfaces, nverts, nidx, uverts, vverts;
231 float x, y, u, v, du, dv;
232 struct g3d_vertex *vptr;
235 if(usub < 1) usub = 1;
236 if(vsub < 1) vsub = 1;
238 nfaces = usub * vsub;
241 du = (float)width / (float)usub;
242 dv = (float)height / (float)vsub;
244 nverts = uverts * vverts;
247 if(!(m->varr = malloc(nverts * sizeof *m->varr))) {
248 fprintf(stderr, "gen_plane_mesh: failed to allocate vertex buffer (%d vertices)\n", nverts);
251 if(!(m->iarr = malloc(nidx * sizeof *m->iarr))) {
252 fprintf(stderr, "gen_plane_mesh: failed to allocate index buffer (%d indices)\n", nidx);
266 for(i=0; i<vverts; i++) {
267 y = (v - 0.5) * height;
270 for(j=0; j<uverts; j++) {
271 x = (u - 0.5) * width;
282 vptr->r = vptr->g = vptr->b = vptr->a = 255;
290 for(i=0; i<vsub; i++) {
291 for(j=0; j<usub; j++) {
292 int idx = i * uverts + j;
295 *iptr++ = idx + uverts + 1;
296 *iptr++ = idx + uverts;
302 int gen_cube_mesh(struct g3d_mesh *mesh, float sz, int sub)
306 struct g3d_mesh tmpmesh;
307 static float rotface[][4] = {
316 g3d_matrix_mode(G3D_MODELVIEW);
320 m = i > 0 ? &tmpmesh : mesh;
321 if(gen_plane_mesh(m, sz, sz, sub, sub) == -1)
324 g3d_rotate(rotface[i][0], rotface[i][1], rotface[i][2], rotface[i][3]);
325 g3d_translate(0, 0, sz / 2.0f);
326 apply_mesh_xform(m, g3d_get_matrix(G3D_MODELVIEW, 0));
328 if(append_mesh(mesh, m) == -1) {
338 static void torusvec(float *res, float theta, float phi, float mr, float rr)
343 rx = -cos(phi) * rr + mr;
347 res[0] = rx * sin(theta) + rz * cos(theta);
349 res[2] = -rx * cos(theta) + rz * sin(theta);
352 int gen_torus_mesh(struct g3d_mesh *mesh, float rad, float ringrad, int usub, int vsub)
355 int nfaces, uverts, vverts;
356 struct g3d_vertex *vptr;
359 mesh->prim = G3D_QUADS;
361 if(usub < 4) usub = 4;
362 if(vsub < 2) vsub = 2;
367 mesh->vcount = uverts * vverts;
368 nfaces = usub * vsub;
369 mesh->icount = nfaces * 4;
371 printf("generating torus with %d faces (%d vertices)\n", nfaces, mesh->vcount);
373 if(!(mesh->varr = malloc(mesh->vcount * sizeof *mesh->varr))) {
376 if(!(mesh->iarr = malloc(mesh->icount * sizeof *mesh->iarr))) {
382 for(i=0; i<uverts; i++) {
383 float u = (float)i / (float)(uverts - 1);
384 float theta = u * 2.0 * M_PI;
387 torusvec(rcent, theta, 0, rad, 0);
389 for(j=0; j<vverts; j++) {
390 float v = (float)j / (float)(vverts - 1);
391 float phi = v * 2.0 * M_PI;
392 int chess = (i & 1) == (j & 1);
394 torusvec(&vptr->x, theta, phi, rad, ringrad);
397 vptr->nx = (vptr->x - rcent[0]) / ringrad;
398 vptr->ny = (vptr->y - rcent[1]) / ringrad;
399 vptr->nz = (vptr->z - rcent[2]) / ringrad;
402 vptr->r = chess ? 255 : 64;
404 vptr->b = chess ? 64 : 255;
407 if(i < usub && j < vsub) {
408 int idx = i * vverts + j;
411 *iptr++ = idx + vverts + 1;
412 *iptr++ = idx + vverts;