fixed div/zero in blob exhibit
[laserbrain_demo] / src / blob_exhibit.cc
index 1dcc80e..c92ac7a 100644 (file)
@@ -1,6 +1,7 @@
 #include "blob_exhibit.h"
 #include "blobs/metasurf.h"
 #include "app.h"
+#include <imago2.h>
 
 struct Metaball {
        Vec3 pos;
@@ -22,25 +23,24 @@ static Metaball def_mball_data[] = {
 };
 
 struct BlobPriv {
+       AABox vol;
        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];
        }
+       priv->vol = AABox(Vec3(-3.5, -3.5, -3.5), Vec3(3.5, 3.5, 3.5));
 }
 
 BlobExhibit::~BlobExhibit()
 {
+       destroy();
        delete priv;
 }
 
@@ -49,45 +49,90 @@ 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_set_bounds(priv->msurf, priv->vol.min.x, priv->vol.min.y, priv->vol.min.z,
+                       priv->vol.max.x, priv->vol.max.y, priv->vol.max.z);
+       msurf_enable(priv->msurf, MSURF_NORMALIZE);
 
        priv->tex = texman.get_texture("data/sphmap.jpg");
+
        return true;
 }
 
 void BlobExhibit::destroy()
 {
-       msurf_free(priv->msurf);
-       priv->msurf = 0;
+       if(priv->msurf) {
+               msurf_free(priv->msurf);
+               priv->msurf = 0;
+       }
 }
 
 void BlobExhibit::update(float dt)
 {
        double sec = time_msec / 1000.0;
 
+       float xmin, xmax, ymin, ymax, zmin, zmax;
+       int xres, yres, zres;
+
+       if(!msurf_voxels(priv->msurf)) {
+               return;
+       }
+
+       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;
        }
+
+       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);
+
+               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);
@@ -95,43 +140,56 @@ void BlobExhibit::draw() const
        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);
+       glMatrixMode(GL_TEXTURE);
+       glLoadIdentity();
+       glScalef(1, -1, 1);
 
-       glPopAttrib();
+       int nverts = msurf_vertex_count(priv->msurf);
+       float *varr = msurf_vertices(priv->msurf);
+       float *narr = msurf_normals(priv->msurf);
 
-       post_draw();
-}
+       glColor3f(1, 1, 1);
 
-static void vertex(struct metasurface *ms, float x, float y, float z)
-{
-       static const float delta = 0.01;
+       glBindBuffer(GL_ARRAY_BUFFER, 0);
+       glEnableClientState(GL_VERTEX_ARRAY);
+       glEnableClientState(GL_NORMAL_ARRAY);
+       glVertexPointer(3, GL_FLOAT, 0, varr);
+       glNormalPointer(GL_FLOAT, 0, narr);
 
-       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;
+       glDrawArrays(GL_TRIANGLES, 0, nverts);
 
-       glNormal3f(dfdx, dfdy, dfdz);
-       glVertex3f(x, y, z);
-}
+       glDisableClientState(GL_VERTEX_ARRAY);
+       glDisableClientState(GL_NORMAL_ARRAY);
 
-static float eval(struct metasurface *ms, float x, float y, float z)
-{
-       float sum = 0.0f;
-       BlobPriv *priv = (BlobPriv*)msurf_get_user_data(ms);
+       /*
+       glDisable(GL_TEXTURE_2D);
+       glDisable(GL_LIGHTING);
 
-       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;
+       varr = msurf_vertices(priv->msurf);
+       narr = msurf_normals(priv->msurf);
+
+       glBegin(GL_LINES);
+       glColor3f(0, 1, 0);
 
-               sum += priv->mballs[i].energy / dsq;
+       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;
        }
-       return sum;
+       glEnd();
+       */
+
+       glLoadIdentity();
+       glMatrixMode(GL_MODELVIEW);
+
+       glPopAttrib();
+}
+
+const AABox &BlobExhibit::get_aabox() const
+{
+       Box box = Box(priv->vol, node->get_matrix());
+       calc_bounding_aabox(&aabb, &box);
+       return aabb;
 }