#include "gfxutil.h"
#include "util.h"
#include "metasurf.h"
-#include "dynarr.h"
struct mesh {
int prim;
static void zsort(struct mesh *m);
static void calc_voxel_field(void);
-static float eval(struct metasurface *ms, float x, float y, float z);
-static void emit_vertex(struct metasurface *ms, float x, float y, float z);
static struct screen scr = {
"metaballs",
};
static float cam_theta, cam_phi = 25;
-static float cam_dist = 3;
+static float cam_dist = 10;
static struct mesh mmesh;
static struct metasurface *msurf;
#define VOL_SZ 32
#define VOL_SCALE 10.0f
+#define VOX_DIST (VOL_SCALE / VOL_SZ)
#define VOL_HALF_SCALE (VOL_SCALE * 0.5f)
-static float *volume;
-#define VOXEL(x, y, z) (volume[(z) * VOL_SZ * VOL_SZ + (y) * VOL_SZ + (x)])
#define NUM_MBALLS 3
static struct metaball mball[NUM_MBALLS];
+static int dbg;
struct screen *metaballs_screen(void)
{
static int init(void)
{
- if(!(volume = malloc(VOL_SZ * VOL_SZ * VOL_SZ * sizeof *volume))) {
- fprintf(stderr, "failed to allocate %dx%dx%d voxel field\n", VOL_SZ, VOL_SZ, VOL_SZ);
- return -1;
- }
-
mball[0].energy = 1.2;
mball[1].energy = 0.8;
mball[2].energy = 1.0;
return -1;
}
msurf_set_resolution(msurf, VOL_SZ, VOL_SZ, VOL_SZ);
- msurf_set_bounds(msurf, 0, 0, 0, VOL_SCALE, VOL_SCALE, VOL_SCALE);
- msurf_eval_func(msurf, eval);
- msurf_set_threshold(msurf, 0.5);
+ msurf_set_bounds(msurf, -VOL_HALF_SCALE, -VOL_HALF_SCALE, -VOL_HALF_SCALE,
+ VOL_HALF_SCALE, VOL_HALF_SCALE, VOL_HALF_SCALE);
+ msurf_set_threshold(msurf, 1.7);
msurf_set_inside(msurf, MSURF_GREATER);
- msurf_vertex_func(msurf, emit_vertex);
mmesh.prim = G3D_TRIANGLES;
mmesh.varr = 0;
static void destroy(void)
{
- dynarr_free(mmesh.varr);
+ msurf_free(msurf);
}
static void start(long trans_time)
g3d_enable(G3D_LIGHTING);
g3d_enable(G3D_LIGHT0);
- g3d_polygon_mode(G3D_WIRE);
+ g3d_polygon_mode(G3D_GOURAUD);
}
static void update(void)
}
calc_voxel_field();
-
- dynarr_free(mmesh.varr);
- mmesh.varr = dynarr_alloc(0, sizeof *mmesh.varr);
msurf_polygonize(msurf);
+
+ mmesh.vcount = msurf_vertex_count(msurf);
+ mmesh.varr = msurf_vertices(msurf);
}
static void draw(void)
{
+ int i, j;
+
update();
memset(fb_pixels, 0, fb_width * fb_height * 2);
+ for(i=0; i<120; i++) {
+ for(j=0; j<160; j++) {
+ fb_pixels[(i + 60) * 320 + (j + 80)] = 0x1e7;
+ }
+ }
+ g3d_viewport(80, 60, 160, 120);
+
g3d_matrix_mode(G3D_MODELVIEW);
g3d_load_identity();
g3d_translate(0, 0, -cam_dist);
g3d_rotate(cam_phi, 1, 0, 0);
g3d_rotate(cam_theta, 0, 1, 0);
- /*g3d_light_pos(0, -10, 10, 20);*/
+ g3d_light_pos(0, -10, 10, 20);
- /*zsort(&metamesh);*/
+ zsort(&mmesh);
- /*g3d_mtl_diffuse(0.6, 0.6, 0.6);*/
+ g3d_mtl_diffuse(0.6, 0.6, 0.6);
draw_mesh(&mmesh);
+ g3d_viewport(0, 0, fb_width, fb_height);
+
swap_buffers(fb_pixels);
}
static int zsort_cmp(const void *aptr, const void *bptr)
{
- const int16_t *a = (const int16_t*)aptr;
- const int16_t *b = (const int16_t*)bptr;
-
const float *m = zsort_cls.xform;
- const struct g3d_vertex *va = zsort_cls.varr + a[0];
- const struct g3d_vertex *vb = zsort_cls.varr + b[0];
+ const struct g3d_vertex *va = (const struct g3d_vertex*)aptr;
+ const struct g3d_vertex *vb = (const struct g3d_vertex*)bptr;
float za = m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
float zb = m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
- va = zsort_cls.varr + a[2];
- vb = zsort_cls.varr + b[2];
+ ++va;
+ ++vb;
za += m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
zb += m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
static void zsort(struct mesh *m)
{
- int nfaces = m->icount / m->prim;
+ int nfaces = m->vcount / m->prim;
zsort_cls.varr = m->varr;
zsort_cls.xform = g3d_get_matrix(G3D_MODELVIEW, 0);
- qsort(m->iarr, nfaces, m->prim * sizeof *m->iarr, zsort_cmp);
+ qsort(m->varr, nfaces, m->prim * sizeof *m->varr, zsort_cmp);
}
static void calc_voxel_field(void)
{
int i, j, k, b;
- float *voxptr = volume;
+ float *voxptr;
+
+ if(!(voxptr = msurf_voxels(msurf))) {
+ fprintf(stderr, "failed to allocate voxel field\n");
+ abort();
+ }
for(i=0; i<VOL_SZ; i++) {
- float z = VOL_SCALE * ((float)i / (float)VOL_SZ - 0.5);
+ float z = -VOL_HALF_SCALE + i * VOX_DIST;
for(j=0; j<VOL_SZ; j++) {
- float y = VOL_SCALE * ((float)j / (float)VOL_SZ - 0.5);
+ float y = -VOL_HALF_SCALE + j * VOX_DIST;
for(k=0; k<VOL_SZ; k++) {
- float x = VOL_SCALE * ((float)k / (float)VOL_SZ - 0.5);
+ float x = -VOL_HALF_SCALE + k * VOX_DIST;
float val = 0.0f;
for(b=0; b<NUM_MBALLS; b++) {
}
}
}
-}
-
-static float eval(struct metasurface *ms, float x, float y, float z)
-{
- int xidx = cround64(x);
- int yidx = cround64(y);
- int zidx = cround64(z);
-
- assert(xidx >= 0 && xidx < VOL_SZ);
- assert(yidx >= 0 && yidx < VOL_SZ);
- assert(zidx >= 0 && zidx < VOL_SZ);
-
- return VOXEL(xidx, yidx, zidx);
-}
-
-static void emit_vertex(struct metasurface *ms, float x, float y, float z)
-{
- struct g3d_vertex v;
-
- v.x = x - VOL_HALF_SCALE;
- v.y = y - VOL_HALF_SCALE;
- v.z = z - VOL_HALF_SCALE;
- v.r = cround64(255.0 * x / VOL_SCALE);
- v.g = cround64(255.0 * y / VOL_SCALE);
- v.b = cround64(255.0 * z / VOL_SCALE);
-
- mmesh.varr = dynarr_push(mmesh.varr, &v);
- assert(mmesh.varr);
- ++mmesh.vcount;
+ ++dbg;
}