From 2b29d1e182bcfe8255a9e73fa5c17d17b06e778b Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Thu, 12 Oct 2023 17:50:01 +0300 Subject: [PATCH] grab and drop, also refactor of metaobject callbacks --- src/game.c | 45 +++++------ src/game.h | 8 ++ src/metaobj.c | 247 +++++++++++++++++++++++++++++++++++++++++++++------------ src/metaobj.h | 18 ++++- 4 files changed, 243 insertions(+), 75 deletions(-) diff --git a/src/game.c b/src/game.c index 3d96161..88d8d1a 100644 --- a/src/game.c +++ b/src/game.c @@ -10,10 +10,6 @@ #include "cgmath/cgmath.h" #include "metaobj.h" -#define BBOX_XSZ 16 -#define BBOX_YSZ 15 -#define BBOX_ZSZ 10 -#define VOX_RES 24 #define BBOX_HXSZ (BBOX_XSZ / 2.0f) #define BBOX_HYSZ (BBOX_YSZ / 2.0f) @@ -28,13 +24,14 @@ #define VBUF_MAX_TRIS 256 #define VBUF_SIZE (VBUF_MAX_TRIS * 3) +unsigned long time_msec; + static struct g3d_vertex *vbuf; static struct metasurface *msurf; -static struct mobject **mobj; +static struct mobject **mobjects, *mobj; #define NUM_OBJ 2 static int num_mobj, cur_obj; -static int grabbed; static int mousebn[3]; static int mousex, mousey; @@ -84,10 +81,11 @@ int game_init(void) vbuf = malloc_nf(VBUF_SIZE * sizeof *vbuf); num_mobj = NUM_OBJ; - mobj = malloc(num_mobj * sizeof *mobj); - mobj[0] = metaobj_sgi(); - mobj[1] = metaobj_sflake(); + mobjects = malloc(num_mobj * sizeof *mobj); + mobjects[0] = metaobj_sgi(); + mobjects[1] = metaobj_sflake(); cur_obj = 1; + mobj = mobjects[cur_obj]; return 0; } @@ -102,7 +100,7 @@ static void update(float tsec) cgm_vec3 pos; float *vox = msurf_voxels(msurf); - mobj[cur_obj]->update(mobj[cur_obj], tsec); + mobjects[cur_obj]->update(mobjects[cur_obj], tsec); for(i=0; ieval(mobj[cur_obj], &pos); + energy += mobj->eval(mobj, &pos); *vox++ = energy; } @@ -128,8 +126,10 @@ static void update(float tsec) void game_draw(void) { - unsigned long msec = game_getmsec(); - float tsec = (float)msec / 1000.0f; + float tsec; + + time_msec = game_getmsec(); + tsec = (float)time_msec / 1000.0f; update(tsec); @@ -157,7 +157,6 @@ static void draw_metaballs(void) int i, nverts, vbuf_count; float *varr, *narr; struct g3d_vertex *vbptr; - static int nfrm; nverts = msurf_vertex_count(msurf); varr = msurf_vertices(msurf); @@ -187,8 +186,6 @@ static void draw_metaballs(void) if(vbptr > vbuf) { g3d_draw(G3D_TRIANGLES, vbuf, vbptr - vbuf); } - - nfrm++; } void game_keyboard(int key, int press) @@ -203,10 +200,12 @@ void game_mouse(int bn, int press, int x, int y) mousey = y; if(bn == 0) { - if(press && !grabbed) { - grabbed = 1; - } else if(!press && grabbed) { - grabbed = 0; + if(press) { + if(y > 3 * FB_HEIGHT / 4) { + mobj->swstate(mobj, MOBJ_GRABING); + } + } else { + mobj->swstate(mobj, MOBJ_DROPPING); } } } @@ -221,10 +220,8 @@ void game_motion(int x, int y) if((dx | dy) == 0) return; if(mousebn[0]) { - if(grabbed) { - mobj[cur_obj]->pos.x += dx * 0.1; - mobj[cur_obj]->pos.y -= dy * 0.1; - } + mobj->pos.x += dx * 0.1; + mobj->pos.y -= dy * 0.1; } if(mousebn[2]) { cam_theta += (float)dx * (0.6f * 1.333333333f); diff --git a/src/game.h b/src/game.h index c416037..037ff32 100644 --- a/src/game.h +++ b/src/game.h @@ -4,7 +4,15 @@ #define FB_WIDTH 320 #define FB_HEIGHT 200 +#define BBOX_XSZ 16 +#define BBOX_YSZ 15 +#define BBOX_ZSZ 10 +#define VOX_RES 24 + +#define TRANSDUR 1.0f + extern unsigned char *framebuf, *vmem; +extern unsigned long time_msec; int game_init(void); void game_shutdown(void); diff --git a/src/metaobj.c b/src/metaobj.c index 71790e5..aee79b4 100644 --- a/src/metaobj.c +++ b/src/metaobj.c @@ -1,77 +1,230 @@ #include #include #include "cgmath/cgmath.h" +#include "game.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 struct mobject *mobj_create(int num); +static void swstate(struct mobject *mobj, int st); +static void update(struct mobject *mobj, float tsec); +static float eval(struct mobject *mobj, cgm_vec3 *pos); + +static void upd_sflake_ball(struct mobject *mobj, struct mball *ball, float tsec, float t); +static int calc_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 void upd_sgi_caps(struct mobject *mobj, struct mcapsule *caps, float tsec, float t); + static float capsule_distsq(struct mcapsule *c, cgm_vec3 *pos); +static float easein(float x); +static float easeout(float x); -/* ---- sphereflake ---- */ -#define SF_MAX_DEPTH 2 -static cgm_vec4 *sfsph; -struct mobject *metaobj_sflake(void) +static struct mobject *mobj_create(int num) { + int i; 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); + mobj->idlepos = malloc_nf(num * sizeof *mobj->idlepos); + mobj->mot = malloc_nf(num * sizeof *mobj->mot); - gen_sflake(sfsph, 0, SF_MAX_DEPTH, 0, 0, 0, 20); + for(i=0; imot[i].x = 2.0f * ((float)rand() / (float)RAND_MAX) - 1.0f; + mobj->mot[i].y = 2.0f * ((float)rand() / (float)RAND_MAX) - 1.0f; + mobj->mot[i].z = 2.0f * ((float)rand() / (float)RAND_MAX) - 1.0f; + mobj->mot[i].w = 0.8; + } - mobj->update = upd_sflake; - mobj->eval = eval_sflake; + mobj->swstate = swstate; + mobj->update = update; + mobj->eval = eval; + + mobj->state = -1; + swstate(mobj, MOBJ_IDLE); return mobj; } -static void upd_sflake(struct mobject *mobj, float t) +static void swstate(struct mobject *mobj, int st) { - int i; - struct mball *ball = mobj->balls; - float mat[16]; + if(st == mobj->state) return; + if(st == MOBJ_GRABING && mobj->state != MOBJ_IDLE) return; + if(st == MOBJ_DROPPING && mobj->state != MOBJ_HELD && mobj->state != MOBJ_GRABING) { + return; + } - 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); + switch(st) { + case MOBJ_GRABING: + if(mobj->state != MOBJ_IDLE) return; + break; + + case MOBJ_DROPPING: + if(mobj->state != MOBJ_HELD && mobj->state != MOBJ_GRABING) { + return; + } + break; + + case MOBJ_IDLE: + mobj->pos.x = mobj->pos.z = 0.0f; + mobj->pos.y = -BBOX_YSZ * 0.5f; + break; + } - 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++; + mobj->state = st; + mobj->tstart = (float)time_msec / 1000.0f; +} + +static void update(struct mobject *mobj, float tsec) +{ + int i, count; + struct mball *ball; + struct mcapsule *caps; + float t; + cgm_vec3 *idleptr; + cgm_vec4 *motptr; + + count = mobj->num_balls + mobj->num_caps; + + if(mobj->state != MOBJ_IDLE) { + cgm_midentity(mobj->xform); + cgm_mrotate_x(mobj->xform, tsec); + cgm_mrotate_y(mobj->xform, tsec); + cgm_mtranslate(mobj->xform, mobj->pos.x, mobj->pos.y, mobj->pos.z); + } + if(mobj->state != MOBJ_HELD) { + for(i=0; iidlepos[i].x = sin(tsec * mobj->mot[i].x + mobj->mot[i].y) * mobj->mot[i].z * 3.0f; + mobj->idlepos[i].z = cos(tsec * mobj->mot[i].z + mobj->mot[i].y) * mobj->mot[i].x * 3.0f; + mobj->idlepos[i].y = -BBOX_YSZ * 0.45f; + } + } + + idleptr = mobj->idlepos; + motptr = mobj->mot; + ball = mobj->balls; + caps = mobj->caps; + + switch(mobj->state) { + case MOBJ_IDLE: + if(mobj->balls) { + for(i=0; inum_balls; i++) { + ball->pos = idleptr[i]; + ball->energy = motptr[i].w; + ball++; + } + idleptr += mobj->num_balls; + motptr += mobj->num_balls; + } + if(mobj->caps) { + for(i=0; inum_caps; i++) { + caps->end[0] = caps->end[1] = idleptr[i]; + caps->energy = motptr[i].w; + caps++; + } + } + break; + + case MOBJ_GRABING: + t = easeout((tsec - mobj->tstart) / TRANSDUR); + if(t >= 1.0f) mobj->swstate(mobj, MOBJ_HELD); + if(0) { + case MOBJ_DROPPING: + t = easein((tsec - mobj->tstart) / TRANSDUR); + if(t >= 1.0f) mobj->swstate(mobj, MOBJ_IDLE); + } + for(i=0; inum_balls; i++) { + mobj->upd_ball(mobj, ball++, tsec, t); + } + for(i=0; inum_caps; i++) { + mobj->upd_caps(mobj, caps++, tsec, t); + } + break; + + case MOBJ_HELD: + for(i=0; inum_balls; i++) { + mobj->upd_ball(mobj, ball++, tsec, 0); + } + for(i=0; inum_caps; i++) { + mobj->upd_caps(mobj, caps++, tsec, 0); + } + break; } } -static float eval_sflake(struct mobject *mobj, cgm_vec3 *pos) +static float eval(struct mobject *mobj, cgm_vec3 *pos) { int i; float dsq, energy = 0.0f; struct mball *ball = mobj->balls; + struct mcapsule *caps = mobj->caps; for(i=0; inum_balls; i++) { dsq = cgm_vdist_sq(&ball->pos, pos); energy += ball->energy / dsq; ball++; } + + for(i=0; inum_caps; i++) { + dsq = capsule_distsq(mobj->caps + i, pos); + energy += caps->energy / dsq; + } return energy; } -static int num_balls(int depth) + +/* ---- sphereflake ---- */ +#define SF_MAX_DEPTH 2 +static cgm_vec4 *sfsph; + +struct mobject *metaobj_sflake(void) +{ + int num_balls; + struct mobject *mobj; + + num_balls = calc_num_balls(SF_MAX_DEPTH); + + mobj = mobj_create(num_balls); + + mobj->num_balls = num_balls; + mobj->balls = malloc_nf(num_balls * sizeof *mobj->balls); + sfsph = malloc_nf(num_balls * sizeof *sfsph); + + gen_sflake(sfsph, 0, SF_MAX_DEPTH, 0, 0, 0, 20); + + mobj->upd_ball = upd_sflake_ball; + return mobj; +} + +static void upd_sflake_ball(struct mobject *mobj, struct mball *ball, float tsec, float t) +{ + int idx = ball - mobj->balls; + cgm_vec3 pos; + + switch(mobj->state) { + case MOBJ_DROPPING: + t = 1.0f - t; + case MOBJ_GRABING: + cgm_vcons(&pos, sfsph[idx].x, sfsph[idx].y, sfsph[idx].z); + cgm_vmul_m4v3(&pos, mobj->xform); + cgm_vlerp(&ball->pos, mobj->idlepos + idx, &pos, t); + ball->energy = cgm_lerp(mobj->mot[idx].w, sfsph[idx].w, t); + break; + + case MOBJ_HELD: + cgm_vcons(&ball->pos, sfsph[idx].x, sfsph[idx].y, sfsph[idx].z); + cgm_vmul_m4v3(&ball->pos, mobj->xform); + ball->energy = sfsph[idx].w; + break; + } +} + +static int calc_num_balls(int depth) { if(!depth) return 0; - return num_balls(depth - 1) * 6 + 1; + return calc_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) @@ -130,13 +283,13 @@ 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 = mobj_create(NUM_SGI_VERTS); + mobj->num_caps = NUM_SGI_VERTS; mobj->caps = calloc_nf(mobj->num_caps, sizeof *mobj->caps); @@ -144,12 +297,11 @@ struct mobject *metaobj_sgi(void) mobj->caps[i].energy = 0.7; } - mobj->update = upd_sgi; - mobj->eval = eval_sgi; + mobj->swstate = swstate; return mobj; } -static void upd_sgi(struct mobject *mobj, float t) +static void upd_sgi_caps(struct mobject *mobj, struct mcapsule *caps, float tsec, float t) { int i; float mat[16]; @@ -172,19 +324,6 @@ static void upd_sgi(struct mobject *mobj, float t) } } -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; @@ -211,3 +350,13 @@ static float capsule_distsq(struct mcapsule *c, cgm_vec3 *pos) cgm_vadd_scaled(&pp, &dir, t); return cgm_vdist_sq(&pp, pos); } + +static float easein(float x) +{ + return x * x * x; +} + +static float easeout(float x) +{ + return 1.0f - pow(1.0f - x, 3.0f); +} diff --git a/src/metaobj.h b/src/metaobj.h index cd73e8a..7dbee8a 100644 --- a/src/metaobj.h +++ b/src/metaobj.h @@ -1,6 +1,12 @@ #ifndef METAOBJ_H_ #define METAOBJ_H_ +enum { + MOBJ_IDLE, + MOBJ_GRABING, + MOBJ_HELD, + MOBJ_DROPPING +}; struct mball { float energy; @@ -14,12 +20,20 @@ struct mcapsule { }; struct mobject { - cgm_vec3 pos; + cgm_vec3 pos, mouse; + int state; struct mball *balls; struct mcapsule *caps; int num_balls, num_caps; + cgm_vec3 *idlepos; + cgm_vec4 *mot; + float tstart; + float xform[16]; - void (*update)(struct mobject *mobj, float t); + void (*swstate)(struct mobject *mobj, int newst); + void (*update)(struct mobject *mobj, float tsec); + void (*upd_ball)(struct mobject *mobj, struct mball *ball, float tsec, float t); + void (*upd_caps)(struct mobject *mobj, struct mcapsule *caps, float tsec, float t); float (*eval)(struct mobject *mobj, cgm_vec3 *pos); }; -- 1.7.10.4