metasurf

annotate 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
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 */