11 int res[3], newres[3];
19 int varr_size, varr_alloc_size;
23 static int msurf_init(struct metasurface *ms);
24 static void process_cell(struct metasurface *ms, int xcell, int ycell, int zcell, vec3 pos, vec3 sz);
26 static int **mc_tri_table;
28 static int decompress_tables(void)
30 int i, j, run, nib, *data;
31 unsigned char *indata;
33 if(!(mc_tri_table = malloc(256 * 16 * sizeof(int) + 256 * sizeof(void*)))) {
34 fprintf(stderr, "decompress_tables: failed to allocate memory\n");
40 data = (int*)(mc_tri_table + 256);
41 for(i=0; i<256; i++) {
42 mc_tri_table[i] = data + i * 16;
44 run = ((i & 1) == 0) ? tritab_runlen[i/2] & 0xf : tritab_runlen[i/2] >> 4;
47 mc_tri_table[i][j] = ((nib++ & 1) == 0) ? *indata & 0xf : *indata++ >> 4;
49 mc_tri_table[i][j] = -1;
57 struct metasurface *msurf_create(void)
59 struct metasurface *ms;
62 if(decompress_tables() == -1) {
67 if(!(ms = malloc(sizeof *ms))) {
70 if(msurf_init(ms) == -1) {
76 void msurf_free(struct metasurface *ms)
86 static int msurf_init(struct metasurface *ms)
90 ms->min[0] = ms->min[1] = ms->min[2] = -1.0;
91 ms->max[0] = ms->max[1] = ms->max[2] = 1.0;
92 ms->res[0] = ms->res[1] = ms->res[2] = 0;
93 ms->newres[0] = ms->newres[1] = ms->newres[2] = 40;
95 ms->varr_alloc_size = ms->varr_size = 0;
96 ms->varr = ms->narr = 0;
98 ms->dx = ms->dy = ms->dz = 0.001;
104 void msurf_enable(struct metasurface *ms, unsigned int opt)
109 void msurf_disable(struct metasurface *ms, unsigned int opt)
114 int msurf_is_enabled(struct metasurface *ms, unsigned int opt)
116 return ms->flags & opt;
119 void msurf_set_inside(struct metasurface *ms, int inside)
123 msurf_enable(ms, MSURF_FLIP);
127 msurf_disable(ms, MSURF_FLIP);
131 fprintf(stderr, "msurf_inside expects MSURF_GREATER or MSURF_LESS\n");
135 int msurf_get_inside(struct metasurface *ms)
137 return msurf_is_enabled(ms, MSURF_FLIP) ? MSURF_LESS : MSURF_GREATER;
140 void msurf_set_bounds(struct metasurface *ms, float xmin, float ymin, float zmin, float xmax, float ymax, float zmax)
150 void msurf_get_bounds(struct metasurface *ms, float *xmin, float *ymin, float *zmin, float *xmax, float *ymax, float *zmax)
160 void msurf_set_resolution(struct metasurface *ms, int xres, int yres, int zres)
162 ms->newres[0] = xres;
163 ms->newres[1] = yres;
164 ms->newres[2] = zres;
167 void msurf_get_resolution(struct metasurface *ms, int *xres, int *yres, int *zres)
174 void msurf_set_threshold(struct metasurface *ms, float thres)
179 float msurf_get_threshold(struct metasurface *ms)
185 float *msurf_voxels(struct metasurface *ms)
187 if(ms->res[0] != ms->newres[0] || ms->res[1] != ms->newres[1] || ms->res[2] != ms->newres[2]) {
189 ms->res[0] = ms->newres[0];
190 ms->res[1] = ms->newres[1];
191 ms->res[2] = ms->newres[2];
192 count = ms->res[0] * ms->res[1] * ms->res[2];
194 if(!(ms->voxels = malloc(count * sizeof *ms->voxels))) {
201 float *msurf_slice(struct metasurface *ms, int idx)
203 float *vox = msurf_voxels(ms);
206 return vox + ms->res[0] * ms->res[1] * idx;
209 int msurf_polygonize(struct metasurface *ms)
214 if(!ms->voxels) return -1;
219 delta[i] = (ms->max[i] - ms->min[i]) / (float)ms->res[i];
222 for(i=0; i<ms->res[0] - 1; i++) {
223 for(j=0; j<ms->res[1] - 1; j++) {
224 for(k=0; k<ms->res[2] - 1; k++) {
226 pos[0] = ms->min[0] + i * delta[0];
227 pos[1] = ms->min[1] + j * delta[1];
228 pos[2] = ms->min[2] + k * delta[2];
230 process_cell(ms, i, j, k, pos, delta);
237 int msurf_vertex_count(struct metasurface *ms)
239 return ms->varr_size / 3;
242 float *msurf_vertices(struct metasurface *ms)
247 float *msurf_normals(struct metasurface *ms)
252 static unsigned int mc_bitcode(float *val, float thres);
254 static void process_cell(struct metasurface *ms, int xcell, int ycell, int zcell, vec3 cellpos, vec3 cellsz)
256 int i, j, k, slice_size;
258 float dfdx[8], dfdy[8], dfdz[8];
259 vec3 vert[12], norm[12];
264 static const int offs[][3] = {
275 static const int pidx[12][2] = {
276 {0, 1}, {1, 2}, {2, 3}, {3, 0}, {4, 5}, {5, 6},
277 {6, 7}, {7, 4}, {0, 4}, {1, 5}, {2, 6}, {3, 7}
280 slice_size = ms->res[0] * ms->res[1];
281 cellptr = ms->voxels + slice_size * zcell + ms->res[0] * ycell + xcell;
283 #define GRIDOFFS(x, y, z) ((z) * slice_size + (y) * ms->res[0] + (x))
286 val[i] = cellptr[GRIDOFFS(offs[i][0], offs[i][1], offs[i][2])];
289 code = mc_bitcode(val, ms->thres);
290 if(ms->flags & MSURF_FLIP) {
293 if(mc_edge_table[code] == 0) {
297 /* calculate normals at the 8 corners */
299 float *ptr = cellptr + GRIDOFFS(offs[i][0], offs[i][1], offs[i][2]);
301 if(xcell < ms->res[0] - 1) {
302 dfdx[i] = ptr[GRIDOFFS(1, 0, 0)] - *ptr;
304 dfdx[i] = *ptr - ptr[GRIDOFFS(-1, 0, 0)];
306 if(ycell < ms->res[1] - 1) {
307 dfdy[i] = ptr[GRIDOFFS(0, 1, 0)] - *ptr;
309 dfdy[i] = *ptr - ptr[GRIDOFFS(0, -1, 0)];
311 if(zcell < ms->res[2] - 1) {
312 dfdz[i] = ptr[GRIDOFFS(0, 0, 1)] - *ptr;
314 dfdz[i] = *ptr - ptr[GRIDOFFS(0, 0, -1)];
318 /* calculate the world-space position of each corner */
320 pos[i][0] = cellpos[0] + cellsz[0] * offs[i][0];
321 pos[i][1] = cellpos[1] + cellsz[1] * offs[i][1];
322 pos[i][2] = cellpos[2] + cellsz[2] * offs[i][2];
325 /* generate up to a max of 12 vertices per cube. interpolate positions and normals for each one */
326 for(i=0; i<12; i++) {
327 if(mc_edge_table[code] & (1 << i)) {
332 float t = (ms->thres - val[p0]) / (val[p1] - val[p0]);
333 vert[i][0] = pos[p0][0] + (pos[p1][0] - pos[p0][0]) * t;
334 vert[i][1] = pos[p0][1] + (pos[p1][1] - pos[p0][1]) * t;
335 vert[i][2] = pos[p0][2] + (pos[p1][2] - pos[p0][2]) * t;
337 nx = dfdx[p0] + (dfdx[p1] - dfdx[p0]) * t;
338 ny = dfdy[p0] + (dfdy[p1] - dfdy[p0]) * t;
339 nz = dfdz[p0] + (dfdz[p1] - dfdz[p0]) * t;
341 if(ms->flags & MSURF_FLIP) {
347 if(ms->flags & MSURF_NORMALIZE) {
348 float len = sqrt(nx * nx + ny * ny + nz * nz);
350 float s = 1.0f / len;
363 /* for each triangle of the cube add the appropriate vertices to the vertex buffer */
364 for(i=0; mc_tri_table[code][i] != -1; i+=3) {
366 int idx = mc_tri_table[code][i + j];
367 float *v = vert[idx];
368 float *n = norm[idx];
370 /* TODO multithreadied polygon emit */
371 if(ms->varr_size + 3 > ms->varr_alloc_size) {
372 int newsz = ms->varr_alloc_size ? ms->varr_alloc_size * 2 : 1024;
373 float *new_varr, *new_narr;
375 if(!(new_varr = realloc(ms->varr, newsz * sizeof *new_varr)) ||
376 !(new_narr = realloc(ms->narr, newsz * sizeof *new_narr))) {
378 fprintf(stderr, "msurf_polygonize: failed to grow vertex buffers to %d elements\n", newsz);
383 ms->varr_alloc_size = newsz;
387 ms->varr[ms->varr_size] = v[k];
388 ms->narr[ms->varr_size] = n[k];
395 static unsigned int mc_bitcode(float *val, float thres)
397 unsigned int i, res = 0;