added a non-interactive blobs exhibit
authorJohn Tsiombikas <nuclear@mutantstargoat.com>
Tue, 6 Dec 2016 04:19:25 +0000 (06:19 +0200)
committerJohn Tsiombikas <nuclear@mutantstargoat.com>
Tue, 6 Dec 2016 04:19:25 +0000 (06:19 +0200)
Makefile
src/app.cc
src/blob_exhibit.cc [new file with mode: 0644]
src/blob_exhibit.h [new file with mode: 0644]
src/blobs/mcubes.h [new file with mode: 0644]
src/blobs/metasurf.c [new file with mode: 0644]
src/blobs/metasurf.h [new file with mode: 0644]
src/exhibit.cc [new file with mode: 0644]
src/exhibit.h
src/ui.cc
src/ui.h

index 71a41d1..431e362 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,10 @@
-src = $(wildcard src/*.cc) $(wildcard src/machine/*.cc)
-csrc = $(wildcard src/*.c) $(wildcard src/machine/*.c)
+src = $(wildcard src/*.cc) $(wildcard src/machine/*.cc) $(wildcard src/blobs/*.cc)
+csrc = $(wildcard src/*.c) $(wildcard src/machine/*.c) $(wildcard src/blobs/*.c)
 obj = $(src:.cc=.o) $(csrc:.c=.o)
 dep = $(obj:.o=.d)
 bin = demo
 
-opt = -O0
+opt = -O3 -ffast-math
 dbg = -g
 
 incpath = -Isrc -Isrc/machine -I/usr/local/include `pkg-config --cflags sdl2`
index 665ded4..ca750fa 100644 (file)
 #include "ui.h"
 #include "opt.h"
 #include "post.h"
+#include "blob_exhibit.h"
 
 #define NEAR_CLIP      5.0
 #define FAR_CLIP       10000.0
 
 static void draw_scene();
 static void toggle_flight();
+static void calc_framerate();
 
 long time_msec;
 int win_width, win_height;
@@ -50,12 +52,17 @@ static bool gpad_bnstate[64];
 static Vec2 joy_move, joy_look;
 static float joy_deadzone = 0.01;
 
+static float framerate;
+
 static Mat4 view_matrix, mouse_view_matrix, proj_matrix;
 static MetaScene *mscn;
 static unsigned int sdr_post_gamma;
 
 static long prev_msec;
 
+static BlobExhibit *blobs;
+static bool show_blobs;
+
 
 bool app_init(int argc, char **argv)
 {
@@ -109,6 +116,13 @@ bool app_init(int argc, char **argv)
        dir.y = 0;
        cam_theta = rad_to_deg(acos(dot(dir, Vec3(0, 0, 1))));
 
+       blobs = new BlobExhibit;
+       blobs->node = new SceneNode;
+       blobs->init();
+       blobs->node->set_position(Vec3(-250, 150, 250));
+       blobs->node->set_scaling(Vec3(20, 20, 20));
+       blobs->node->update(0);
+
        if(!(sdr_ltmap_notex = create_program_load("sdr/lightmap.v.glsl", "sdr/lightmap-notex.p.glsl"))) {
                return false;
        }
@@ -138,6 +152,10 @@ void app_cleanup()
                goatvr_shutdown();
        }
 
+       blobs->destroy();
+       delete blobs->node;
+       delete blobs;
+
        texman.clear();
        sceneman.clear();
 }
@@ -166,6 +184,9 @@ static void update(float dt)
        sceneman.update();
 
        mscn->update(dt);
+       if(show_blobs) {
+               blobs->update(dt);
+       }
 
        float speed = walk_speed * dt;
        Vec3 dir;
@@ -319,6 +340,8 @@ void app_display()
                app_swap_buffers();
        }
        assert(glGetError() == GL_NO_ERROR);
+
+       calc_framerate();
 }
 
 
@@ -330,6 +353,9 @@ static void draw_scene()
        set_light(2, lpos[2], Vec3(0.8, 1.0, 0.8) * 0.3);
 
        mscn->draw();
+       if(show_blobs) {
+               blobs->draw();
+       }
 
        if(show_walk_mesh && mscn->walk_mesh) {
                glPushAttrib(GL_ENABLE_BIT);
@@ -351,6 +377,7 @@ static void draw_scene()
                glPopAttrib();
        }
 
+       print_text(Vec2(9 * win_width / 10, 20), Vec3(1, 1, 0), "fps: %.1f", framerate);
        draw_ui();
 }
 
@@ -427,6 +454,11 @@ void app_keyboard(int key, bool pressed)
                        mouse_speed *= 0.8;
                        show_message("mouse speed: %g", mouse_speed);
                        break;
+
+               case 'b':
+                       show_blobs = !show_blobs;
+                       show_message("blobs: %s\n", show_blobs ? "on" : "off");
+                       break;
                }
        }
 
@@ -513,6 +545,11 @@ void app_gamepad_button(int bn, bool pressed)
                        toggle_flight();
                        break;
 
+               case GPAD_X:
+                       show_blobs = !show_blobs;
+                       show_message("blobs: %s\n", show_blobs ? "on" : "off");
+                       break;
+
                default:
                        break;
                }
@@ -534,3 +571,18 @@ static void toggle_flight()
                show_message("walk mode\n");
        }
 }
+
+static void calc_framerate()
+{
+       static int nframes;
+       static long prev_upd;
+
+       long elapsed = time_msec - prev_upd;
+       if(elapsed >= 1000) {
+               framerate = (float)nframes / (float)(elapsed * 0.001);
+               nframes = 1;
+               prev_upd = time_msec;
+       } else {
+               ++nframes;
+       }
+}
diff --git a/src/blob_exhibit.cc b/src/blob_exhibit.cc
new file mode 100644 (file)
index 0000000..1dcc80e
--- /dev/null
@@ -0,0 +1,137 @@
+#include "blob_exhibit.h"
+#include "blobs/metasurf.h"
+#include "app.h"
+
+struct Metaball {
+       Vec3 pos;
+       float energy;
+       Vec3 path_scale, path_offset;
+       float phase_offset, speed;
+};
+#define NUM_MBALLS     8
+
+static Metaball def_mball_data[] = {
+       {Vec3(0, 0, 0), 2.18038,  Vec3(1.09157, 1.69766, 1),   Vec3(0.622818, 0.905624, 0), 1.24125, 0.835223},
+       {Vec3(0, 0, 0), 2.03646,  Vec3(0.916662, 1.2161, 1),   Vec3(0.118734, 0.283516, 0), 2.29201, 1.0134},
+       {Vec3(0, 0, 0), 2.40446,  Vec3(1.87429, 1.57595, 1),   Vec3(0.298566, -0.788474, 0), 3.8137, 0.516301},
+       {Vec3(0, 0, 0), 0.985774, Vec3(0.705847, 0.735019, 1), Vec3(0.669189, -0.217922, 0), 0.815497, 0.608809},
+       {Vec3(0, 0, 0), 2.49785,  Vec3(0.827385, 1.75867, 1),  Vec3(0.0284513, 0.247808, 0), 1.86002, 1.13755},
+       {Vec3(0, 0, 0), 1.54857,  Vec3(1.24037, 0.938775, 1),  Vec3(1.04011, 0.596987, 0), 3.30964, 1.26991},
+       {Vec3(0, 0, 0), 1.30046,  Vec3(1.83729, 1.02869, 1),   Vec3(-0.476708, 0.676994, 0), 5.77441, 0.569755},
+       {Vec3(0, 0, 0), 2.39865,  Vec3(1.28899, 0.788321, 1),  Vec3(-0.910677, 0.359099, 0), 5.5935, 0.848893}
+};
+
+struct BlobPriv {
+       metasurface *msurf;
+       Metaball mballs[NUM_MBALLS];
+       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;
+       for(int i=0; i<NUM_MBALLS; i++) {
+               priv->mballs[i] = def_mball_data[i];
+       }
+}
+
+BlobExhibit::~BlobExhibit()
+{
+       delete priv;
+}
+
+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);
+
+       priv->tex = texman.get_texture("data/sphmap.jpg");
+       return true;
+}
+
+void BlobExhibit::destroy()
+{
+       msurf_free(priv->msurf);
+       priv->msurf = 0;
+}
+
+void BlobExhibit::update(float dt)
+{
+       double sec = time_msec / 1000.0;
+
+       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;
+       }
+}
+
+void BlobExhibit::draw() const
+{
+       pre_draw();
+
+       glPushAttrib(GL_ENABLE_BIT);
+
+       glUseProgram(0);
+
+       glDisable(GL_LIGHTING);
+       glEnable(GL_TEXTURE_2D);
+       priv->tex->bind();
+
+       glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+       glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+       glEnable(GL_TEXTURE_GEN_S);
+       glEnable(GL_TEXTURE_GEN_T);
+
+       glFrontFace(GL_CW);
+       glBegin(GL_TRIANGLES);
+       glColor3f(1, 1, 1);
+       msurf_polygonize(priv->msurf);
+       glEnd();
+       glFrontFace(GL_CCW);
+
+       glPopAttrib();
+
+       post_draw();
+}
+
+static void vertex(struct metasurface *ms, float x, float y, float z)
+{
+       static const float delta = 0.01;
+
+       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;
+
+       glNormal3f(dfdx, dfdy, dfdz);
+       glVertex3f(x, y, z);
+}
+
+static float eval(struct metasurface *ms, float x, float y, float z)
+{
+       float sum = 0.0f;
+       BlobPriv *priv = (BlobPriv*)msurf_get_user_data(ms);
+
+       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;
+
+               sum += priv->mballs[i].energy / dsq;
+       }
+       return sum;
+}
diff --git a/src/blob_exhibit.h b/src/blob_exhibit.h
new file mode 100644 (file)
index 0000000..001047a
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef BLOB_EXHIBIT_H_
+#define BLOB_EXHIBIT_H_
+
+#include "exhibit.h"
+
+struct BlobPriv;
+
+class BlobExhibit : public Exhibit {
+private:
+       BlobPriv *priv;
+
+public:
+       BlobExhibit();
+       ~BlobExhibit();
+
+       bool init();
+       void destroy();
+
+       void update(float dt);
+       void draw() const;
+};
+
+#endif // BLOB_EXHIBIT_H_
diff --git a/src/blobs/mcubes.h b/src/blobs/mcubes.h
new file mode 100644 (file)
index 0000000..2a9034d
--- /dev/null
@@ -0,0 +1,294 @@
+static int mc_edge_table[256] = {
+       0x0  , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
+       0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
+       0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
+       0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
+       0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
+       0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
+       0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
+       0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
+       0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
+       0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
+       0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
+       0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
+       0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
+       0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
+       0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
+       0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
+       0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
+       0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
+       0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
+       0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
+       0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
+       0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
+       0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
+       0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
+       0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
+       0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
+       0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
+       0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
+       0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
+       0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
+       0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
+       0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0
+};
+
+
+static int mc_tri_table[256][16] = {
+       {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1},
+       {3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1},
+       {3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1},
+       {3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1},
+       {9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1},
+       {9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
+       {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1},
+       {8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1},
+       {9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
+       {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1},
+       {3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1},
+       {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1},
+       {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1},
+       {4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1},
+       {9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
+       {5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1},
+       {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1},
+       {9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
+       {0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
+       {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1},
+       {10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1},
+       {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1},
+       {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1},
+       {5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1},
+       {9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1},
+       {0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1},
+       {1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1},
+       {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1},
+       {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1},
+       {2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
+       {7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1},
+       {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1},
+       {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1},
+       {11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1},
+       {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1},
+       {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1},
+       {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1},
+       {11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
+       {1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1},
+       {9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1},
+       {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1},
+       {2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
+       {0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
+       {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1},
+       {6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1},
+       {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1},
+       {6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1},
+       {5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1},
+       {1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
+       {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1},
+       {6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1},
+       {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1},
+       {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1},
+       {3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
+       {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1},
+       {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1},
+       {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1},
+       {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1},
+       {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1},
+       {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1},
+       {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1},
+       {10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1},
+       {10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1},
+       {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1},
+       {1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1},
+       {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1},
+       {0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1},
+       {10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1},
+       {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1},
+       {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1},
+       {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1},
+       {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1},
+       {3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1},
+       {6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1},
+       {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1},
+       {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1},
+       {10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1},
+       {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1},
+       {7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1},
+       {7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1},
+       {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1},
+       {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1},
+       {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1},
+       {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1},
+       {0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1},
+       {7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
+       {10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
+       {2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
+       {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1},
+       {7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1},
+       {2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1},
+       {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1},
+       {10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1},
+       {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1},
+       {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1},
+       {7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1},
+       {6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1},
+       {8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1},
+       {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1},
+       {6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1},
+       {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1},
+       {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1},
+       {8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1},
+       {0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1},
+       {1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
+       {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1},
+       {10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1},
+       {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1},
+       {10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
+       {5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
+       {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1},
+       {9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
+       {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1},
+       {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1},
+       {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1},
+       {7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1},
+       {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1},
+       {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1},
+       {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1},
+       {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1},
+       {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1},
+       {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1},
+       {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1},
+       {6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1},
+       {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1},
+       {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1},
+       {6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1},
+       {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1},
+       {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1},
+       {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1},
+       {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1},
+       {9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1},
+       {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1},
+       {1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1},
+       {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1},
+       {0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1},
+       {5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1},
+       {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1},
+       {11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1},
+       {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1},
+       {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1},
+       {2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1},
+       {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1},
+       {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1},
+       {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1},
+       {1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1},
+       {9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1},
+       {9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1},
+       {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1},
+       {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1},
+       {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1},
+       {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1},
+       {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1},
+       {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1},
+       {9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1},
+       {5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1},
+       {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1},
+       {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1},
+       {8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1},
+       {9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1},
+       {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1},
+       {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1},
+       {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1},
+       {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1},
+       {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1},
+       {11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1},
+       {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1},
+       {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1},
+       {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1},
+       {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1},
+       {1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1},
+       {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1},
+       {4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1},
+       {0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1},
+       {3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1},
+       {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1},
+       {0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1},
+       {9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1},
+       {1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+       {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}
+};
diff --git a/src/blobs/metasurf.c b/src/blobs/metasurf.c
new file mode 100644 (file)
index 0000000..2207b3d
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+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 "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
+
+typedef float vec3[3];
+
+struct metasurface {
+       vec3 min, max;
+       int res[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;
+
+       vec3 vbuf[3];
+       int nverts;
+};
+
+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
+
+
+struct metasurface *msurf_create(void)
+{
+       struct metasurface *ms;
+
+       if(!(ms = malloc(sizeof *ms))) {
+               return 0;
+       }
+       if(msurf_init(ms) == -1) {
+               free(ms);
+       }
+       return ms;
+}
+
+void msurf_free(struct metasurface *ms)
+{
+       free(ms);
+}
+
+static int msurf_init(struct metasurface *ms)
+{
+       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->dx = ms->dy = ms->dz = 0.001;
+       ms->flip = 0;
+
+       return 0;
+}
+
+void msurf_set_user_data(struct metasurface *ms, void *udata)
+{
+       ms->udata = udata;
+}
+
+void *msurf_get_user_data(struct metasurface *ms)
+{
+       return ms->udata;
+}
+
+void msurf_set_inside(struct metasurface *ms, int inside)
+{
+       switch(inside) {
+       case MSURF_GREATER:
+               ms->flip = 0;
+               break;
+
+       case MSURF_LESS:
+               ms->flip = 1;
+               break;
+
+       default:
+               fprintf(stderr, "msurf_inside expects MSURF_GREATER or MSURF_LESS\n");
+       }
+}
+
+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;
+}
+
+void msurf_set_bounds(struct metasurface *ms, float xmin, float ymin, float zmin, float xmax, float ymax, float zmax)
+{
+       ms->min[0] = xmin;
+       ms->min[1] = ymin;
+       ms->min[2] = zmin;
+       ms->max[0] = xmax;
+       ms->max[1] = ymax;
+       ms->max[2] = zmax;
+}
+
+void msurf_get_bounds(struct metasurface *ms, float *xmin, float *ymin, float *zmin, float *xmax, float *ymax, float *zmax)
+{
+       *xmin = ms->min[0];
+       *ymin = ms->min[1];
+       *zmin = ms->min[2];
+       *xmax = ms->max[0];
+       *ymax = ms->max[1];
+       *zmax = ms->max[2];
+}
+
+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;
+}
+
+void msurf_get_resolution(struct metasurface *ms, int *xres, int *yres, int *zres)
+{
+       *xres = ms->res[0];
+       *yres = ms->res[1];
+       *zres = ms->res[2];
+}
+
+void msurf_set_threshold(struct metasurface *ms, float thres)
+{
+       ms->thres = thres;
+}
+
+float msurf_get_threshold(struct metasurface *ms)
+{
+       return ms->thres;
+}
+
+
+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;
+       }
+
+       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[2] += delta[2];
+                       }
+                       pos[1] += delta[1];
+               }
+               pos[0] += delta[0];
+       }
+       return 0;
+}
+
+
+static void process_cell(struct metasurface *ms, vec3 pos, vec3 sz)
+{
+       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
+}
+
+
+/* ---- marching cubes implementation ---- */
+#ifdef USE_MCUBES
+
+static unsigned int mc_bitcode(float *val, float thres);
+
+static void process_cube(struct metasurface *ms, vec3 *pos, float *val)
+{
+       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) {
+               code = ~code & 0xff;
+       }
+
+       if(mc_edge_table[code] == 0) {
+               return;
+       }
+
+       for(i=0; i<12; i++) {
+               if(mc_edge_table[code] & (1 << i)) {
+                       int p0 = pidx[i][0];
+                       int p1 = pidx[i][1];
+
+                       float t = (ms->thres - val[p0]) / (val[p1] - val[p0]);
+                       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;
+               }
+       }
+
+       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;
+                               }
+                               ms->normal(ms, dfdx, dfdy, dfdz);
+                       }
+
+                       /* TODO multithreadied polygon emmit */
+                       ms->vertex(ms, v[0], v[1], v[2]);
+               }
+       }
+}
+
+static unsigned int mc_bitcode(float *val, float thres)
+{
+       unsigned int i, res = 0;
+
+       for(i=0; i<8; i++) {
+               if(val[i] > thres) {
+                       res |= 1 << i;
+               }
+       }
+       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 */
diff --git a/src/blobs/metasurf.h b/src/blobs/metasurf.h
new file mode 100644 (file)
index 0000000..77d2920
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+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;
+
+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);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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);
+
+/* 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
+ */
+void msurf_set_bounds(struct metasurface *ms, float xmin, float ymin, float zmin, float xmax, float ymax, float zmax);
+void msurf_get_bounds(struct metasurface *ms, float *xmin, float *ymin, float *zmin, float *xmax, float *ymax, float *zmax);
+
+/* resolution of the 3D evaluation grid, the bigger, the better, the slower
+ * (default: 40, 40, 40)
+ */
+void msurf_set_resolution(struct metasurface *ms, int xres, int yres, int zres);
+void msurf_get_resolution(struct metasurface *ms, int *xres, int *yres, int *zres);
+
+/* isosurface threshold value (default: 0) */
+void msurf_set_threshold(struct metasurface *ms, float thres);
+float msurf_get_threshold(struct metasurface *ms);
+
+
+/* finally call this to perform the polygonization */
+int msurf_polygonize(struct metasurface *ms);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* METASURF_H_ */
diff --git a/src/exhibit.cc b/src/exhibit.cc
new file mode 100644 (file)
index 0000000..8653343
--- /dev/null
@@ -0,0 +1,41 @@
+#include "exhibit.h"
+#include "snode.h"
+
+Exhibit::Exhibit()
+{
+}
+
+void *Exhibit::select(const Ray &ray) const
+{
+       return 0;       // TODO
+}
+
+void *Exhibit::select(const Sphere &sph) const
+{
+       return 0;       // TODO
+}
+
+void Exhibit::update(float dt)
+{
+}
+
+void Exhibit::pre_draw() const
+{
+       if(node) {
+               glMatrixMode(GL_MODELVIEW);
+               glPushMatrix();
+               glMultMatrixf(node->get_matrix()[0]);
+       }
+}
+
+void Exhibit::draw() const
+{
+}
+
+void Exhibit::post_draw() const
+{
+       if(node) {
+               glMatrixMode(GL_MODELVIEW);
+               glPopMatrix();
+       }
+}
index c607fdb..c4c0ec9 100644 (file)
@@ -23,7 +23,10 @@ public:
        virtual void *select(const Sphere &sph) const;
 
        virtual void update(float dt = 0.0f);
