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)
#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)
#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();
g3d_polygon_mode(G3D_GOURAUD);
- gen_torus_mesh(&mesh, 2.0, 0.7, 24, 12);
-
if(!(msurf = msurf_create())) {
return -1;
}
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; i<num_balls; i++) {
- balls[i].energy = 5;
- }
-
- cgm_midentity(mat);
- cgm_mtranslate(mat, 0, -BBOX_HH / 2, 0);
- cgm_mrotate_y(mat, -M_PI / 4.0f);
- cgm_mrotate_x(mat, M_PI / 4.0f);
-
- for(i=0; i<num_caps; i++) {
- caps[i].energy = 1;
- caps[i].end[0] = sgiv[i];
- cgm_vscale(caps[i].end, 0.6);
- caps[i].end[1] = sgiv[(i + 1) % num_caps];
- cgm_vscale(caps[i].end + 1, 0.6);
-
- cgm_vmul_m4v3(caps[i].end, mat);
- cgm_vmul_m4v3(caps[i].end + 1, mat);
- }
+ num_mobj = NUM_OBJ;
+ mobj = malloc(num_mobj * sizeof *mobj);
+ mobj[0] = metaobj_sgi();
+ mobj[1] = metaobj_sflake();
+ cur_obj = 1;
return 0;
}
static void update(float tsec)
{
- int i, j, k, n;
- float dsq, energy;
+ int i, j, k;
+ float energy;
cgm_vec3 pos;
float *vox = msurf_voxels(msurf);
- for(i=0; i<num_balls; i++) {
- balls[i].pos.y = sin(tsec) * BBOX_HH;
- }
-
- float y = sin(tsec) * BBOX_HH / 80.0f;
- for(i=0; i<num_caps; i++) {
- caps[i].end[0].y += y;
- caps[i].end[1].y += y;
- caps[i].len = cgm_vdist(caps[i].end, caps[i].end + 1);
- }
+ mobj[cur_obj]->update(mobj[cur_obj], tsec);
for(i=0; i<VOX_RES; i++) {
pos.z = -BBOX_HSZ + i * VOX_STEP;
/* initialize with the vertical distance for the pool */
energy = 5.0 / (pos.y + BBOX_HH * 0.98);
- /* add the contribution of the balls */
- for(n=0; n<num_balls; n++) {
- dsq = cgm_vdist_sq(&balls[n].pos, &pos);
- energy += balls[n].energy / dsq;
- }
-
- /* add the contribution of the capsules */
- for(n=0; n<num_caps; n++) {
- dsq = capsule_distsq(caps + n, &pos);
- energy += caps[n].energy / dsq;
- }
+ energy += mobj[cur_obj]->eval(mobj[cur_obj], &pos);
*vox++ = energy;
}
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);
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);
}
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#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; i<mobj->num_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; i<mobj->num_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; i<mobj->num_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; i<NUM_SGI_VERTS; i++) {
+ vpos[i] = sgiv[i];
+ cgm_vscale(vpos + i, 0.5);
+ cgm_vmul_m4v3(vpos + i, mat);
+ }
+
+ for(i=0; i<NUM_SGI_VERTS; i++) {
+ mobj->caps[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; i<mobj->num_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);
+}
--- /dev/null
+#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_ */