disabled dep-files when building on dos, because it goes into an infinite loop
[dosdemo] / src / metaball.c
index 052607d..9404912 100644 (file)
@@ -9,14 +9,7 @@
 #include "gfxutil.h"
 #include "util.h"
 #include "metasurf.h"
-#include "dynarr.h"
-
-struct mesh {
-       int prim;
-       struct g3d_vertex *varr;
-       int16_t *iarr;
-       int vcount, icount;
-};
+#include "mesh.h"
 
 struct metaball {
        float energy;
@@ -27,12 +20,8 @@ static int init(void);
 static void destroy(void);
 static void start(long trans_time);
 static void draw(void);
-static void draw_mesh(struct mesh *mesh);
-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",
@@ -44,7 +33,7 @@ static struct screen scr = {
 
 static float cam_theta, cam_phi = 25;
 static float cam_dist = 10;
-static struct mesh mmesh;
+static struct g3d_mesh mmesh;
 
 static struct metasurface *msurf;
 
@@ -52,8 +41,6 @@ static struct metasurface *msurf;
 #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];
@@ -67,11 +54,6 @@ 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;
@@ -81,11 +63,10 @@ static int init(void)
                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_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;
@@ -97,7 +78,7 @@ static int init(void)
 
 static void destroy(void)
 {
-       dynarr_free(mmesh.varr);
+       msurf_free(msurf);
 }
 
 static void start(long trans_time)
@@ -115,66 +96,46 @@ static void start(long trans_time)
 
 static void update(void)
 {
-       static int prev_mx, prev_my;
-       static unsigned int prev_bmask;
-
-       if(mouse_bmask) {
-               if((mouse_bmask ^ prev_bmask) == 0) {
-                       int dx = mouse_x - prev_mx;
-                       int dy = mouse_y - prev_my;
+       int i, j;
+       float tsec = time_msec / 1000.0f;
+       static float phase[] = {0.0, M_PI / 3.0, M_PI * 0.8};
+       static float speed[] = {0.8, 1.4, 1.0};
+       static float scale[][3] = {{1, 2, 0.8}, {0.5, 1.6, 0.6}, {1.5, 0.7, 0.5}};
+       static float offset[][3] = {{0, 0, 0}, {0.25, 0, 0}, {-0.2, 0.15, 0.2}};
 
-                       if(dx || dy) {
-                               if(mouse_bmask & 1) {
-                                       cam_theta += dx * 1.0;
-                                       cam_phi += dy * 1.0;
+       mouse_orbit_update(&cam_theta, &cam_phi, &cam_dist);
 
-                                       if(cam_phi < -90) cam_phi = -90;
-                                       if(cam_phi > 90) cam_phi = 90;
-                               }
-                               if(mouse_bmask & 4) {
-                                       cam_dist += dy * 0.5;
+       for(i=0; i<NUM_MBALLS; i++) {
+               float t = (tsec + phase[i]) * speed[i];
 
-                                       if(cam_dist < 0) cam_dist = 0;
-                               }
-                       }
-               }
-       }
-       prev_mx = mouse_x;
-       prev_my = mouse_y;
-       prev_bmask = mouse_bmask;
-
-       {
-               int i, j;
-               float tsec = time_msec / 1000.0f;
-               static float phase[] = {0.0, M_PI / 3.0, M_PI * 0.8};
-               static float speed[] = {0.8, 1.4, 1.0};
-               static float scale[][3] = {{1, 2, 0.8}, {0.5, 1.6, 0.6}, {1.5, 0.7, 0.5}};
-               static float offset[][3] = {{0, 0, 0}, {0.25, 0, 0}, {-0.2, 0.15, 0.2}};
-
-               for(i=0; i<NUM_MBALLS; i++) {
-                       float t = (tsec + phase[i]) * speed[i];
-
-                       for(j=0; j<3; j++) {
-                               float x = sin(t + j * M_PI / 2.0);
-                               mball[i].pos[j] = offset[i][j] + x * scale[i][j];
-                       }
+               for(j=0; j<3; j++) {
+                       float x = sin(t + j * M_PI / 2.0);
+                       mball[i].pos[j] = offset[i][j] + x * scale[i][j];
                }
        }
 
        calc_voxel_field();
-
-       dynarr_free(mmesh.varr);
-       mmesh.vcount = 0;
-       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);
@@ -183,74 +144,35 @@ static void draw(void)
 
        g3d_light_pos(0, -10, 10, 20);
 
-       zsort(&mmesh);
+       zsort_mesh(&mmesh);
 
        g3d_mtl_diffuse(0.6, 0.6, 0.6);
 
        draw_mesh(&mmesh);
 
-       swap_buffers(fb_pixels);
-}
-
-static void draw_mesh(struct mesh *mesh)
-{
-       if(mesh->iarr) {
-               g3d_draw_indexed(mesh->prim, mesh->varr, mesh->vcount, mesh->iarr, mesh->icount);
-       } else {
-               g3d_draw(mesh->prim, mesh->varr, mesh->vcount);
-       }
-}
-
-static struct {
-       struct g3d_vertex *varr;
-       const float *xform;
-} zsort_cls;
-
-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];
-
-       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];
+       g3d_viewport(0, 0, fb_width, fb_height);
 
-       va = zsort_cls.varr + a[2];
-       vb = zsort_cls.varr + b[2];
-
-       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];
-
-       return za - zb;
-}
-
-static void zsort(struct mesh *m)
-{
-       int nfaces = m->icount / 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);
+       swap_buffers(fb_pixels);
 }
 
 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++) {
@@ -269,46 +191,3 @@ static void calc_voxel_field(void)
        }
        ++dbg;
 }
-
-static float eval(struct metasurface *ms, float x, float y, float z)
-{
-       int xidx = cround64(VOL_SZ * x / VOL_SCALE);
-       int yidx = cround64(VOL_SZ * y / VOL_SCALE);
-       int zidx = cround64(VOL_SZ * z / VOL_SCALE);
-
-       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;
-       float val, len;
-
-       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);
-
-       val = eval(ms, x, y, z);
-       v.nx = eval(ms, x + VOX_DIST, y, z) - val;
-       v.ny = eval(ms, x, y + VOX_DIST, z) - val;
-       v.nz = eval(ms, x, y, z - VOX_DIST) - val;
-
-       if((len = sqrt(v.nx * v.nx + v.ny * v.ny + v.nz * v.nz)) != 0.0f) {
-               v.nx /= len;
-               v.ny /= len;
-               v.nz /= len;
-       }
-
-       mmesh.varr = dynarr_push(mmesh.varr, &v);
-       assert(mmesh.varr);
-       ++mmesh.vcount;
-}
-
-