metaballs effect
[dosdemo] / src / metasurf.c
1 /*
2 metasurf - a library for implicit surface polygonization
3 Copyright (C) 2011-2015  John Tsiombikas <nuclear@member.fsf.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include "metasurf.h"
21 #include "mcubes.h"
22
23 #undef USE_MTETRA
24 #define USE_MCUBES
25
26 #if (defined(USE_MTETRA) && defined(USE_MCUBES)) || (!defined(USE_MTETRA) && !defined(USE_MCUBES))
27 #error "pick either USE_MTETRA or USE_MCUBES, not both..."
28 #endif
29
30 typedef float vec3[3];
31
32 struct metasurface {
33         vec3 min, max;
34         int res[3];
35         float thres;
36
37         msurf_eval_func_t eval;
38         msurf_vertex_func_t vertex;
39         msurf_normal_func_t normal;
40         void *udata;
41
42         float dx, dy, dz;
43         int flip;
44
45         vec3 vbuf[3];
46         int nverts;
47 };
48
49 static int msurf_init(struct metasurface *ms);
50 static void process_cell(struct metasurface *ms, vec3 pos, vec3 sz);
51 #ifdef USE_MTETRA
52 static void process_tetra(struct metasurface *ms, int *idx, vec3 *pos, float *val);
53 #endif
54 #ifdef USE_MCUBES
55 static void process_cube(struct metasurface *ms, vec3 *pos, float *val);
56 #endif
57
58
59 struct metasurface *msurf_create(void)
60 {
61         struct metasurface *ms;
62
63         if(!(ms = malloc(sizeof *ms))) {
64                 return 0;
65         }
66         if(msurf_init(ms) == -1) {
67                 free(ms);
68         }
69         return ms;
70 }
71
72 void msurf_free(struct metasurface *ms)
73 {
74         free(ms);
75 }
76
77 static int msurf_init(struct metasurface *ms)
78 {
79         ms->thres = 0.0;
80         ms->eval = 0;
81         ms->vertex = 0;
82         ms->normal = 0;
83         ms->udata = 0;
84         ms->min[0] = ms->min[1] = ms->min[2] = -1.0;
85         ms->max[0] = ms->max[1] = ms->max[2] = 1.0;
86         ms->res[0] = ms->res[1] = ms->res[2] = 40;
87         ms->nverts = 0;
88
89         ms->dx = ms->dy = ms->dz = 0.001;
90         ms->flip = 0;
91
92         return 0;
93 }
94
95 void msurf_set_user_data(struct metasurface *ms, void *udata)
96 {
97         ms->udata = udata;
98 }
99
100 void *msurf_get_user_data(struct metasurface *ms)
101 {
102         return ms->udata;
103 }
104
105 void msurf_set_inside(struct metasurface *ms, int inside)
106 {
107         switch(inside) {
108         case MSURF_GREATER:
109                 ms->flip = 0;
110                 break;
111
112         case MSURF_LESS:
113                 ms->flip = 1;
114                 break;
115
116         default:
117                 fprintf(stderr, "msurf_inside expects MSURF_GREATER or MSURF_LESS\n");
118         }
119 }
120
121 int msurf_get_inside(struct metasurface *ms)
122 {
123         return ms->flip ? MSURF_LESS : MSURF_GREATER;
124 }
125
126 void msurf_eval_func(struct metasurface *ms, msurf_eval_func_t func)
127 {
128         ms->eval = func;
129 }
130
131 void msurf_vertex_func(struct metasurface *ms, msurf_vertex_func_t func)
132 {
133         ms->vertex = func;
134 }
135
136 void msurf_normal_func(struct metasurface *ms, msurf_normal_func_t func)
137 {
138         ms->normal = func;
139 }
140
141 void msurf_set_bounds(struct metasurface *ms, float xmin, float ymin, float zmin, float xmax, float ymax, float zmax)
142 {
143         ms->min[0] = xmin;
144         ms->min[1] = ymin;
145         ms->min[2] = zmin;
146         ms->max[0] = xmax;
147         ms->max[1] = ymax;
148         ms->max[2] = zmax;
149 }
150
151 void msurf_get_bounds(struct metasurface *ms, float *xmin, float *ymin, float *zmin, float *xmax, float *ymax, float *zmax)
152 {
153         *xmin = ms->min[0];
154         *ymin = ms->min[1];
155         *zmin = ms->min[2];
156         *xmax = ms->max[0];
157         *ymax = ms->max[1];
158         *zmax = ms->max[2];
159 }
160
161 void msurf_set_resolution(struct metasurface *ms, int xres, int yres, int zres)
162 {
163         ms->res[0] = xres;
164         ms->res[1] = yres;
165         ms->res[2] = zres;
166 }
167
168 void msurf_get_resolution(struct metasurface *ms, int *xres, int *yres, int *zres)
169 {
170         *xres = ms->res[0];
171         *yres = ms->res[1];
172         *zres = ms->res[2];
173 }
174
175 void msurf_set_threshold(struct metasurface *ms, float thres)
176 {
177         ms->thres = thres;
178 }
179
180 float msurf_get_threshold(struct metasurface *ms)
181 {
182         return ms->thres;
183 }
184
185
186 int msurf_polygonize(struct metasurface *ms)
187 {
188         int i, j, k;
189         vec3 pos, delta;
190
191         if(!ms->eval || !ms->vertex) {
192                 fprintf(stderr, "you need to set eval and vertex callbacks before calling msurf_polygonize\n");
193                 return -1;
194         }
195
196         for(i=0; i<3; i++) {
197                 delta[i] = (ms->max[i] - ms->min[i]) / (float)ms->res[i];
198         }
199
200         pos[0] = ms->min[0];
201         for(i=0; i<ms->res[0] - 1; i++) {
202                 pos[1] = ms->min[1];
203                 for(j=0; j<ms->res[1] - 1; j++) {
204
205                         pos[2] = ms->min[2];
206                         for(k=0; k<ms->res[2] - 1; k++) {
207
208                                 process_cell(ms, pos, delta);
209
210                                 pos[2] += delta[2];
211                         }
212                         pos[1] += delta[1];
213                 }
214                 pos[0] += delta[0];
215         }
216         return 0;
217 }
218
219
220 static void process_cell(struct metasurface *ms, vec3 pos, vec3 sz)
221 {
222         int i;
223         vec3 p[8];
224         float val[8];
225
226 #ifdef USE_MTETRA
227         static int tetra[][4] = {
228                 {0, 2, 3, 7},
229                 {0, 2, 6, 7},
230                 {0, 4, 6, 7},
231                 {0, 6, 1, 2},
232                 {0, 6, 1, 4},
233                 {5, 6, 1, 4}
234         };
235 #endif
236
237         static const float offs[][3] = {
238                 {0.0f, 0.0f, 0.0f},
239                 {1.0f, 0.0f, 0.0f},
240                 {1.0f, 1.0f, 0.0f},
241                 {0.0f, 1.0f, 0.0f},
242                 {0.0f, 0.0f, 1.0f},
243                 {1.0f, 0.0f, 1.0f},
244                 {1.0f, 1.0f, 1.0f},
245                 {0.0f, 1.0f, 1.0f}
246         };
247
248         for(i=0; i<8; i++) {
249                 p[i][0] = pos[0] + sz[0] * offs[i][2];
250                 p[i][1] = pos[1] + sz[1] * offs[i][1];
251                 p[i][2] = pos[2] + sz[2] * offs[i][0];
252
253                 val[i] = ms->eval(ms, p[i][0], p[i][1], p[i][2]);
254         }
255
256 #ifdef USE_MTETRA
257         for(i=0; i<6; i++) {
258                 process_tetra(ms, tetra[i], p, val);
259         }
260 #endif
261 #ifdef USE_MCUBES
262         process_cube(ms, p, val);
263 #endif
264 }
265
266
267 /* ---- marching cubes implementation ---- */
268 #ifdef USE_MCUBES
269
270 static unsigned int mc_bitcode(float *val, float thres);
271
272 static void process_cube(struct metasurface *ms, vec3 *pos, float *val)
273 {
274         static const int pidx[12][2] = {
275                 {0, 1}, {1, 2}, {2, 3}, {3, 0}, {4, 5}, {5, 6},
276                 {6, 7}, {7, 4}, {0, 4}, {1, 5}, {2, 6}, {3, 7}
277         };
278         int i, j;
279         vec3 vert[12];
280         unsigned int code = mc_bitcode(val, ms->thres);
281
282         if(ms->flip) {
283                 code = ~code & 0xff;
284         }
285
286         if(mc_edge_table[code] == 0) {
287                 return;
288         }
289
290         for(i=0; i<12; i++) {
291                 if(mc_edge_table[code] & (1 << i)) {
292                         int p0 = pidx[i][0];
293                         int p1 = pidx[i][1];
294
295                         float t = (ms->thres - val[p0]) / (val[p1] - val[p0]);
296                         vert[i][0] = pos[p0][0] + (pos[p1][0] - pos[p0][0]) * t;
297                         vert[i][1] = pos[p0][1] + (pos[p1][1] - pos[p0][1]) * t;
298                         vert[i][2] = pos[p0][2] + (pos[p1][2] - pos[p0][2]) * t;
299                 }
300         }
301
302         for(i=0; mc_tri_table[code][i] != -1; i+=3) {
303                 for(j=0; j<3; j++) {
304                         float *v = vert[mc_tri_table[code][i + j]];
305
306                         if(ms->normal) {
307                                 float dfdx, dfdy, dfdz;
308                                 dfdx = ms->eval(ms, v[0] - ms->dx, v[1], v[2]) - ms->eval(ms, v[0] + ms->dx, v[1], v[2]);
309                                 dfdy = ms->eval(ms, v[0], v[1] - ms->dy, v[2]) - ms->eval(ms, v[0], v[1] + ms->dy, v[2]);
310                                 dfdz = ms->eval(ms, v[0], v[1], v[2] - ms->dz) - ms->eval(ms, v[0], v[1], v[2] + ms->dz);
311
312                                 if(ms->flip) {
313                                         dfdx = -dfdx;
314                                         dfdy = -dfdy;
315                                         dfdz = -dfdz;
316                                 }
317                                 ms->normal(ms, dfdx, dfdy, dfdz);
318                         }
319
320                         /* TODO multithreadied polygon emmit */
321                         ms->vertex(ms, v[0], v[1], v[2]);
322                 }
323         }
324 }
325
326 static unsigned int mc_bitcode(float *val, float thres)
327 {
328         unsigned int i, res = 0;
329
330         for(i=0; i<8; i++) {
331                 if(val[i] > thres) {
332                         res |= 1 << i;
333                 }
334         }
335         return res;
336 }
337 #endif  /* USE_MCUBES */
338
339
340 /* ---- marching tetrahedra implementation (incomplete) ---- */
341 #ifdef USE_MTETRA
342
343 static unsigned int mt_bitcode(float v0, float v1, float v2, float v3, float thres);
344 static void emmit(struct metasurface *ms, float v0, float v1, vec3 p0, vec3 p1, int rev)
345
346
347 #define REVBIT(x)       ((x) & 8)
348 #define INV(x)          (~(x) & 0xf)
349 #define EDGE(a, b)      emmit(ms, val[idx[a]], val[idx[b]], pos[idx[a]], pos[idx[b]], REVBIT(code))
350 static void process_tetra(struct metasurface *ms, int *idx, vec3 *pos, float *val)
351 {
352         unsigned int code = mt_bitcode(val[idx[0]], val[idx[1]], val[idx[2]], val[idx[3]], ms->thres);
353
354         switch(code) {
355         case 1:
356         case INV(1):
357                 EDGE(0, 1);
358                 EDGE(0, 2);
359                 EDGE(0, 3);
360                 break;
361
362         case 2:
363         case INV(2):
364                 EDGE(1, 0);
365                 EDGE(1, 3);
366                 EDGE(1, 2);
367                 break;
368
369         case 3:
370         case INV(3):
371                 EDGE(0, 3);
372                 EDGE(0, 2);
373                 EDGE(1, 3);
374
375                 EDGE(1, 3);
376                 EDGE(1, 2);
377                 EDGE(0, 2);
378                 break;
379
380         case 4:
381         case INV(4):
382                 EDGE(2, 0);
383                 EDGE(2, 1);
384                 EDGE(2, 3);
385                 break;
386
387         case 5:
388         case INV(5):
389                 EDGE(0, 1);
390                 EDGE(2, 3);
391                 EDGE(0, 3);
392
393                 EDGE(0, 1);
394                 EDGE(1, 2);
395                 EDGE(2, 3);
396                 break;
397
398         case 6:
399         case INV(6):
400                 EDGE(0, 1);
401                 EDGE(1, 3);
402                 EDGE(2, 3);
403
404                 EDGE(0, 1);
405                 EDGE(0, 2);
406                 EDGE(2, 3);
407                 break;
408
409         case 7:
410         case INV(7):
411                 EDGE(3, 0);
412                 EDGE(3, 2);
413                 EDGE(3, 1);
414                 break;
415
416         default:
417                 break;  /* cases 0 and 15 */
418         }
419 }
420
421 #define BIT(i)  ((v##i > thres) ? (1 << i) : 0)
422 static unsigned int mt_bitcode(float v0, float v1, float v2, float v3, float thres)
423 {
424         return BIT(0) | BIT(1) | BIT(2) | BIT(3);
425 }
426
427 static void emmit(struct metasurface *ms, float v0, float v1, vec3 p0, vec3 p1, int rev)
428 {
429         int i;
430         float t = (ms->thres - v0) / (v1 - v0);
431
432         vec3 p;
433         for(i=0; i<3; i++) {
434                 p[i] = p0[i] + (p1[i] - p0[i]) * t;
435         }
436         ms->vertex(ms, p[0], p[1], p[2]);
437
438         /*for(i=0; i<3; i++) {
439                 ms->vbuf[ms->nverts][i] = p0[i] + (p1[i] - p0[i]) * t;
440         }
441
442         if(++ms->nverts >= 3) {
443                 ms->nverts = 0;
444
445                 for(i=0; i<3; i++) {
446                         int idx = rev ? (2 - i) : i;
447                         ms->vertex(ms, ms->vbuf[idx][0], ms->vbuf[idx][1], ms->vbuf[idx][2]);
448                 }
449         }*/
450 }
451 #endif  /* USE_MTETRA */