From a1ede8e271fee1b4d029752603096db2be780e67 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Thu, 15 Feb 2018 06:30:14 +0200 Subject: [PATCH] - added mesh operations: apply_mesh_xform, append_mesh, indexify_mesh (untested), gen_plane_mesh, gen_cube_mesh. --- Makefile | 4 +- src/infcubes.c | 9 +- src/mesh.c | 294 ++++++++++++++++++++++++++++++++++++++++++++------------ src/mesh.h | 11 ++- src/polytest.c | 4 +- 5 files changed, 256 insertions(+), 66 deletions(-) diff --git a/Makefile b/Makefile index af258f8..9845ce2 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ demoobj = main.obj demo.obj screen.obj cfgopt.obj music.obj gfxutil.obj & -3dgfx.obj polyfill.obj polyclip.obj metasurf.obj dynarr.obj +3dgfx.obj polyfill.obj polyclip.obj metasurf.obj dynarr.obj mesh.obj scrobj = tunnel.obj fract.obj grise.obj polytest.obj plasma.obj bump.obj & -thunder.obj metaball.obj greets.obj +thunder.obj metaball.obj greets.obj infcubes.obj sysobj = gfx.obj vbe.obj watdpmi.obj timer.obj keyb.obj mouse.obj sball.obj & logger.obj tinyfps.obj util.obj obj = $(baseobj) $(demoobj) $(sysobj) $(scrobj) diff --git a/src/infcubes.c b/src/infcubes.c index cfa665b..3df25fe 100644 --- a/src/infcubes.c +++ b/src/infcubes.c @@ -8,6 +8,7 @@ #include "polyfill.h" #include "imago2.h" #include "gfxutil.h" +#include "mesh.h" static int init(void); static void destroy(void); @@ -26,6 +27,7 @@ static struct screen scr = { static float cam_theta = -29, cam_phi = 35; static float cam_dist = 5; static struct pimage tex_crate; +static struct g3d_mesh mesh_cube; struct screen *infcubes_screen(void) { @@ -54,6 +56,10 @@ static int init(void) int b = *src++; *dst++ = PACK_RGB16(r, g, b); } + + if(gen_cube_mesh(&mesh_cube, 1.0f, 3) == -1) { + return -1; + } return 0; } @@ -99,7 +105,8 @@ static void draw(void) draw_cube(-6); g3d_polygon_mode(G3D_TEX); - draw_cube(1); + /*draw_cube(1);*/ + draw_mesh(&mesh_cube); swap_buffers(fb_pixels); } diff --git a/src/mesh.c b/src/mesh.c index 0027ccf..9e31840 100644 --- a/src/mesh.c +++ b/src/mesh.c @@ -1,5 +1,6 @@ #include #include +#include #include #include "mesh.h" #include "3dgfx.h" @@ -80,74 +81,249 @@ void draw_mesh(struct g3d_mesh *mesh) } } +void apply_mesh_xform(struct g3d_mesh *mesh, const float *xform) +{ + int i; + struct g3d_vertex *v = mesh->varr; + + for(i=0; ivcount; i++) { + float x = xform[0] * v->x + xform[4] * v->y + xform[8] * v->z + xform[12]; + float y = xform[1] * v->x + xform[5] * v->y + xform[9] * v->z + xform[13]; + v->z = xform[2] * v->x + xform[6] * v->y + xform[10] * v->z + xform[14]; + v->x = x; + v->y = y; + x = xform[0] * v->nx + xform[4] * v->ny + xform[8] * v->nz; + y = xform[1] * v->nx + xform[5] * v->ny + xform[9] * v->nz; + v->nz = xform[2] * v->nx + xform[6] * v->ny + xform[10] * v->nz; + v->nx = x; + v->ny = y; + ++v; + } +} + +int append_mesh(struct g3d_mesh *ma, struct g3d_mesh *mb) +{ + int i, new_vcount, new_icount; + void *tmp; + int16_t *iptr; + + if(ma->prim != mb->prim) { + fprintf(stderr, "append_mesh failed, primitive mismatch\n"); + return -1; + } + + if(ma->iarr || mb->iarr) { + if(!ma->iarr) { + if(indexify_mesh(ma) == -1) { + return -1; + } + } else if(!mb->iarr) { + if(indexify_mesh(mb) == -1) { + return -1; + } + } + + new_icount = ma->icount + mb->icount; + if(!(iptr = realloc(ma->iarr, new_icount * sizeof *iptr))) { + fprintf(stderr, "append_mesh: failed to allocate combined index buffer (%d indices)\n", new_icount); + return -1; + } + ma->iarr = iptr; + + iptr += ma->icount; + for(i=0; iicount; i++) { + *iptr++ = mb->iarr[i] + ma->vcount; + } + ma->icount = new_icount; + } + + new_vcount = ma->vcount + mb->vcount; + if(!(tmp = realloc(ma->varr, new_vcount * sizeof *ma->varr))) { + fprintf(stderr, "append_mesh: failed to allocate combined vertex buffer (%d verts)\n", new_vcount); + return -1; + } + ma->varr = tmp; + memcpy(ma->varr + ma->vcount, mb->varr, mb->vcount * sizeof *ma->varr); + ma->vcount = new_vcount; + return 0; +} + +#define FEQ(a, b) ((a) - (b) < 1e-5 && (b) - (a) < 1e-5) +static int cmp_vertex(struct g3d_vertex *a, struct g3d_vertex *b) +{ + if(!FEQ(a->x, b->x) || !FEQ(a->y, b->y) || !FEQ(a->z, b->z) || !FEQ(a->w, b->w)) + return -1; + if(!FEQ(a->nx, b->nx) || !FEQ(a->ny, b->ny) || !FEQ(a->nz, b->nz)) + return -1; + if(!FEQ(a->u, b->u) || !FEQ(a->v, b->v)) + return -1; + if(a->r != b->r || a->g != b->g || a->b != b->b || a->a != b->a) + return -1; + return 0; +} + +static int find_existing(struct g3d_vertex *v, struct g3d_vertex *varr, int vcount) +{ + int i; + for(i=0; iiarr) { + fprintf(stderr, "indexify_mesh failed: already indexed\n"); + return -1; + } -#define NORMAL(vp, x, y, z) do { vp->nx = x; vp->ny = y; vp->nz = z; } while(0) -#define COLOR(vp, cr, cg, cb) do { vp->r = cr; vp->g = cg; vp->b = cb; } while(0) -#define TEXCOORD(vp, tu, tv) do { vp->u = tu; vp->v = tv; } while(0) -#define VERTEX(vp, vx, vy, vz) \ - do { \ - vp->x = vx; vp->y = vy; vp->z = vz; vp->w = 1.0f; \ - ++vp; \ - } while(0) + nfaces = mesh->vcount / mesh->prim; + max_icount = mesh->vcount; -int gen_cube(struct g3d_mesh *mesh, float sz, int sub) + if(!(mesh->iarr = malloc(max_icount * sizeof *mesh->iarr))) { + fprintf(stderr, "indexify_mesh failed to allocate index buffer of %d indices\n", max_icount); + return -1; + } + + vin = vout = mesh->varr; + iout = mesh->iarr; + + for(i=0; iprim; j++) { + if((idx = find_existing(vin, mesh->varr, out_vcount)) >= 0) { + *iout++ = idx; + } else { + *iout++ = out_vcount++; + if(vin != vout) { + *vout++ = *vin; + } + } + ++vin; + } + } + + /* XXX also shrink buffers? I'll just leave them to max size for now */ + return 0; +} + +int gen_plane_mesh(struct g3d_mesh *m, float width, float height, int usub, int vsub) { + int i, j; + int nfaces, nverts, nidx, uverts, vverts; + float x, y, u, v, du, dv; struct g3d_vertex *vptr; - float hsz = sz / 2.0; + int16_t *iptr; - mesh->prim = G3D_QUADS; - mesh->iarr = 0; - mesh->icount = 0; + if(usub < 1) usub = 1; + if(vsub < 1) vsub = 1; - mesh->vcount = 24; - if(!(mesh->varr = malloc(mesh->vcount * sizeof *mesh->varr))) { + nfaces = usub * vsub; + uverts = usub + 1; + vverts = vsub + 1; + du = (float)width / (float)usub; + dv = (float)height / (float)vsub; + + nverts = uverts * vverts; + nidx = nfaces * 4; + + if(!(m->varr = malloc(nverts * sizeof *m->varr))) { + fprintf(stderr, "gen_plane_mesh: failed to allocate vertex buffer (%d vertices)\n", nverts); return -1; } - vptr = mesh->varr; + if(!(m->iarr = malloc(nidx * sizeof *m->iarr))) { + fprintf(stderr, "gen_plane_mesh: failed to allocate index buffer (%d indices)\n", nidx); + free(m->varr); + m->varr = 0; + return -1; + } + + m->prim = G3D_QUADS; + m->vcount = nverts; + m->icount = nidx; + + vptr = m->varr; + iptr = m->iarr; - /* -Z */ - NORMAL(vptr, 0, 0, -1); - COLOR(vptr, 255, 0, 255); - VERTEX(vptr, hsz, -hsz, -hsz); - VERTEX(vptr, -hsz, -hsz, -hsz); - VERTEX(vptr, -hsz, hsz, -hsz); - VERTEX(vptr, hsz, hsz, -hsz); - /* -Y */ - NORMAL(vptr, 0, -1, 0); - COLOR(vptr, 0, 255, 255); - VERTEX(vptr, -hsz, -hsz, -hsz); - VERTEX(vptr, hsz, -hsz, -hsz); - VERTEX(vptr, hsz, -hsz, hsz); - VERTEX(vptr, -hsz, -hsz, hsz); - /* -X */ - NORMAL(vptr, -1, 0, 0); - COLOR(vptr, 255, 255, 0); - VERTEX(vptr, -hsz, -hsz, -hsz); - VERTEX(vptr, -hsz, -hsz, hsz); - VERTEX(vptr, -hsz, hsz, hsz); - VERTEX(vptr, -hsz, hsz, -hsz); - /* +X */ - NORMAL(vptr, 1, 0, 0); - COLOR(vptr, 255, 0, 0); - VERTEX(vptr, hsz, -hsz, hsz); - VERTEX(vptr, hsz, -hsz, -hsz); - VERTEX(vptr, hsz, hsz, -hsz); - VERTEX(vptr, hsz, hsz, hsz); - /* +Y */ - NORMAL(vptr, 0, 1, 0); - COLOR(vptr, 0, 255, 0); - VERTEX(vptr, -hsz, hsz, hsz); - VERTEX(vptr, hsz, hsz, hsz); - VERTEX(vptr, hsz, hsz, -hsz); - VERTEX(vptr, -hsz, hsz, -hsz); - /* +Z */ - NORMAL(vptr, 0, 0, 1); - COLOR(vptr, 0, 0, 255); - VERTEX(vptr, -hsz, -hsz, hsz); - VERTEX(vptr, hsz, -hsz, hsz); - VERTEX(vptr, hsz, hsz, hsz); - VERTEX(vptr, -hsz, hsz, hsz); + v = 0.0f; + for(i=0; ix = x; + vptr->y = y; + vptr->z = 0.0f; + vptr->w = 1.0f; + vptr->nx = 0.0f; + vptr->ny = 0.0f; + vptr->nz = 1.0f; + vptr->u = u; + vptr->v = v; + vptr->r = vptr->g = vptr->b = vptr->a = 255; + ++vptr; + + u += du; + } + v += dv; + } + + for(i=0; i 0 ? &tmpmesh : mesh; + if(gen_plane_mesh(m, sz, sz, sub, sub) == -1) + return -1; + g3d_load_identity(); + g3d_rotate(rotface[i][0], rotface[i][1], rotface[i][2], rotface[i][3]); + g3d_translate(0, 0, sz / 2.0f); + g3d_get_matrix(G3D_MODELVIEW, xform); + apply_mesh_xform(m, xform); + if(i > 0) { + if(append_mesh(mesh, m) == -1) { + return -1; + } + } + } + g3d_pop_matrix(); return 0; } @@ -165,7 +341,7 @@ static void torusvec(float *res, float theta, float phi, float mr, float rr) res[2] = -rx * cos(theta) + rz * sin(theta); } -int gen_torus(struct g3d_mesh *mesh, float rad, float ringrad, int usub, int vsub) +int gen_torus_mesh(struct g3d_mesh *mesh, float rad, float ringrad, int usub, int vsub) { int i, j; int nfaces, uverts, vverts; diff --git a/src/mesh.h b/src/mesh.h index 92cc240..704c492 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -1,6 +1,8 @@ #ifndef MESH_H_ #define MESH_H_ +#include "inttypes.h" + struct g3d_mesh { int prim; struct g3d_vertex *varr; @@ -13,7 +15,12 @@ int load_mesh(struct g3d_mesh *mesh, const char *fname); void zsort_mesh(struct g3d_mesh *mesh); void draw_mesh(struct g3d_mesh *mesh); -int gen_cube(struct g3d_mesh *mesh, float sz, int sub); -int gen_torus(struct g3d_mesh *mesh, float rad, float ringrad, int usub, int vsub); +void apply_mesh_xform(struct g3d_mesh *mesh, const float *xform); +int append_mesh(struct g3d_mesh *ma, struct g3d_mesh *mb); +int indexify_mesh(struct g3d_mesh *mesh); + +int gen_plane_mesh(struct g3d_mesh *mesh, float width, float height, int usub, int vsub); +int gen_cube_mesh(struct g3d_mesh *mesh, float sz, int sub); +int gen_torus_mesh(struct g3d_mesh *mesh, float rad, float ringrad, int usub, int vsub); #endif /* MESH_H_ */ diff --git a/src/polytest.c b/src/polytest.c index 207fb31..85b3128 100644 --- a/src/polytest.c +++ b/src/polytest.c @@ -44,8 +44,8 @@ static int init(void) { int i; - gen_cube(&cube, 1.0, 0); - gen_torus(&torus, 1.0, 0.25, 24, 12); + gen_cube_mesh(&cube, 1.0, 0); + gen_torus_mesh(&torus, 1.0, 0.25, 24, 12); /* scale texcoords */ for(i=0; i