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