+
+       virtual void pre_draw() const;
        virtual void draw() const;
+       virtual void post_draw() const;
 };
 
 #endif // EXHIBIT_H_
index 1a18324..a0babe4 100644 (file)
--- a/src/ui.cc
+++ b/src/ui.cc
@@ -19,6 +19,14 @@ struct Message {
 };
 static Message *msglist;
 
+struct Text {
+       char *str;
+       Vec2 pos;
+       Vec3 color;
+       Text *next;
+};
+static Text *txlist;
+
 static long timeout = 2000;
 static long trans_time = 250;
 static dtx_font *font;
@@ -71,6 +79,33 @@ void show_messagev(long timeout, const Vec3 &color, const char *fmt, va_list ap)
        msglist = dummy.next;
 }
 
+void print_text(const Vec2 &pos, const Vec3 &color, const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       print_textv(pos, color, fmt, ap);
+       va_end(ap);
+}
+
+void print_textv(const Vec2 &pos, const Vec3 &color, const char *fmt, va_list ap)
+{
+       char buf[512];
+
+       init();
+
+       vsnprintf(buf, sizeof buf, fmt, ap);
+
+       Text *tx = new Text;
+       int len = strlen(buf);
+       tx->str = new char[len + 1];
+       memcpy(tx->str, buf, len + 1);
+       tx->color = color;
+       tx->pos = Vec2(pos.x, -pos.y);
+
+       tx->next = txlist;
+       txlist = tx;
+}
+
 void draw_ui()
 {
        if(!font) return;
@@ -111,6 +146,21 @@ void draw_ui()
                msg = msg->next;
        }
 
+       while(txlist) {
+               Text *tx = txlist;
+               txlist = txlist->next;
+
+               glMatrixMode(GL_MODELVIEW);
+               glLoadIdentity();
+               glTranslatef(tx->pos.x, tx->pos.y, 0);
+
+               glColor3f(tx->color.x, tx->color.y, tx->color.z);
+               dtx_string(tx->str);
+
+               delete [] tx->str;
+               delete tx;
+       }
+
        glPopAttrib();
 
        glMatrixMode(GL_PROJECTION);
index dbd693d..088fb82 100644 (file)
--- a/src/ui.h
+++ b/src/ui.h
@@ -9,6 +9,9 @@ void show_message(const char *fmt, ...);
 void show_message(long timeout, const Vec3 &color, const char *fmt, ...);
 void show_messagev(long timeout, const Vec3 &color, const char *fmt, va_list ap);
 
+void print_text(const Vec2 &pos, const Vec3 &color, const char *fmt, ...);
+void print_textv(const Vec2 &pos, const Vec3 &color, const char *fmt, va_list ap);
+
 void draw_ui();
 
 #endif // UI_H_