From: John Tsiombikas Date: Wed, 11 Oct 2023 05:27:56 +0000 (+0300) Subject: meta shapes X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=commitdiff_plain;h=15a13efb20311cf8d151dc86602e7b97be3372ff;p=metatoy meta shapes --- diff --git a/Makefile b/Makefile index dfd0e35..e4b62f8 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ bin = game inc = -Isrc -Isrc/3dgfx -Isrc/kern -CFLAGS = -pedantic -Wall -g $(inc) -MMD +CFLAGS = -pedantic -Wall -O2 -ffast-math -fno-strict-aliasing -g $(inc) -MMD LDFLAGS = -lGL -lX11 -lXext -lm $(bin): $(obj) diff --git a/src/game.c b/src/game.c index 70f40c4..136fb4f 100644 --- a/src/game.c +++ b/src/game.c @@ -8,12 +8,13 @@ #include "metasurf.h" #include "util.h" #include "cgmath/cgmath.h" +#include "metaobj.h" #define BBOX_SIZE 10.0f #define BBOX_HEIGHT 15.0f #define BBOX_HSZ (BBOX_SIZE / 2.0f) #define BBOX_HH (BBOX_HEIGHT / 2.0f) -#define VOX_RES 30 +#define VOX_RES 32 #define VOX_YRES (VOX_RES * BBOX_HEIGHT / BBOX_SIZE) #define VOX_STEP (BBOX_SIZE / (float)VOX_RES) #define VOX_YSTEP (BBOX_HEIGHT / (float)VOX_YRES) @@ -21,55 +22,25 @@ #define VBUF_MAX_TRIS 256 #define VBUF_SIZE (VBUF_MAX_TRIS * 3) -struct mball { - float energy; - cgm_vec3 pos; -}; - -struct mcapsule { - float energy; - cgm_vec3 end[2]; - float len; -}; - -static struct g3d_mesh mesh; static struct g3d_vertex *vbuf; static struct metasurface *msurf; -static struct mball *balls; -static int num_balls; -static struct mcapsule *caps; -static int num_caps; +static struct mobject **mobj; + +#define NUM_OBJ 2 +static int num_mobj, cur_obj; +static int grabbed; + +static int mousebn[3]; +static int mousex, mousey; +static float cam_theta, cam_phi; + static void update(float tsec); static void draw_metaballs(void); -static float capsule_distsq(struct mcapsule *c, cgm_vec3 *pos); - -static cgm_vec3 sgiv[] = { - {2.794170, 4.254175, 2.738066}, - {2.794170, 4.254174, -4.358471}, - {-2.173414, 4.254174, -4.358471}, - {-2.173414, -2.842363, -4.358470}, - {4.923134, -2.842363, -4.358471}, - {4.923134, 2.125212, -4.358471}, - {4.923134, 2.125212, 2.738066}, - {4.923134, -4.971326, 2.738067}, - {4.923134, -4.971326, -2.229511}, - {-2.173413, -4.971326, -2.229511}, - {-2.173413, -4.971325, 4.867042}, - {2.794170, -4.971325, 4.867042}, - {2.794170, 2.125213, 4.867042}, - {-4.302382, 2.125213, 4.867042}, - {-4.302383, -2.842362, 4.867042}, - {-4.302382, -2.842363, -2.229511}, - {-4.302382, 4.254175, -2.229512}, - {-4.302383, 4.254175, 2.738066} -}; + int game_init(void) { - int i; - float mat[16]; - init_colormgr(); g3d_init(); @@ -89,8 +60,6 @@ int game_init(void) g3d_polygon_mode(G3D_GOURAUD); - gen_torus_mesh(&mesh, 2.0, 0.7, 24, 12); - if(!(msurf = msurf_create())) { return -1; } @@ -102,30 +71,11 @@ int game_init(void) vbuf = malloc_nf(VBUF_SIZE * sizeof *vbuf); - num_balls = 0; - balls = calloc_nf(num_balls, sizeof *balls); - num_caps = sizeof sgiv / sizeof *sgiv; - caps = calloc_nf(num_caps, sizeof *caps); - - for(i=0; iupdate(mobj[cur_obj], tsec); for(i=0; ieval(mobj[cur_obj], &pos); *vox++ = energy; } @@ -193,6 +124,8 @@ void game_draw(void) g3d_matrix_mode(G3D_MODELVIEW); g3d_load_identity(); g3d_translate(0, 1, -15); + g3d_rotate(cam_phi, 1, 0, 0); + g3d_rotate(cam_theta, 0, 1, 0); /*g3d_rotate(tsec * 50.0f, 1, 0, 0); g3d_rotate(tsec * 30.0f, 0, 0, 1); @@ -248,35 +181,38 @@ void game_keyboard(int key, int press) void game_mouse(int bn, int press, int x, int y) { + mousebn[bn] = press; + mousex = x; + mousey = y; + + if(bn == 0) { + if(press && !grabbed) { + grabbed = 1; + } else if(!press && grabbed) { + grabbed = 0; + } + } } void game_motion(int x, int y) { -} + int dx = x - mousex; + int dy = y - mousey; + mousex = x; + mousey = y; -static float capsule_distsq(struct mcapsule *c, cgm_vec3 *pos) -{ - float t; - cgm_vec3 pp, dir, pdir; - - dir = c->end[1]; cgm_vsub(&dir, c->end); - if(c->len != 0.0f) { - float s = 1.0f / c->len; - dir.x *= s; - dir.y *= s; - dir.z *= s; - } - pdir = *pos; cgm_vsub(&pdir, c->end); - t = cgm_vdot(&dir, &pdir); + if((dx | dy) == 0) return; - if(t < 0.0f) { - return cgm_vdist_sq(c->end, pos); + if(mousebn[0]) { + if(grabbed) { + mobj[cur_obj]->pos.x += dx * 0.1; + mobj[cur_obj]->pos.y -= dy * 0.1; + } } - if(t > c->len) { - return cgm_vdist_sq(c->end + 1, pos); + if(mousebn[2]) { + cam_theta += (float)dx * (0.6f * 1.333333333f); + cam_phi += (float)dy * 0.6f; + if(cam_phi < -90) cam_phi = -90; + if(cam_phi > 90) cam_phi = 90; } - - pp = c->end[0]; - cgm_vadd_scaled(&pp, &dir, t); - return cgm_vdist_sq(&pp, pos); } diff --git a/src/metaobj.c b/src/metaobj.c new file mode 100644 index 0000000..71790e5 --- /dev/null +++ b/src/metaobj.c @@ -0,0 +1,213 @@ +#include +#include +#include "cgmath/cgmath.h" +#include "metasurf.h" +#include "metaobj.h" +#include "util.h" + +static void upd_sflake(struct mobject *mobj, float t); +static float eval_sflake(struct mobject *mobj, cgm_vec3 *pos); +static int num_balls(int depth); +static int gen_sflake(cgm_vec4 *sarr, int num, int depth, float x, float y, float z, float rad); + +static void upd_sgi(struct mobject *mobj, float t); +static float eval_sgi(struct mobject *mobj, cgm_vec3 *pos); +static float capsule_distsq(struct mcapsule *c, cgm_vec3 *pos); + +/* ---- sphereflake ---- */ +#define SF_MAX_DEPTH 2 +static cgm_vec4 *sfsph; + +struct mobject *metaobj_sflake(void) +{ + struct mobject *mobj; + + mobj = calloc_nf(1, sizeof *mobj); + + mobj->num_balls = num_balls(SF_MAX_DEPTH); + mobj->balls = malloc_nf(mobj->num_balls * sizeof *mobj->balls); + sfsph = malloc_nf(mobj->num_balls * sizeof *sfsph); + + gen_sflake(sfsph, 0, SF_MAX_DEPTH, 0, 0, 0, 20); + + mobj->update = upd_sflake; + mobj->eval = eval_sflake; + return mobj; +} + +static void upd_sflake(struct mobject *mobj, float t) +{ + int i; + struct mball *ball = mobj->balls; + float mat[16]; + + cgm_midentity(mat); + cgm_mrotate_x(mat, t); + cgm_mrotate_y(mat, t); + cgm_mtranslate(mat, mobj->pos.x, mobj->pos.y, mobj->pos.z); + + for(i=0; inum_balls; i++) { + cgm_vcons(&ball->pos, sfsph[i].x, sfsph[i].y, sfsph[i].z); + cgm_vmul_m4v3(&ball->pos, mat); + ball->energy = sfsph[i].w; + ball++; + } +} + +static float eval_sflake(struct mobject *mobj, cgm_vec3 *pos) +{ + int i; + float dsq, energy = 0.0f; + struct mball *ball = mobj->balls; + + for(i=0; inum_balls; i++) { + dsq = cgm_vdist_sq(&ball->pos, pos); + energy += ball->energy / dsq; + ball++; + } + return energy; +} + +static int num_balls(int depth) +{ + if(!depth) return 0; + return num_balls(depth - 1) * 6 + 1; +} + +static int gen_sflake(cgm_vec4 *sarr, int num, int depth, float x, float y, float z, float rad) +{ + int subnum; + float subrad, offs; + + if(!depth) return 0; + + sarr[num].x = x; + sarr[num].y = y; + sarr[num].z = z; + sarr[num].w = rad; + num++; + + subrad = rad * 0.2f; + offs = rad * 0.16f; + + subnum = 0; + subnum += gen_sflake(sarr, num + subnum, depth - 1, x + offs, y, z, subrad); + subnum += gen_sflake(sarr, num + subnum, depth - 1, x - offs, y, z, subrad); + subnum += gen_sflake(sarr, num + subnum, depth - 1, x, y + offs, z, subrad); + subnum += gen_sflake(sarr, num + subnum, depth - 1, x, y - offs, z, subrad); + subnum += gen_sflake(sarr, num + subnum, depth - 1, x, y, z + offs, subrad); + subnum += gen_sflake(sarr, num + subnum, depth - 1, x, y, z - offs, subrad); + return subnum + 1; +} + +/* ---- SGI logo ---- */ + +static const cgm_vec3 sgiv[] = { + {2.794170, 4.254175, 2.738066}, + {2.794170, 4.254174, -4.358471}, + {-2.173414, 4.254174, -4.358471}, + {-2.173414, -2.842363, -4.358470}, + {4.923134, -2.842363, -4.358471}, + {4.923134, 2.125212, -4.358471}, + {4.923134, 2.125212, 2.738066}, + {4.923134, -4.971326, 2.738067}, + {4.923134, -4.971326, -2.229511}, + {-2.173413, -4.971326, -2.229511}, + {-2.173413, -4.971325, 4.867042}, + {2.794170, -4.971325, 4.867042}, + {2.794170, 2.125213, 4.867042}, + {-4.302382, 2.125213, 4.867042}, + {-4.302383, -2.842362, 4.867042}, + {-4.302382, -2.842363, -2.229511}, + {-4.302382, 4.254175, -2.229512}, + {-4.302383, 4.254175, 2.738066} +}; +#define NUM_SGI_VERTS (sizeof sgiv / sizeof *sgiv) +static float sgimat[16]; + +struct mobject *metaobj_sgi(void) +{ + int i; + struct mobject *mobj; + + mobj = calloc_nf(1, sizeof *mobj); + + cgm_midentity(sgimat); + cgm_mrotate_y(sgimat, -M_PI / 4.0f); + cgm_mrotate_x(sgimat, M_PI / 4.0f); + cgm_mtranslate(sgimat, 0, -4, 0); + + mobj->num_caps = NUM_SGI_VERTS; + mobj->caps = calloc_nf(mobj->num_caps, sizeof *mobj->caps); + + for(i=0; inum_caps; i++) { + mobj->caps[i].energy = 0.7; + } + + mobj->update = upd_sgi; + mobj->eval = eval_sgi; + return mobj; +} + +static void upd_sgi(struct mobject *mobj, float t) +{ + int i; + float mat[16]; + cgm_vec3 vpos[NUM_SGI_VERTS]; + + cgm_mcopy(mat, sgimat); + cgm_mrotate_y(mat, t); + cgm_mtranslate(mat, mobj->pos.x, mobj->pos.y, mobj->pos.z); + + for(i=0; icaps[i].end[0] = vpos[i]; + mobj->caps[i].end[1] = vpos[(i + 1) % NUM_SGI_VERTS]; + mobj->caps[i].len = cgm_vdist(mobj->caps[i].end, mobj->caps[i].end + 1); + } +} + +static float eval_sgi(struct mobject *mobj, cgm_vec3 *pos) +{ + int i; + float dsq, val = 0.0f; + + for(i=0; inum_caps; i++) { + dsq = capsule_distsq(mobj->caps + i, pos); + val += mobj->caps[i].energy / dsq; + } + + return val; +} + +static float capsule_distsq(struct mcapsule *c, cgm_vec3 *pos) +{ + float t; + cgm_vec3 pp, dir, pdir; + + dir = c->end[1]; cgm_vsub(&dir, c->end); + if(c->len != 0.0f) { + float s = 1.0f / c->len; + dir.x *= s; + dir.y *= s; + dir.z *= s; + } + pdir = *pos; cgm_vsub(&pdir, c->end); + t = cgm_vdot(&dir, &pdir); + + if(t < 0.0f) { + return cgm_vdist_sq(c->end, pos); + } + if(t > c->len) { + return cgm_vdist_sq(c->end + 1, pos); + } + + pp = c->end[0]; + cgm_vadd_scaled(&pp, &dir, t); + return cgm_vdist_sq(&pp, pos); +} diff --git a/src/metaobj.h b/src/metaobj.h new file mode 100644 index 0000000..cd73e8a --- /dev/null +++ b/src/metaobj.h @@ -0,0 +1,29 @@ +#ifndef METAOBJ_H_ +#define METAOBJ_H_ + + +struct mball { + float energy; + cgm_vec3 pos; +}; + +struct mcapsule { + float energy; + cgm_vec3 end[2]; + float len; +}; + +struct mobject { + cgm_vec3 pos; + struct mball *balls; + struct mcapsule *caps; + int num_balls, num_caps; + + void (*update)(struct mobject *mobj, float t); + float (*eval)(struct mobject *mobj, cgm_vec3 *pos); +}; + +struct mobject *metaobj_sflake(void); +struct mobject *metaobj_sgi(void); + +#endif /* METAOBJ_H_ */