exhibits
authorJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 8 Jan 2018 10:31:27 +0000 (12:31 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 8 Jan 2018 10:31:27 +0000 (12:31 +0200)
src/app.cc
src/blob_exhibit.cc
src/blobs/metasurf.c
src/blobs/metasurf.h
src/exman.cc
src/exman.h
src/scene.cc

index d9d44c0..1c27685 100644 (file)
@@ -141,9 +141,11 @@ bool app_init(int argc, char **argv)
        avatar.body_rot = rad_to_deg(acos(dot(dir, Vec3(0, 0, 1))));
 
        exman = new ExhibitManager;
+       /*
        if(!exman->load(mscn, "data/exhibits")) {
                //return false;
        }
+       */
 
        blobs = new BlobExhibit;
        blobs->node = new SceneNode;
@@ -425,10 +427,7 @@ static void draw_scene()
        set_light(2, lpos[2], Vec3(0.8, 1.0, 0.8) * 0.3);
 
        rend->draw();
-
-       if(show_blobs) {
-               blobs->draw();
-       }
+       exman->draw();
 
        /*
        if(have_handtracking) {
@@ -580,6 +579,11 @@ void app_keyboard(int key, bool pressed)
                        goatvr_recenter();
                        show_message("VR recenter\n");
                        break;
+
+               case 'x':
+                       exman->clear();
+                       exman->load(mscn, "data/exhibits");
+                       break;
                }
        }
 
index 5e9f213..3d13396 100644 (file)
@@ -1,6 +1,7 @@
 #include "blob_exhibit.h"
 #include "blobs/metasurf.h"
 #include "app.h"
+#include <imago2.h>
 
 struct Metaball {
        Vec3 pos;
@@ -27,10 +28,6 @@ struct BlobPriv {
        Texture *tex;
 };
 
-static void vertex(struct metasurface *ms, float x, float y, float z);
-static float eval(struct metasurface *ms, float x, float y, float z);
-
-
 BlobExhibit::BlobExhibit()
 {
        priv = new BlobPriv;
@@ -50,12 +47,10 @@ bool BlobExhibit::init()
        if(!(priv->msurf = msurf_create())) {
                return false;
        }
-       msurf_set_user_data(priv->msurf, priv);
        msurf_set_threshold(priv->msurf, 8);
        msurf_set_inside(priv->msurf, MSURF_GREATER);
        msurf_set_bounds(priv->msurf, -3.5, 3.5, -3.5, 3.5, -3.5, 3.5);
-       msurf_eval_func(priv->msurf, eval);
-       msurf_vertex_func(priv->msurf, vertex);
+       msurf_enable(priv->msurf, MSURF_NORMALIZE);
 
        priv->tex = texman.get_texture("data/sphmap.jpg");
        return true;
@@ -73,24 +68,68 @@ void BlobExhibit::update(float dt)
 {
        double sec = time_msec / 1000.0;
 
+       float xmin, xmax, ymin, ymax, zmin, zmax;
+       int xres, yres, zres;
+
+       msurf_get_bounds(priv->msurf, &xmin, &ymin, &zmin, &xmax, &ymax, &zmax);
+       msurf_get_resolution(priv->msurf, &xres, &yres, &zres);
+
+       float xstep = (xmax - xmin) / xres;
+       float ystep = (ymax - ymin) / yres;
+       float zstep = (zmax - zmin) / zres;
+
        for(int i=0; i<NUM_MBALLS; i++) {
                float t = fmod(sec * priv->mballs[i].speed + priv->mballs[i].phase_offset, M_PI * 2.0);
                priv->mballs[i].pos.x = cos(t) * priv->mballs[i].path_scale.x + priv->mballs[i].path_offset.x;
                priv->mballs[i].pos.y = sin(t) * priv->mballs[i].path_scale.y + priv->mballs[i].path_offset.y;
                priv->mballs[i].pos.z = -cos(t) * priv->mballs[i].path_scale.z + priv->mballs[i].path_offset.z;
        }
+
+       if(!msurf_voxels(priv->msurf)) {
+               return;
+       }
+
+       float max_energy = 0.0f;
+
+//#pragma omp parallel for
+       for(int i=0; i<zres; i++) {
+               float z = zmin + i * zstep;
+               float *voxptr = msurf_slice(priv->msurf, i);
+               if(!voxptr) break;
+
+               for(int j=0; j<yres; j++) {
+                       float y = ymin + j * ystep;
+
+                       for(int k=0; k<xres; k++) {
+                               float x = xmin + k * xstep;
+
+                               float sum = 0.0f;
+                               for(int n=0; n<NUM_MBALLS; n++) {
+                                       float dx = x - priv->mballs[n].pos.x;
+                                       float dy = y - priv->mballs[n].pos.y;
+                                       float dz = z - priv->mballs[n].pos.z;
+                                       float dsq = dx * dx + dy * dy + dz * dz;
+
+                                       sum += priv->mballs[n].energy / dsq;
+                               }
+                               *voxptr++ = sum;
+                               if(sum > max_energy) max_energy = sum;
+                       }
+               }
+       }
+
+       msurf_polygonize(priv->msurf);
 }
 
 void BlobExhibit::draw() const
 {
-       pre_draw();
-
        glPushAttrib(GL_ENABLE_BIT);
 
        glUseProgram(0);
 
        glDisable(GL_LIGHTING);
        glEnable(GL_TEXTURE_2D);
+       glEnable(GL_NORMALIZE);
        priv->tex->bind();
 
        glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
@@ -103,45 +142,44 @@ void BlobExhibit::draw() const
        glScalef(1, -1, 1);
 
        glFrontFace(GL_CW);
+
+
+       int nverts = msurf_vertex_count(priv->msurf);
+       float *varr = msurf_vertices(priv->msurf);
+       float *narr = msurf_normals(priv->msurf);
+
        glBegin(GL_TRIANGLES);
        glColor3f(1, 1, 1);
-       msurf_polygonize(priv->msurf);
+       for(int i=0; i<nverts; i++) {
+               glNormal3f(narr[0], narr[1], narr[2]);
+               glVertex3f(varr[0], varr[1], varr[2]);
+               varr += 3;
+               narr += 3;
+       }
        glEnd();
-       glFrontFace(GL_CCW);
 
-       glLoadIdentity();
-       glMatrixMode(GL_MODELVIEW);
-
-       glPopAttrib();
-
-       post_draw();
-}
+       glFrontFace(GL_CCW);
 
-static void vertex(struct metasurface *ms, float x, float y, float z)
-{
-       static const float delta = 0.01;
+       glDisable(GL_TEXTURE_2D);
+       glDisable(GL_LIGHTING);
 
-       float val = eval(ms, x, y, z);
-       float dfdx = eval(ms, x + delta, y, z) - val;
-       float dfdy = eval(ms, x, y + delta, z) - val;
-       float dfdz = eval(ms, x, y, z + delta) - val;
+       varr = msurf_vertices(priv->msurf);
+       narr = msurf_normals(priv->msurf);
 
-       glNormal3f(dfdx, dfdy, dfdz);
-       glVertex3f(x, y, z);
-}
+       glBegin(GL_LINES);
+       glColor3f(0, 1, 0);
 
-static float eval(struct metasurface *ms, float x, float y, float z)
-{
-       float sum = 0.0f;
-       BlobPriv *priv = (BlobPriv*)msurf_get_user_data(ms);
+       float nscale = 0.2;
+       for(int i=0; i<nverts; i++) {
+               glVertex3f(varr[0], varr[1], varr[2]);
+               glVertex3f(varr[0] + narr[0] * nscale, varr[1] + narr[1] * nscale, varr[2] + narr[2] * nscale);
+               varr += 3;
+               narr += 3;
+       }
+       glEnd();
 
-       for(int i=0; i<NUM_MBALLS; i++) {
-               float dx = x - priv->mballs[i].pos.x;
-               float dy = y - priv->mballs[i].pos.y;
-               float dz = z - priv->mballs[i].pos.z;
-               float dsq = dx * dx + dy * dy + dz * dz;
+       glLoadIdentity();
+       glMatrixMode(GL_MODELVIEW);
 
-               sum += priv->mballs[i].energy / dsq;
-       }
-       return sum;
+       glPopAttrib();
 }
index 2207b3d..0298e05 100644 (file)
@@ -1,60 +1,28 @@
-/*
-metasurf - a library for implicit surface polygonization
-Copyright (C) 2011-2016  John Tsiombikas <nuclear@member.fsf.org>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-/* this is pulled from: https://github.com/jtsiomb/metasurf */
 #include <stdio.h>
 #include <stdlib.h>
+#include <math.h>
 #include "metasurf.h"
 #include "mcubes.h"
-
-#undef USE_MTETRA
-#define USE_MCUBES
-
-#if (defined(USE_MTETRA) && defined(USE_MCUBES)) || (!defined(USE_MTETRA) && !defined(USE_MCUBES))
-#error "pick either USE_MTETRA or USE_MCUBES, not both..."
-#endif
+#include "logger.h"
 
 typedef float vec3[3];
 
 struct metasurface {
        vec3 min, max;
-       int res[3];
+       int res[3], newres[3];
        float thres;
 
-       msurf_eval_func_t eval;
-       msurf_vertex_func_t vertex;
-       msurf_normal_func_t normal;
-       void *udata;
-
        float dx, dy, dz;
-       int flip;
+       unsigned int flags;
+
+       float *voxels;
 
-       vec3 vbuf[3];
-       int nverts;
+       int varr_size, varr_alloc_size;
+       float *varr, *narr;
 };
 
 static int msurf_init(struct metasurface *ms);
-static void process_cell(struct metasurface *ms, vec3 pos, vec3 sz);
-#ifdef USE_MTETRA
-static void process_tetra(struct metasurface *ms, int *idx, vec3 *pos, float *val);
-#endif
-#ifdef USE_MCUBES
-static void process_cube(struct metasurface *ms, vec3 *pos, float *val);
-#endif
+static void process_cell(struct metasurface *ms, int xcell, int ycell, int zcell, vec3 pos, vec3 sz);
 
 
 struct metasurface *msurf_create(void)
@@ -72,46 +40,56 @@ struct metasurface *msurf_create(void)
 
 void msurf_free(struct metasurface *ms)
 {
-       free(ms);
+       if(ms) {
+               free(ms->voxels);
+               free(ms->varr);
+               free(ms->narr);
+               free(ms);
+       }
 }
 
 static int msurf_init(struct metasurface *ms)
 {
+       ms->voxels = 0;
        ms->thres = 0.0;
-       ms->eval = 0;
-       ms->vertex = 0;
-       ms->normal = 0;
-       ms->udata = 0;
        ms->min[0] = ms->min[1] = ms->min[2] = -1.0;
        ms->max[0] = ms->max[1] = ms->max[2] = 1.0;
-       ms->res[0] = ms->res[1] = ms->res[2] = 40;
-       ms->nverts = 0;
+       ms->res[0] = ms->res[1] = ms->res[2] = 0;
+       ms->newres[0] = ms->newres[1] = ms->newres[2] = 40;
+
+       ms->varr_alloc_size = ms->varr_size = 0;
+       ms->varr = ms->narr = 0;
 
        ms->dx = ms->dy = ms->dz = 0.001;
-       ms->flip = 0;
+       ms->flags = 0;
 
        return 0;
 }
 
-void msurf_set_user_data(struct metasurface *ms, void *udata)
+void msurf_enable(struct metasurface *ms, unsigned int opt)
 {
-       ms->udata = udata;
+       ms->flags |= opt;
 }
 
-void *msurf_get_user_data(struct metasurface *ms)
+void msurf_disable(struct metasurface *ms, unsigned int opt)
 {
-       return ms->udata;
+       ms->flags &= ~opt;
+}
+
+int msurf_is_enabled(struct metasurface *ms, unsigned int opt)
+{
+       return ms->flags & opt;
 }
 
 void msurf_set_inside(struct metasurface *ms, int inside)
 {
        switch(inside) {
        case MSURF_GREATER:
-               ms->flip = 0;
+               msurf_disable(ms, MSURF_FLIP);
                break;
 
        case MSURF_LESS:
-               ms->flip = 1;
+               msurf_enable(ms, MSURF_FLIP);
                break;
 
        default:
@@ -121,22 +99,7 @@ void msurf_set_inside(struct metasurface *ms, int inside)
 
 int msurf_get_inside(struct metasurface *ms)
 {
-       return ms->flip ? MSURF_LESS : MSURF_GREATER;
-}
-
-void msurf_eval_func(struct metasurface *ms, msurf_eval_func_t func)
-{
-       ms->eval = func;
-}
-
-void msurf_vertex_func(struct metasurface *ms, msurf_vertex_func_t func)
-{
-       ms->vertex = func;
-}
-
-void msurf_normal_func(struct metasurface *ms, msurf_normal_func_t func)
-{
-       ms->normal = func;
+       return msurf_is_enabled(ms, MSURF_FLIP) ? MSURF_LESS : MSURF_GREATER;
 }
 
 void msurf_set_bounds(struct metasurface *ms, float xmin, float ymin, float zmin, float xmax, float ymax, float zmax)
@@ -161,9 +124,9 @@ void msurf_get_bounds(struct metasurface *ms, float *xmin, float *ymin, float *z
 
 void msurf_set_resolution(struct metasurface *ms, int xres, int yres, int zres)
 {
-       ms->res[0] = xres;
-       ms->res[1] = yres;
-       ms->res[2] = zres;
+       ms->newres[0] = xres;
+       ms->newres[1] = yres;
+       ms->newres[2] = zres;
 }
 
 void msurf_get_resolution(struct metasurface *ms, int *xres, int *yres, int *zres)
@@ -184,112 +147,155 @@ float msurf_get_threshold(struct metasurface *ms)
 }
 
 
+float *msurf_voxels(struct metasurface *ms)
+{
+       if(ms->res[0] != ms->newres[0] || ms->res[1] != ms->newres[1] || ms->res[2] != ms->newres[2]) {
+               int count;
+               ms->res[0] = ms->newres[0];
+               ms->res[1] = ms->newres[1];
+               ms->res[2] = ms->newres[2];
+               count = ms->res[0] * ms->res[1] * ms->res[2];
+               free(ms->voxels);
+               if(!(ms->voxels = malloc(count * sizeof *ms->voxels))) {
+                       return 0;
+               }
+       }
+       return ms->voxels;
+}
+
+float *msurf_slice(struct metasurface *ms, int idx)
+{
+       float *vox = msurf_voxels(ms);
+       if(!vox) return 0;
+
+       return vox + ms->res[0] * ms->res[1] * idx;
+}
+
 int msurf_polygonize(struct metasurface *ms)
 {
        int i, j, k;
        vec3 pos, delta;
 
-       if(!ms->eval || !ms->vertex) {
-               fprintf(stderr, "you need to set eval and vertex callbacks before calling msurf_polygonize\n");
-               return -1;
-       }
+       if(!ms->voxels) return -1;
+
+       ms->varr_size = 0;
 
        for(i=0; i<3; i++) {
                delta[i] = (ms->max[i] - ms->min[i]) / (float)ms->res[i];
        }
 
-       pos[0] = ms->min[0];
        for(i=0; i<ms->res[0] - 1; i++) {
-               pos[1] = ms->min[1];
                for(j=0; j<ms->res[1] - 1; j++) {
-
-                       pos[2] = ms->min[2];
                        for(k=0; k<ms->res[2] - 1; k++) {
 
-                               process_cell(ms, pos, delta);
+                               pos[0] = ms->min[0] + i * delta[0];
+                               pos[1] = ms->min[1] + j * delta[1];
+                               pos[2] = ms->min[2] + k * delta[2];
 
-                               pos[2] += delta[2];
+                               process_cell(ms, i, j, k, pos, delta);
                        }
-                       pos[1] += delta[1];
                }
-               pos[0] += delta[0];
        }
        return 0;
 }
 
-
-static void process_cell(struct metasurface *ms, vec3 pos, vec3 sz)
+int msurf_vertex_count(struct metasurface *ms)
 {
-       int i;
-       vec3 p[8];
-       float val[8];
-
-#ifdef USE_MTETRA
-       static int tetra[][4] = {
-               {0, 2, 3, 7},
-               {0, 2, 6, 7},
-               {0, 4, 6, 7},
-               {0, 6, 1, 2},
-               {0, 6, 1, 4},
-               {5, 6, 1, 4}
-       };
-#endif
-
-       static const float offs[][3] = {
-               {0.0f, 0.0f, 0.0f},
-               {1.0f, 0.0f, 0.0f},
-               {1.0f, 1.0f, 0.0f},
-               {0.0f, 1.0f, 0.0f},
-               {0.0f, 0.0f, 1.0f},
-               {1.0f, 0.0f, 1.0f},
-               {1.0f, 1.0f, 1.0f},
-               {0.0f, 1.0f, 1.0f}
-       };
-
-       for(i=0; i<8; i++) {
-               p[i][0] = pos[0] + sz[0] * offs[i][2];
-               p[i][1] = pos[1] + sz[1] * offs[i][1];
-               p[i][2] = pos[2] + sz[2] * offs[i][0];
-
-               val[i] = ms->eval(ms, p[i][0], p[i][1], p[i][2]);
-       }
-
-#ifdef USE_MTETRA
-       for(i=0; i<6; i++) {
-               process_tetra(ms, tetra[i], p, val);
-       }
-#endif
-#ifdef USE_MCUBES
-       process_cube(ms, p, val);
-#endif
+       return ms->varr_size / 3;
 }
 
+float *msurf_vertices(struct metasurface *ms)
+{
+       return ms->varr;
+}
 
-/* ---- marching cubes implementation ---- */
-#ifdef USE_MCUBES
+float *msurf_normals(struct metasurface *ms)
+{
+       return ms->narr;
+}
 
 static unsigned int mc_bitcode(float *val, float thres);
 
-static void process_cube(struct metasurface *ms, vec3 *pos, float *val)
+static void process_cell(struct metasurface *ms, int xcell, int ycell, int zcell, vec3 cellpos, vec3 cellsz)
 {
+       int i, j, k, slice_size;
+       vec3 pos[8];
+       float dfdx[8], dfdy[8], dfdz[8];
+       vec3 vert[12], norm[12];
+       float val[8];
+       float *cellptr;
+       unsigned int code;
+
+       static const int offs[][3] = {
+               {0, 0, 0},
+               {1, 0, 0},
+               {1, 1, 0},
+               {0, 1, 0},
+               {0, 0, 1},
+               {1, 0, 1},
+               {1, 1, 1},
+               {0, 1, 1}
+       };
+
        static const int pidx[12][2] = {
                {0, 1}, {1, 2}, {2, 3}, {3, 0}, {4, 5}, {5, 6},
                {6, 7}, {7, 4}, {0, 4}, {1, 5}, {2, 6}, {3, 7}
        };
-       int i, j;
-       vec3 vert[12];
-       unsigned int code = mc_bitcode(val, ms->thres);
 
-       if(ms->flip) {
+       slice_size = ms->res[0] * ms->res[1];
+       cellptr = ms->voxels + slice_size * zcell + ms->res[0] * ycell + xcell;
+
+       val[0] = *cellptr;
+       val[1] = *(cellptr + 1);
+       val[2] = *(cellptr + 1 + ms->res[0]);
+       val[3] = *(cellptr + ms->res[0]);
+       cellptr += slice_size;
+       val[4] = *cellptr;
+       val[5] = *(cellptr + 1);
+       val[6] = *(cellptr + 1 + ms->res[0]);
+       val[7] = *(cellptr + ms->res[0]);
+       cellptr -= slice_size;
+
+       code = mc_bitcode(val, ms->thres);
+       if(ms->flags & MSURF_FLIP) {
                code = ~code & 0xff;
        }
-
        if(mc_edge_table[code] == 0) {
                return;
        }
 
+       /* calculate normals at the 8 corners */
+       for(i=0; i<8; i++) {
+               float *ptr = cellptr + offs[i][2] * slice_size + offs[i][1] * ms->res[0] + offs[i][0];
+
+               if(xcell < ms->res[0] - 1) {
+                       dfdx[i] = *(ptr + 1) - *ptr;
+               } else {
+                       dfdx[i] = *ptr - *(ptr - 1);
+               }
+               if(ycell < ms->res[1] - 1) {
+                       dfdy[i] = *(ptr + ms->res[0]) - *ptr;
+               } else {
+                       dfdy[i] = *ptr - *(ptr - ms->res[0]);
+               }
+               if(zcell < ms->res[2] - 1) {
+                       dfdz[i] = *(ptr + slice_size) - *ptr;
+               } else {
+                       dfdz[i] = *ptr - *(ptr - slice_size);
+               }
+       }
+
+       /* calculate the world-space position of each corner */
+       for(i=0; i<8; i++) {
+               pos[i][0] = cellpos[0] + cellsz[0] * offs[i][0];
+               pos[i][1] = cellpos[1] + cellsz[1] * offs[i][1];
+               pos[i][2] = cellpos[2] + cellsz[2] * offs[i][2];
+       }
+
+       /* generate up to a max of 12 vertices per cube. interpolate positions and normals for each one */
        for(i=0; i<12; i++) {
                if(mc_edge_table[code] & (1 << i)) {
+                       float nx, ny, nz;
                        int p0 = pidx[i][0];
                        int p1 = pidx[i][1];
 
@@ -297,29 +303,61 @@ static void process_cube(struct metasurface *ms, vec3 *pos, float *val)
                        vert[i][0] = pos[p0][0] + (pos[p1][0] - pos[p0][0]) * t;
                        vert[i][1] = pos[p0][1] + (pos[p1][1] - pos[p0][1]) * t;
                        vert[i][2] = pos[p0][2] + (pos[p1][2] - pos[p0][2]) * t;
+
+                       nx = dfdx[p0] + (dfdx[p1] - dfdx[p0]) * t;
+                       ny = dfdy[p0] + (dfdy[p1] - dfdy[p0]) * t;
+                       nz = dfdz[p0] + (dfdz[p1] - dfdz[p0]) * t;
+
+                       if(ms->flags & MSURF_FLIP) {
+                               nx = -nx;
+                               ny = -ny;
+                               nz = -nz;
+                       }
+
+                       if(ms->flags & MSURF_NORMALIZE) {
+                               float len = sqrt(nx * nx + ny * ny + nz * nz);
+                               if(len != 0.0) {
+                                       float s = 1.0f / len;
+                                       nx *= s;
+                                       ny *= s;
+                                       nz *= s;
+                               }
+                       }
+
+                       norm[i][0] = nx;
+                       norm[i][1] = ny;
+                       norm[i][2] = nz;
                }
        }
 
+       /* for each triangle of the cube add the appropriate vertices to the vertex buffer */
        for(i=0; mc_tri_table[code][i] != -1; i+=3) {
                for(j=0; j<3; j++) {
-                       float *v = vert[mc_tri_table[code][i + j]];
-
-                       if(ms->normal) {
-                               float dfdx, dfdy, dfdz;
-                               dfdx = ms->eval(ms, v[0] - ms->dx, v[1], v[2]) - ms->eval(ms, v[0] + ms->dx, v[1], v[2]);
-                               dfdy = ms->eval(ms, v[0], v[1] - ms->dy, v[2]) - ms->eval(ms, v[0], v[1] + ms->dy, v[2]);
-                               dfdz = ms->eval(ms, v[0], v[1], v[2] - ms->dz) - ms->eval(ms, v[0], v[1], v[2] + ms->dz);
-
-                               if(ms->flip) {
-                                       dfdx = -dfdx;
-                                       dfdy = -dfdy;
-                                       dfdz = -dfdz;
+                       int idx = mc_tri_table[code][i + j];
+                       float *v = vert[idx];
+                       float *n = norm[idx];
+
+                       /* TODO multithreadied polygon emit */
+                       if(ms->varr_size + 3 > ms->varr_alloc_size) {
+                               int newsz = ms->varr_alloc_size ? ms->varr_alloc_size * 2 : 1024;
+                               float *new_varr, *new_narr;
+
+                               if(!(new_varr = realloc(ms->varr, newsz * sizeof *new_varr)) ||
+                                               !(new_narr = realloc(ms->narr, newsz * sizeof *new_narr))) {
+                                       free(new_varr);
+                                       error_log("msurf_polygonize: failed to grow vertex buffers to %d elements\n", newsz);
+                                       return;
                                }
-                               ms->normal(ms, dfdx, dfdy, dfdz);
+                               ms->varr = new_varr;
+                               ms->narr = new_narr;
+                               ms->varr_alloc_size = newsz;
                        }
 
-                       /* TODO multithreadied polygon emmit */
-                       ms->vertex(ms, v[0], v[1], v[2]);
+                       for(k=0; k<3; k++) {
+                               ms->varr[ms->varr_size] = v[k];
+                               ms->narr[ms->varr_size] = n[k];
+                               ++ms->varr_size;
+                       }
                }
        }
 }
@@ -335,118 +373,3 @@ static unsigned int mc_bitcode(float *val, float thres)
        }
        return res;
 }
-#endif /* USE_MCUBES */
-
-
-/* ---- marching tetrahedra implementation (incomplete) ---- */
-#ifdef USE_MTETRA
-
-static unsigned int mt_bitcode(float v0, float v1, float v2, float v3, float thres);
-static void emmit(struct metasurface *ms, float v0, float v1, vec3 p0, vec3 p1, int rev)
-
-
-#define REVBIT(x)      ((x) & 8)
-#define INV(x)         (~(x) & 0xf)
-#define EDGE(a, b)     emmit(ms, val[idx[a]], val[idx[b]], pos[idx[a]], pos[idx[b]], REVBIT(code))
-static void process_tetra(struct metasurface *ms, int *idx, vec3 *pos, float *val)
-{
-       unsigned int code = mt_bitcode(val[idx[0]], val[idx[1]], val[idx[2]], val[idx[3]], ms->thres);
-
-       switch(code) {
-       case 1:
-       case INV(1):
-               EDGE(0, 1);
-               EDGE(0, 2);
-               EDGE(0, 3);
-               break;
-
-       case 2:
-       case INV(2):
-               EDGE(1, 0);
-               EDGE(1, 3);
-               EDGE(1, 2);
-               break;
-
-       case 3:
-       case INV(3):
-               EDGE(0, 3);
-               EDGE(0, 2);
-               EDGE(1, 3);
-
-               EDGE(1, 3);
-               EDGE(1, 2);
-               EDGE(0, 2);
-               break;
-
-       case 4:
-       case INV(4):
-               EDGE(2, 0);
-               EDGE(2, 1);
-               EDGE(2, 3);
-               break;
-
-       case 5:
-       case INV(5):
-               EDGE(0, 1);
-               EDGE(2, 3);
-               EDGE(0, 3);
-
-               EDGE(0, 1);
-               EDGE(1, 2);
-               EDGE(2, 3);
-               break;
-
-       case 6:
-       case INV(6):
-               EDGE(0, 1);
-               EDGE(1, 3);
-               EDGE(2, 3);
-
-               EDGE(0, 1);
-               EDGE(0, 2);
-               EDGE(2, 3);
-               break;
-
-       case 7:
-       case INV(7):
-               EDGE(3, 0);
-               EDGE(3, 2);
-               EDGE(3, 1);
-               break;
-
-       default:
-               break;  /* cases 0 and 15 */
-       }
-}
-
-#define BIT(i) ((v##i > thres) ? (1 << i) : 0)
-static unsigned int mt_bitcode(float v0, float v1, float v2, float v3, float thres)
-{
-       return BIT(0) | BIT(1) | BIT(2) | BIT(3);
-}
-
-static void emmit(struct metasurface *ms, float v0, float v1, vec3 p0, vec3 p1, int rev)
-{
-       int i;
-       float t = (ms->thres - v0) / (v1 - v0);
-
-       vec3 p;
-       for(i=0; i<3; i++) {
-               p[i] = p0[i] + (p1[i] - p0[i]) * t;
-       }
-       ms->vertex(ms, p[0], p[1], p[2]);
-
-       /*for(i=0; i<3; i++) {
-               ms->vbuf[ms->nverts][i] = p0[i] + (p1[i] - p0[i]) * t;
-       }
-
-       if(++ms->nverts >= 3) {
-               ms->nverts = 0;
-
-               for(i=0; i<3; i++) {
-                       int idx = rev ? (2 - i) : i;
-                       ms->vertex(ms, ms->vbuf[idx][0], ms->vbuf[idx][1], ms->vbuf[idx][2]);
-               }
-       }*/
-}
-#endif /* USE_MTETRA */
index 77d2920..3f7ed6e 100644 (file)
@@ -1,32 +1,13 @@
-/*
-metasurf - a library for implicit surface polygonization
-Copyright (C) 2011-2015  John Tsiombikas <nuclear@member.fsf.org>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-/* this is pulled from: https://github.com/jtsiomb/metasurf */
 #ifndef METASURF_H_
 #define METASURF_H_
 
 #define MSURF_GREATER  1
 #define MSURF_LESS             0
 
-struct metasurface;
+#define MSURF_FLIP                     1
+#define MSURF_NORMALIZE                2
 
-typedef float (*msurf_eval_func_t)(struct metasurface *ms, float, float, float);
-typedef void (*msurf_vertex_func_t)(struct metasurface *ms, float, float, float);
-typedef void (*msurf_normal_func_t)(struct metasurface *ms, float, float, float);
+struct metasurface;
 
 #ifdef __cplusplus
 extern "C" {
@@ -35,22 +16,14 @@ extern "C" {
 struct metasurface *msurf_create(void);
 void msurf_free(struct metasurface *ms);
 
-void msurf_set_user_data(struct metasurface *ms, void *udata);
-void *msurf_get_user_data(struct metasurface *ms);
+void msurf_enable(struct metasurface *ms, unsigned int opt);
+void msurf_disable(struct metasurface *ms, unsigned int opt);
+int msurf_is_enabled(struct metasurface *ms, unsigned int opt);
 
 /* which is inside above or below the threshold */
 void msurf_set_inside(struct metasurface *ms, int inside);
 int msurf_get_inside(struct metasurface *ms);
 
-/* set a scalar field evaluator function */
-void msurf_eval_func(struct metasurface *ms, msurf_eval_func_t func);
-
-/* set a generated vertex callback function */
-void msurf_vertex_func(struct metasurface *ms, msurf_vertex_func_t func);
-
-/* set a generated surface normal callback function (unused yet) */
-void msurf_normal_func(struct metasurface *ms, msurf_normal_func_t func);
-
 /* set the bounding box (default: -1, -1, -1, 1, 1, 1)
  * keep this as tight as possible to avoid wasting grid resolution
  */
@@ -67,10 +40,16 @@ void msurf_get_resolution(struct metasurface *ms, int *xres, int *yres, int *zre
 void msurf_set_threshold(struct metasurface *ms, float thres);
 float msurf_get_threshold(struct metasurface *ms);
 
+/* get pointer to the scalar field */
+float *msurf_voxels(struct metasurface *ms);
+float *msurf_slice(struct metasurface *ms, int idx);
 
 /* finally call this to perform the polygonization */
 int msurf_polygonize(struct metasurface *ms);
 
+int msurf_vertex_count(struct metasurface *ms);
+float *msurf_vertices(struct metasurface *ms);
+float *msurf_normals(struct metasurface *ms);
 
 #ifdef __cplusplus
 }
index d93c2ff..28f3700 100644 (file)
@@ -12,6 +12,11 @@ ExhibitManager::ExhibitManager()
 
 ExhibitManager::~ExhibitManager()
 {
+       clear();
+}
+
+void ExhibitManager::clear()
+{
        int num = (int)items.size();
        for(int i=0; i<num; i++) {
                delete items[i];
@@ -56,7 +61,8 @@ bool ExhibitManager::load(MetaScene *mscn, const char *fname)
 
                        const char *amatch = ts_get_attr_str(node, "match_node");
                        if(!amatch || !(snode = mscn->match_node(amatch))) {
-                               error_log("regexp \"%s\" didn't match any nodes\n", amatch ? amatch : "");
+                               error_log("ExhibitManager::load: regexp \"%s\" didn't match any nodes\n",
+                                               amatch ? amatch : "");
                                continue;
                        }
 
@@ -76,6 +82,16 @@ bool ExhibitManager::load(MetaScene *mscn, const char *fname)
        return true;
 }
 
+ExSelection ExhibitManager::select(const Ray &ray) const
+{
+       return ExSelection();   // TODO
+}
+
+ExSelection ExhibitManager::select(const Sphere &sph) const
+{
+       return ExSelection();   // TODO
+}
+
 void ExhibitManager::update(float dt)
 {
        int num = items.size();
@@ -84,11 +100,23 @@ void ExhibitManager::update(float dt)
        }
 }
 
+void ExhibitManager::draw() const
+{
+       int num = items.size();
+       for(int i=0; i<num; i++) {
+               items[i]->pre_draw();
+               items[i]->draw();
+               items[i]->post_draw();
+       }
+}
+
 static Exhibit *create_exhibit(const char *type)
 {
        if(strcmp(type, "static") == 0) {
+               debug_log("creating static exhibit\n");
                return new Exhibit;
        } else if(strcmp(type, "blobs") == 0) {
+               debug_log("creating blobs exhibit\n");
                return new BlobExhibit;
        }
        error_log("unknown exhibit type: %s\n", type);
index d91e374..4a72993 100644 (file)
@@ -13,6 +13,8 @@ public:
        ExhibitManager();
        ~ExhibitManager();
 
+       void clear();
+
        void add(Exhibit *ex);
        bool remove(Exhibit *ex);
 
@@ -22,6 +24,7 @@ public:
        ExSelection select(const Sphere &sph) const;
 
        void update(float dt = 0.0f);
+       void draw() const;
 };
 
 #endif // EXMAN_H_
index 012847c..b439286 100644 (file)
@@ -203,11 +203,10 @@ static SceneNode *find_node_rec(SceneNode *tree, const std::regex &re)
        if(std::regex_match(tree->get_name(), re)) {
                return tree;
        }
-       debug_log("no match: \"%s\"\n", tree->get_name());
 
        int num = tree->get_num_children();
        for(int i=0; i<num; i++) {
-               SceneNode *n = find_node_rec(tree, re);
+               SceneNode *n = find_node_rec(tree->get_child(i), re);
                if(n) return n;
        }
        return 0;