fixed div/zero in blob exhibit
[laserbrain_demo] / src / blob_exhibit.cc
1 #include "blob_exhibit.h"
2 #include "blobs/metasurf.h"
3 #include "app.h"
4 #include <imago2.h>
5
6 struct Metaball {
7         Vec3 pos;
8         float energy;
9         Vec3 path_scale, path_offset;
10         float phase_offset, speed;
11 };
12 #define NUM_MBALLS      8
13
14 static Metaball def_mball_data[] = {
15         {Vec3(0, 0, 0), 2.18038,  Vec3(1.09157, 1.69766, 1),   Vec3(0.622818, 0.905624, 0), 1.24125, 0.835223},
16         {Vec3(0, 0, 0), 2.03646,  Vec3(0.916662, 1.2161, 1),   Vec3(0.118734, 0.283516, 0), 2.29201, 1.0134},
17         {Vec3(0, 0, 0), 2.40446,  Vec3(1.87429, 1.57595, 1),   Vec3(0.298566, -0.788474, 0), 3.8137, 0.516301},
18         {Vec3(0, 0, 0), 0.985774, Vec3(0.705847, 0.735019, 1), Vec3(0.669189, -0.217922, 0), 0.815497, 0.608809},
19         {Vec3(0, 0, 0), 2.49785,  Vec3(0.827385, 1.75867, 1),  Vec3(0.0284513, 0.247808, 0), 1.86002, 1.13755},
20         {Vec3(0, 0, 0), 1.54857,  Vec3(1.24037, 0.938775, 1),  Vec3(1.04011, 0.596987, 0), 3.30964, 1.26991},
21         {Vec3(0, 0, 0), 1.30046,  Vec3(1.83729, 1.02869, 1),   Vec3(-0.476708, 0.676994, 0), 5.77441, 0.569755},
22         {Vec3(0, 0, 0), 2.39865,  Vec3(1.28899, 0.788321, 1),  Vec3(-0.910677, 0.359099, 0), 5.5935, 0.848893}
23 };
24
25 struct BlobPriv {
26         AABox vol;
27         metasurface *msurf;
28         Metaball mballs[NUM_MBALLS];
29         Texture *tex;
30 };
31
32 BlobExhibit::BlobExhibit()
33 {
34         priv = new BlobPriv;
35         for(int i=0; i<NUM_MBALLS; i++) {
36                 priv->mballs[i] = def_mball_data[i];
37         }
38         priv->vol = AABox(Vec3(-3.5, -3.5, -3.5), Vec3(3.5, 3.5, 3.5));
39 }
40
41 BlobExhibit::~BlobExhibit()
42 {
43         destroy();
44         delete priv;
45 }
46
47 bool BlobExhibit::init()
48 {
49         if(!(priv->msurf = msurf_create())) {
50                 return false;
51         }
52         msurf_set_threshold(priv->msurf, 8);
53         msurf_set_inside(priv->msurf, MSURF_GREATER);
54         msurf_set_bounds(priv->msurf, priv->vol.min.x, priv->vol.min.y, priv->vol.min.z,
55                         priv->vol.max.x, priv->vol.max.y, priv->vol.max.z);
56         msurf_enable(priv->msurf, MSURF_NORMALIZE);
57
58         priv->tex = texman.get_texture("data/sphmap.jpg");
59
60         return true;
61 }
62
63 void BlobExhibit::destroy()
64 {
65         if(priv->msurf) {
66                 msurf_free(priv->msurf);
67                 priv->msurf = 0;
68         }
69 }
70
71 void BlobExhibit::update(float dt)
72 {
73         double sec = time_msec / 1000.0;
74
75         float xmin, xmax, ymin, ymax, zmin, zmax;
76         int xres, yres, zres;
77
78         if(!msurf_voxels(priv->msurf)) {
79                 return;
80         }
81
82         msurf_get_bounds(priv->msurf, &xmin, &ymin, &zmin, &xmax, &ymax, &zmax);
83         msurf_get_resolution(priv->msurf, &xres, &yres, &zres);
84
85         float xstep = (xmax - xmin) / xres;
86         float ystep = (ymax - ymin) / yres;
87         float zstep = (zmax - zmin) / zres;
88
89         for(int i=0; i<NUM_MBALLS; i++) {
90                 float t = fmod(sec * priv->mballs[i].speed + priv->mballs[i].phase_offset, M_PI * 2.0);
91                 priv->mballs[i].pos.x = cos(t) * priv->mballs[i].path_scale.x + priv->mballs[i].path_offset.x;
92                 priv->mballs[i].pos.y = sin(t) * priv->mballs[i].path_scale.y + priv->mballs[i].path_offset.y;
93                 priv->mballs[i].pos.z = -cos(t) * priv->mballs[i].path_scale.z + priv->mballs[i].path_offset.z;
94         }
95
96         float max_energy = 0.0f;
97
98 #pragma omp parallel for
99         for(int i=0; i<zres; i++) {
100                 float z = zmin + i * zstep;
101                 float *voxptr = msurf_slice(priv->msurf, i);
102
103                 for(int j=0; j<yres; j++) {
104                         float y = ymin + j * ystep;
105
106                         for(int k=0; k<xres; k++) {
107                                 float x = xmin + k * xstep;
108
109                                 float sum = 0.0f;
110                                 for(int n=0; n<NUM_MBALLS; n++) {
111                                         float dx = x - priv->mballs[n].pos.x;
112                                         float dy = y - priv->mballs[n].pos.y;
113                                         float dz = z - priv->mballs[n].pos.z;
114                                         float dsq = dx * dx + dy * dy + dz * dz;
115
116                                         sum += priv->mballs[n].energy / dsq;
117                                 }
118                                 *voxptr++ = sum;
119                                 if(sum > max_energy) max_energy = sum;
120                         }
121                 }
122         }
123
124         msurf_polygonize(priv->msurf);
125 }
126
127 void BlobExhibit::draw() const
128 {
129         glPushAttrib(GL_ENABLE_BIT);
130
131         glUseProgram(0);
132
133         glDisable(GL_LIGHTING);
134         glEnable(GL_TEXTURE_2D);
135         glEnable(GL_NORMALIZE);
136         priv->tex->bind();
137
138         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
139         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
140         glEnable(GL_TEXTURE_GEN_S);
141         glEnable(GL_TEXTURE_GEN_T);
142
143         glMatrixMode(GL_TEXTURE);
144         glLoadIdentity();
145         glScalef(1, -1, 1);
146
147         int nverts = msurf_vertex_count(priv->msurf);
148         float *varr = msurf_vertices(priv->msurf);
149         float *narr = msurf_normals(priv->msurf);
150
151         glColor3f(1, 1, 1);
152
153         glBindBuffer(GL_ARRAY_BUFFER, 0);
154         glEnableClientState(GL_VERTEX_ARRAY);
155         glEnableClientState(GL_NORMAL_ARRAY);
156         glVertexPointer(3, GL_FLOAT, 0, varr);
157         glNormalPointer(GL_FLOAT, 0, narr);
158
159         glDrawArrays(GL_TRIANGLES, 0, nverts);
160
161         glDisableClientState(GL_VERTEX_ARRAY);
162         glDisableClientState(GL_NORMAL_ARRAY);
163
164         /*
165         glDisable(GL_TEXTURE_2D);
166         glDisable(GL_LIGHTING);
167
168         varr = msurf_vertices(priv->msurf);
169         narr = msurf_normals(priv->msurf);
170
171         glBegin(GL_LINES);
172         glColor3f(0, 1, 0);
173
174         float nscale = 0.2;
175         for(int i=0; i<nverts; i++) {
176                 glVertex3f(varr[0], varr[1], varr[2]);
177                 glVertex3f(varr[0] + narr[0] * nscale, varr[1] + narr[1] * nscale, varr[2] + narr[2] * nscale);
178                 varr += 3;
179                 narr += 3;
180         }
181         glEnd();
182         */
183
184         glLoadIdentity();
185         glMatrixMode(GL_MODELVIEW);
186
187         glPopAttrib();
188 }
189
190 const AABox &BlobExhibit::get_aabox() const
191 {
192         Box box = Box(priv->vol, node->get_matrix());
193         calc_bounding_aabox(&aabb, &box);
194         return aabb;
195 }