metasurf

view src/metasurf.c @ 0:7aa4627e492b

first commit
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 25 Oct 2011 07:34:31 +0300
parents
children 9ab057fba0c5
line source
1 #include <stdlib.h>
2 #include "metasurf.h"
3 #include "mcubes.h"
5 #undef USE_MTETRA
6 #define USE_MCUBES
8 #if (defined(USE_MTETRA) && defined(USE_MCUBES)) || (!defined(USE_MTETRA) && !defined(USE_MCUBES))
9 #error "pick either USE_MTETRA or USE_MCUBES, not both..."
10 #endif
12 typedef float vec3[3];
14 struct metasurface {
15 vec3 min, max;
16 int res[3];
17 float thres;
19 msurf_eval_func_t eval;
20 msurf_vertex_func_t vertex;
21 msurf_normal_func_t normal;
23 vec3 vbuf[3];
24 int nverts;
25 };
27 static int msurf_init(struct metasurface *ms);
28 static void process_cell(struct metasurface *ms, vec3 pos, vec3 sz);
29 #ifdef USE_MTETRA
30 static void process_tetra(struct metasurface *ms, int *idx, vec3 *pos, float *val);
31 #endif
32 #ifdef USE_MCUBES
33 static void process_cube(struct metasurface *ms, vec3 *pos, float *val);
34 #endif
37 struct metasurface *msurf_create(void)
38 {
39 struct metasurface *ms;
41 if(!(ms = malloc(sizeof *ms))) {
42 return 0;
43 }
44 if(msurf_init(ms) == -1) {
45 free(ms);
46 }
47 return ms;
48 }
50 void msurf_free(struct metasurface *ms)
51 {
52 free(ms);
53 }
55 static int msurf_init(struct metasurface *ms)
56 {
57 ms->thres = 0.0;
58 ms->eval = 0;
59 ms->vertex = 0;
60 ms->normal = 0;
61 ms->min[0] = ms->min[1] = ms->min[2] = -1.0;
62 ms->max[0] = ms->max[1] = ms->max[2] = 1.0;
63 ms->res[0] = ms->res[1] = ms->res[2] = 32;
64 ms->nverts = 0;
66 return 0;
67 }
69 void msurf_eval_func(struct metasurface *ms, msurf_eval_func_t func)
70 {
71 ms->eval = func;
72 }
74 void msurf_vertex_func(struct metasurface *ms, msurf_vertex_func_t func)
75 {
76 ms->vertex = func;
77 }
79 void msurf_normal_func(struct metasurface *ms, msurf_normal_func_t func)
80 {
81 ms->normal = func;
82 }
84 void msurf_bounds(struct metasurface *ms, float xmin, float ymin, float zmin, float xmax, float ymax, float zmax)
85 {
86 ms->min[0] = xmin;
87 ms->min[1] = ymin;
88 ms->min[2] = zmin;
89 ms->max[0] = xmax;
90 ms->max[1] = ymax;
91 ms->max[2] = zmax;
92 }
94 void msurf_resolution(struct metasurface *ms, int xres, int yres, int zres)
95 {
96 ms->res[0] = xres;
97 ms->res[1] = yres;
98 ms->res[2] = zres;
99 }
101 void msurf_threshold(struct metasurface *ms, float thres)
102 {
103 ms->thres = thres;
104 }
107 void msurf_polygonize(struct metasurface *ms)
108 {
109 int i, j, k;
110 vec3 pos, delta;
112 for(i=0; i<3; i++) {
113 delta[i] = (ms->max[i] - ms->min[i]) / (float)ms->res[i];
114 }
116 pos[0] = ms->min[0];
117 for(i=0; i<ms->res[0] - 1; i++) {
119 pos[1] = ms->min[1];
120 for(j=0; j<ms->res[1] - 1; j++) {
122 pos[2] = ms->min[2];
123 for(k=0; k<ms->res[2] - 1; k++) {
125 process_cell(ms, pos, delta);
127 pos[2] += delta[2];
128 }
129 pos[1] += delta[1];
130 }
131 pos[0] += delta[0];
132 }
133 }
136 static void process_cell(struct metasurface *ms, vec3 pos, vec3 sz)
137 {
138 int i;
139 vec3 p[8];
140 float val[8];
142 #ifdef USE_MTETRA
143 static int tetra[][4] = {
144 {0, 2, 3, 7},
145 {0, 2, 6, 7},
146 {0, 4, 6, 7},
147 {0, 6, 1, 2},
148 {0, 6, 1, 4},
149 {5, 6, 1, 4}
150 };
151 #endif
153 static const float offs[][3] = {
154 {0.0f, 0.0f, 0.0f},
155 {1.0f, 0.0f, 0.0f},
156 {1.0f, 1.0f, 0.0f},
157 {0.0f, 1.0f, 0.0f},
158 {0.0f, 0.0f, 1.0f},
159 {1.0f, 0.0f, 1.0f},
160 {1.0f, 1.0f, 1.0f},
161 {0.0f, 1.0f, 1.0f}
162 };
164 for(i=0; i<8; i++) {
165 p[i][0] = pos[0] + sz[0] * offs[i][2];
166 p[i][1] = pos[1] + sz[1] * offs[i][1];
167 p[i][2] = pos[2] + sz[2] * offs[i][0];
169 val[i] = ms->eval(p[i][0], p[i][1], p[i][2]);
170 }
172 #ifdef USE_MTETRA
173 for(i=0; i<6; i++) {
174 process_tetra(ms, tetra[i], p, val);
175 }
176 #endif
177 #ifdef USE_MCUBES
178 process_cube(ms, p, val);
179 #endif
180 }
183 /* ---- marching cubes implementation ---- */
184 #ifdef USE_MCUBES
186 static unsigned int mc_bitcode(float *val, float thres);
188 static void process_cube(struct metasurface *ms, vec3 *pos, float *val)
189 {
190 static const int pidx[12][2] = {
191 {0, 1}, {1, 2}, {2, 3}, {3, 0}, {4, 5}, {5, 6},
192 {6, 7}, {7, 4}, {0, 4}, {1, 5}, {2, 6}, {3, 7}
193 };
194 int i, j;
195 vec3 vert[12];
196 unsigned int code = mc_bitcode(val, ms->thres);
198 if(mc_edge_table[code] == 0) {
199 return;
200 }
202 for(i=0; i<12; i++) {
203 if(mc_edge_table[code] & (1 << i)) {
204 int p0 = pidx[i][0];
205 int p1 = pidx[i][1];
207 float t = (ms->thres - val[p0]) / (val[p1] - val[p0]);
208 vert[i][0] = pos[p0][0] + (pos[p1][0] - pos[p0][0]) * t;
209 vert[i][1] = pos[p0][1] + (pos[p1][1] - pos[p0][1]) * t;
210 vert[i][2] = pos[p0][2] + (pos[p1][2] - pos[p0][2]) * t;
211 }
212 }
214 for(i=0; mc_tri_table[code][i] != -1; i+=3) {
215 for(j=0; j<3; j++) {
216 float *v = vert[mc_tri_table[code][i + j]];
217 ms->vertex(v[0], v[1], v[2]);
218 }
219 }
220 }
222 static unsigned int mc_bitcode(float *val, float thres)
223 {
224 unsigned int i, res = 0;
226 for(i=0; i<8; i++) {
227 if(val[i] > thres) {
228 res |= 1 << i;
229 }
230 }
231 return res;
232 }
233 #endif /* USE_MCUBES */
236 /* ---- marching tetrahedra implementation (incomplete) ---- */
237 #ifdef USE_MTETRA
239 static unsigned int mt_bitcode(float v0, float v1, float v2, float v3, float thres);
240 static void emmit(struct metasurface *ms, float v0, float v1, vec3 p0, vec3 p1, int rev)
243 #define REVBIT(x) ((x) & 8)
244 #define INV(x) (~(x) & 0xf)
245 #define EDGE(a, b) emmit(ms, val[idx[a]], val[idx[b]], pos[idx[a]], pos[idx[b]], REVBIT(code))
246 static void process_tetra(struct metasurface *ms, int *idx, vec3 *pos, float *val)
247 {
248 unsigned int code = mt_bitcode(val[idx[0]], val[idx[1]], val[idx[2]], val[idx[3]], ms->thres);
250 switch(code) {
251 /*case 1:
252 case INV(1):*/
253 case 0x0e:
254 case 0x01:
255 EDGE(0, 1);
256 EDGE(0, 2);
257 EDGE(0, 3);
258 break;
260 /*case 2:
261 case INV(2):*/
262 case 0x0d:
263 case 0x02:
264 EDGE(1, 0);
265 EDGE(1, 3);
266 EDGE(1, 2);
267 break;
269 /*case 3:
270 case INV(3):*/
271 case 0x0c:
272 case 0x03:
273 EDGE(0, 3);
274 EDGE(0, 2);
275 EDGE(1, 3);
277 EDGE(1, 3);
278 EDGE(1, 2);
279 EDGE(0, 2);
280 break;
282 /*case 4:
283 case INV(4):*/
284 case 0x0b:
285 case 0x04:
286 EDGE(2, 0);
287 EDGE(2, 1);
288 EDGE(2, 3);
289 break;
291 /*case 5:
292 case INV(5):*/
293 case 0x0a:
294 case 0x05:
295 EDGE(0, 1);
296 EDGE(2, 3);
297 EDGE(0, 3);
299 EDGE(0, 1);
300 EDGE(1, 2);
301 EDGE(2, 3);
302 break;
304 /*case 6:
305 case INV(6):*/
306 case 0x09:
307 case 0x06:
308 EDGE(0, 1);
309 EDGE(1, 3);
310 EDGE(2, 3);
312 EDGE(0, 1);
313 EDGE(0, 2);
314 EDGE(2, 3);
315 break;
317 /*case 7:
318 case INV(7):*/
319 case 0x07:
320 case 0x08:
321 EDGE(3, 0);
322 EDGE(3, 2);
323 EDGE(3, 1);
324 break;
326 default:
327 break; /* cases 0 and 15 */
328 }
329 }
331 #define BIT(i) ((v##i > thres) ? (1 << i) : 0)
332 static unsigned int mt_bitcode(float v0, float v1, float v2, float v3, float thres)
333 {
334 return BIT(0) | BIT(1) | BIT(2) | BIT(3);
335 }
337 static void emmit(struct metasurface *ms, float v0, float v1, vec3 p0, vec3 p1, int rev)
338 {
339 int i;
340 float t = (ms->thres - v0) / (v1 - v0);
342 vec3 p;
343 for(i=0; i<3; i++) {
344 p[i] = p0[i] + (p1[i] - p0[i]) * t;
345 }
346 ms->vertex(p[0], p[1], p[2]);
348 /*for(i=0; i<3; i++) {
349 ms->vbuf[ms->nverts][i] = p0[i] + (p1[i] - p0[i]) * t;
350 }
352 if(++ms->nverts >= 3) {
353 ms->nverts = 0;
355 for(i=0; i<3; i++) {
356 int idx = rev ? (2 - i) : i;
357 ms->vertex(ms->vbuf[idx][0], ms->vbuf[idx][1], ms->vbuf[idx][2]);
358 }
359 }*/
360 }
362 #endif /* USE_MTETRA */