dbf-udg
diff libs/metasurf/metasurf.c @ 5:e09cbb2e9d4f
metaballs
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 18 Feb 2013 03:46:52 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/metasurf/metasurf.c Mon Feb 18 03:46:52 2013 +0200 1.3 @@ -0,0 +1,413 @@ 1.4 +/* 1.5 +metasurf - a library for implicit surface polygonization 1.6 +Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org> 1.7 + 1.8 +This program is free software: you can redistribute it and/or modify 1.9 +it under the terms of the GNU Lesser General Public License as published by 1.10 +the Free Software Foundation, either version 3 of the License, or 1.11 +(at your option) any later version. 1.12 + 1.13 +This program is distributed in the hope that it will be useful, 1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.16 +GNU Lesser General Public License for more details. 1.17 + 1.18 +You should have received a copy of the GNU Lesser General Public License 1.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 1.20 +*/ 1.21 +#include <stdio.h> 1.22 +#include <stdlib.h> 1.23 +#include "metasurf.h" 1.24 +#include "mcubes.h" 1.25 + 1.26 +#undef USE_MTETRA 1.27 +#define USE_MCUBES 1.28 + 1.29 +#if (defined(USE_MTETRA) && defined(USE_MCUBES)) || (!defined(USE_MTETRA) && !defined(USE_MCUBES)) 1.30 +#error "pick either USE_MTETRA or USE_MCUBES, not both..." 1.31 +#endif 1.32 + 1.33 +typedef float vec3[3]; 1.34 + 1.35 +struct metasurface { 1.36 + vec3 min, max; 1.37 + int res[3]; 1.38 + float thres; 1.39 + 1.40 + msurf_eval_func_t eval; 1.41 + msurf_vertex_func_t vertex; 1.42 + msurf_normal_func_t normal; 1.43 + 1.44 + float dx, dy, dz; 1.45 + int flip; 1.46 + 1.47 + vec3 vbuf[3]; 1.48 + int nverts; 1.49 +}; 1.50 + 1.51 +static int msurf_init(struct metasurface *ms); 1.52 +static void process_cell(struct metasurface *ms, vec3 pos, vec3 sz); 1.53 +#ifdef USE_MTETRA 1.54 +static void process_tetra(struct metasurface *ms, int *idx, vec3 *pos, float *val); 1.55 +#endif 1.56 +#ifdef USE_MCUBES 1.57 +static void process_cube(struct metasurface *ms, vec3 *pos, float *val); 1.58 +#endif 1.59 + 1.60 + 1.61 +struct metasurface *msurf_create(void) 1.62 +{ 1.63 + struct metasurface *ms; 1.64 + 1.65 + if(!(ms = malloc(sizeof *ms))) { 1.66 + return 0; 1.67 + } 1.68 + if(msurf_init(ms) == -1) { 1.69 + free(ms); 1.70 + } 1.71 + return ms; 1.72 +} 1.73 + 1.74 +void msurf_free(struct metasurface *ms) 1.75 +{ 1.76 + free(ms); 1.77 +} 1.78 + 1.79 +static int msurf_init(struct metasurface *ms) 1.80 +{ 1.81 + ms->thres = 0.0; 1.82 + ms->eval = 0; 1.83 + ms->vertex = 0; 1.84 + ms->normal = 0; 1.85 + ms->min[0] = ms->min[1] = ms->min[2] = -1.0; 1.86 + ms->max[0] = ms->max[1] = ms->max[2] = 1.0; 1.87 + ms->res[0] = ms->res[1] = ms->res[2] = 40; 1.88 + ms->nverts = 0; 1.89 + 1.90 + ms->dx = ms->dy = ms->dz = 0.001; 1.91 + ms->flip = 0; 1.92 + 1.93 + return 0; 1.94 +} 1.95 + 1.96 +void msurf_inside(struct metasurface *ms, int inside) 1.97 +{ 1.98 + switch(inside) { 1.99 + case MSURF_GREATER: 1.100 + ms->flip = 0; 1.101 + break; 1.102 + 1.103 + case MSURF_LESS: 1.104 + ms->flip = 1; 1.105 + break; 1.106 + 1.107 + default: 1.108 + fprintf(stderr, "msurf_inside expects MSURF_GREATER or MSURF_LESS\n"); 1.109 + } 1.110 +} 1.111 + 1.112 +void msurf_eval_func(struct metasurface *ms, msurf_eval_func_t func) 1.113 +{ 1.114 + ms->eval = func; 1.115 +} 1.116 + 1.117 +void msurf_vertex_func(struct metasurface *ms, msurf_vertex_func_t func) 1.118 +{ 1.119 + ms->vertex = func; 1.120 +} 1.121 + 1.122 +void msurf_normal_func(struct metasurface *ms, msurf_normal_func_t func) 1.123 +{ 1.124 + ms->normal = func; 1.125 +} 1.126 + 1.127 +void msurf_bounds(struct metasurface *ms, float xmin, float ymin, float zmin, float xmax, float ymax, float zmax) 1.128 +{ 1.129 + ms->min[0] = xmin; 1.130 + ms->min[1] = ymin; 1.131 + ms->min[2] = zmin; 1.132 + ms->max[0] = xmax; 1.133 + ms->max[1] = ymax; 1.134 + ms->max[2] = zmax; 1.135 +} 1.136 + 1.137 +void msurf_resolution(struct metasurface *ms, int xres, int yres, int zres) 1.138 +{ 1.139 + ms->res[0] = xres; 1.140 + ms->res[1] = yres; 1.141 + ms->res[2] = zres; 1.142 +} 1.143 + 1.144 +void msurf_threshold(struct metasurface *ms, float thres) 1.145 +{ 1.146 + ms->thres = thres; 1.147 +} 1.148 + 1.149 + 1.150 +int msurf_polygonize(struct metasurface *ms) 1.151 +{ 1.152 + int i, j, k; 1.153 + vec3 pos, delta; 1.154 + 1.155 + if(!ms->eval || !ms->vertex) { 1.156 + fprintf(stderr, "you need to set eval and vertex callbacks before calling msurf_polygonize\n"); 1.157 + return -1; 1.158 + } 1.159 + 1.160 + for(i=0; i<3; i++) { 1.161 + delta[i] = (ms->max[i] - ms->min[i]) / (float)ms->res[i]; 1.162 + } 1.163 + 1.164 + pos[0] = ms->min[0]; 1.165 + for(i=0; i<ms->res[0] - 1; i++) { 1.166 + 1.167 + pos[1] = ms->min[1]; 1.168 + for(j=0; j<ms->res[1] - 1; j++) { 1.169 + 1.170 + pos[2] = ms->min[2]; 1.171 + for(k=0; k<ms->res[2] - 1; k++) { 1.172 + 1.173 + process_cell(ms, pos, delta); 1.174 + 1.175 + pos[2] += delta[2]; 1.176 + } 1.177 + pos[1] += delta[1]; 1.178 + } 1.179 + pos[0] += delta[0]; 1.180 + } 1.181 + return 0; 1.182 +} 1.183 + 1.184 + 1.185 +static void process_cell(struct metasurface *ms, vec3 pos, vec3 sz) 1.186 +{ 1.187 + int i; 1.188 + vec3 p[8]; 1.189 + float val[8]; 1.190 + 1.191 +#ifdef USE_MTETRA 1.192 + static int tetra[][4] = { 1.193 + {0, 2, 3, 7}, 1.194 + {0, 2, 6, 7}, 1.195 + {0, 4, 6, 7}, 1.196 + {0, 6, 1, 2}, 1.197 + {0, 6, 1, 4}, 1.198 + {5, 6, 1, 4} 1.199 + }; 1.200 +#endif 1.201 + 1.202 + static const float offs[][3] = { 1.203 + {0.0f, 0.0f, 0.0f}, 1.204 + {1.0f, 0.0f, 0.0f}, 1.205 + {1.0f, 1.0f, 0.0f}, 1.206 + {0.0f, 1.0f, 0.0f}, 1.207 + {0.0f, 0.0f, 1.0f}, 1.208 + {1.0f, 0.0f, 1.0f}, 1.209 + {1.0f, 1.0f, 1.0f}, 1.210 + {0.0f, 1.0f, 1.0f} 1.211 + }; 1.212 + 1.213 + for(i=0; i<8; i++) { 1.214 + p[i][0] = pos[0] + sz[0] * offs[i][2]; 1.215 + p[i][1] = pos[1] + sz[1] * offs[i][1]; 1.216 + p[i][2] = pos[2] + sz[2] * offs[i][0]; 1.217 + 1.218 + val[i] = ms->eval(p[i][0], p[i][1], p[i][2]); 1.219 + } 1.220 + 1.221 +#ifdef USE_MTETRA 1.222 + for(i=0; i<6; i++) { 1.223 + process_tetra(ms, tetra[i], p, val); 1.224 + } 1.225 +#endif 1.226 +#ifdef USE_MCUBES 1.227 + process_cube(ms, p, val); 1.228 +#endif 1.229 +} 1.230 + 1.231 + 1.232 +/* ---- marching cubes implementation ---- */ 1.233 +#ifdef USE_MCUBES 1.234 + 1.235 +static unsigned int mc_bitcode(float *val, float thres); 1.236 + 1.237 +static void process_cube(struct metasurface *ms, vec3 *pos, float *val) 1.238 +{ 1.239 + static const int pidx[12][2] = { 1.240 + {0, 1}, {1, 2}, {2, 3}, {3, 0}, {4, 5}, {5, 6}, 1.241 + {6, 7}, {7, 4}, {0, 4}, {1, 5}, {2, 6}, {3, 7} 1.242 + }; 1.243 + int i, j; 1.244 + vec3 vert[12]; 1.245 + unsigned int code = mc_bitcode(val, ms->thres); 1.246 + 1.247 + if(ms->flip) { 1.248 + code = ~code & 0xff; 1.249 + } 1.250 + 1.251 + if(mc_edge_table[code] == 0) { 1.252 + return; 1.253 + } 1.254 + 1.255 + for(i=0; i<12; i++) { 1.256 + if(mc_edge_table[code] & (1 << i)) { 1.257 + int p0 = pidx[i][0]; 1.258 + int p1 = pidx[i][1]; 1.259 + 1.260 + float t = (ms->thres - val[p0]) / (val[p1] - val[p0]); 1.261 + vert[i][0] = pos[p0][0] + (pos[p1][0] - pos[p0][0]) * t; 1.262 + vert[i][1] = pos[p0][1] + (pos[p1][1] - pos[p0][1]) * t; 1.263 + vert[i][2] = pos[p0][2] + (pos[p1][2] - pos[p0][2]) * t; 1.264 + } 1.265 + } 1.266 + 1.267 + for(i=0; mc_tri_table[code][i] != -1; i+=3) { 1.268 + for(j=0; j<3; j++) { 1.269 + float *v = vert[mc_tri_table[code][i + j]]; 1.270 + 1.271 + if(ms->normal) { 1.272 + float dfdx, dfdy, dfdz; 1.273 + dfdx = ms->eval(v[0] - ms->dx, v[1], v[2]) - ms->eval(v[0] + ms->dx, v[1], v[2]); 1.274 + dfdy = ms->eval(v[0], v[1] - ms->dy, v[2]) - ms->eval(v[0], v[1] + ms->dy, v[2]); 1.275 + dfdz = ms->eval(v[0], v[1], v[2] - ms->dz) - ms->eval(v[0], v[1], v[2] + ms->dz); 1.276 + 1.277 + if(ms->flip) { 1.278 + dfdx = -dfdx; 1.279 + dfdy = -dfdy; 1.280 + dfdz = -dfdz; 1.281 + } 1.282 + ms->normal(dfdx, dfdy, dfdz); 1.283 + } 1.284 + 1.285 + ms->vertex(v[0], v[1], v[2]); 1.286 + } 1.287 + } 1.288 +} 1.289 + 1.290 +static unsigned int mc_bitcode(float *val, float thres) 1.291 +{ 1.292 + unsigned int i, res = 0; 1.293 + 1.294 + for(i=0; i<8; i++) { 1.295 + if(val[i] > thres) { 1.296 + res |= 1 << i; 1.297 + } 1.298 + } 1.299 + return res; 1.300 +} 1.301 +#endif /* USE_MCUBES */ 1.302 + 1.303 + 1.304 +/* ---- marching tetrahedra implementation (incomplete) ---- */ 1.305 +#ifdef USE_MTETRA 1.306 + 1.307 +static unsigned int mt_bitcode(float v0, float v1, float v2, float v3, float thres); 1.308 +static void emmit(struct metasurface *ms, float v0, float v1, vec3 p0, vec3 p1, int rev) 1.309 + 1.310 + 1.311 +#define REVBIT(x) ((x) & 8) 1.312 +#define INV(x) (~(x) & 0xf) 1.313 +#define EDGE(a, b) emmit(ms, val[idx[a]], val[idx[b]], pos[idx[a]], pos[idx[b]], REVBIT(code)) 1.314 +static void process_tetra(struct metasurface *ms, int *idx, vec3 *pos, float *val) 1.315 +{ 1.316 + unsigned int code = mt_bitcode(val[idx[0]], val[idx[1]], val[idx[2]], val[idx[3]], ms->thres); 1.317 + 1.318 + switch(code) { 1.319 + case 1: 1.320 + case INV(1): 1.321 + EDGE(0, 1); 1.322 + EDGE(0, 2); 1.323 + EDGE(0, 3); 1.324 + break; 1.325 + 1.326 + case 2: 1.327 + case INV(2): 1.328 + EDGE(1, 0); 1.329 + EDGE(1, 3); 1.330 + EDGE(1, 2); 1.331 + break; 1.332 + 1.333 + case 3: 1.334 + case INV(3): 1.335 + EDGE(0, 3); 1.336 + EDGE(0, 2); 1.337 + EDGE(1, 3); 1.338 + 1.339 + EDGE(1, 3); 1.340 + EDGE(1, 2); 1.341 + EDGE(0, 2); 1.342 + break; 1.343 + 1.344 + case 4: 1.345 + case INV(4): 1.346 + EDGE(2, 0); 1.347 + EDGE(2, 1); 1.348 + EDGE(2, 3); 1.349 + break; 1.350 + 1.351 + case 5: 1.352 + case INV(5): 1.353 + EDGE(0, 1); 1.354 + EDGE(2, 3); 1.355 + EDGE(0, 3); 1.356 + 1.357 + EDGE(0, 1); 1.358 + EDGE(1, 2); 1.359 + EDGE(2, 3); 1.360 + break; 1.361 + 1.362 + case 6: 1.363 + case INV(6): 1.364 + EDGE(0, 1); 1.365 + EDGE(1, 3); 1.366 + EDGE(2, 3); 1.367 + 1.368 + EDGE(0, 1); 1.369 + EDGE(0, 2); 1.370 + EDGE(2, 3); 1.371 + break; 1.372 + 1.373 + case 7: 1.374 + case INV(7): 1.375 + EDGE(3, 0); 1.376 + EDGE(3, 2); 1.377 + EDGE(3, 1); 1.378 + break; 1.379 + 1.380 + default: 1.381 + break; /* cases 0 and 15 */ 1.382 + } 1.383 +} 1.384 + 1.385 +#define BIT(i) ((v##i > thres) ? (1 << i) : 0) 1.386 +static unsigned int mt_bitcode(float v0, float v1, float v2, float v3, float thres) 1.387 +{ 1.388 + return BIT(0) | BIT(1) | BIT(2) | BIT(3); 1.389 +} 1.390 + 1.391 +static void emmit(struct metasurface *ms, float v0, float v1, vec3 p0, vec3 p1, int rev) 1.392 +{ 1.393 + int i; 1.394 + float t = (ms->thres - v0) / (v1 - v0); 1.395 + 1.396 + vec3 p; 1.397 + for(i=0; i<3; i++) { 1.398 + p[i] = p0[i] + (p1[i] - p0[i]) * t; 1.399 + } 1.400 + ms->vertex(p[0], p[1], p[2]); 1.401 + 1.402 + /*for(i=0; i<3; i++) { 1.403 + ms->vbuf[ms->nverts][i] = p0[i] + (p1[i] - p0[i]) * t; 1.404 + } 1.405 + 1.406 + if(++ms->nverts >= 3) { 1.407 + ms->nverts = 0; 1.408 + 1.409 + for(i=0; i<3; i++) { 1.410 + int idx = rev ? (2 - i) : i; 1.411 + ms->vertex(ms->vbuf[idx][0], ms->vbuf[idx][1], ms->vbuf[idx][2]); 1.412 + } 1.413 + }*/ 1.414 +} 1.415 + 1.416 +#endif /* USE_MTETRA */