diff --git a/README b/README index b8fdf8f..937ba1b 100644 --- a/README +++ b/README @@ -20,7 +20,7 @@ sphere, centered around the origin. /* initialization */ ms = msurf_create(); msurf_eval_func(ms, eval); - msurf_vertex_func(ms, glVertex3f); + msurf_vertex_func(ms, vertex); /* drawing */ glBegin(GL_TRIANGLES); @@ -28,11 +28,17 @@ sphere, centered around the origin. glEnd(); /* evaluator */ - float eval(float x, float y, float z) + float eval(struct metasurface *ms, float x, float y, float z) { return (x * x + y * y + z * z) - 1.0; } + /* vertex generation callback */ + float vertex(struct metasurface *ms, float x, float y, float z) + { + glVertex3f(x, y, z); + } + See the examples subdirectory for more examples. 3. License diff --git a/examples/metaballs/src/metaballs.c b/examples/metaballs/src/metaballs.c index c7ee01c..4a93ae2 100644 --- a/examples/metaballs/src/metaballs.c +++ b/examples/metaballs/src/metaballs.c @@ -30,8 +30,8 @@ struct metaball { int num_mballs = sizeof mball / sizeof *mball; -float eval(float x, float y, float z); -void vertex(float x, float y, float z); +float eval(struct metasurface *ms, float x, float y, float z); +void vertex(struct metasurface *ms, float x, float y, float z); void render(void); void disp(void); void reshape(int x, int y); @@ -107,9 +107,9 @@ int main(int argc, char **argv) msurf = msurf_create(); msurf_eval_func(msurf, eval); msurf_vertex_func(msurf, vertex); - msurf_threshold(msurf, threshold); - msurf_resolution(msurf, RES, RES, RES); - msurf_bounds(msurf, -1, -1, -1, 1, 1, 1); + msurf_set_threshold(msurf, threshold); + msurf_set_resolution(msurf, RES, RES, RES); + msurf_set_bounds(msurf, -1, -1, -1, 1, 1, 1); glClearColor(0.8, 0.8, 0.8, 1.0); @@ -117,7 +117,7 @@ int main(int argc, char **argv) return 0; } -float eval(float x, float y, float z) +float eval(struct metasurface *ms, float x, float y, float z) { int i; float val = 0.0f; @@ -137,12 +137,12 @@ float eval(float x, float y, float z) return val; } -void vertex(float x, float y, float z) +void vertex(struct metasurface *ms, float x, float y, float z) { const float dt = 0.001; - float dfdx = eval(x - dt, y, z) - eval(x + dt, y, z); - float dfdy = eval(x, y - dt, z) - eval(x, y + dt, z); - float dfdz = eval(x, y, z - dt) - eval(x, y, z + dt); + float dfdx = eval(ms, x - dt, y, z) - eval(ms, x + dt, y, z); + float dfdy = eval(ms, x, y - dt, z) - eval(ms, x, y + dt, z); + float dfdz = eval(ms, x, y, z - dt) - eval(ms, x, y, z + dt); glNormal3f(dfdx, dfdy, dfdz); glVertex3f(x, y, z); @@ -239,14 +239,14 @@ void keyb(unsigned char key, int x, int y) case '=': threshold += 0.05; - msurf_threshold(msurf, threshold); + msurf_set_threshold(msurf, threshold); printf("threshold: %f\n", threshold); glutPostRedisplay(); break; case '-': threshold -= 0.05; - msurf_threshold(msurf, threshold); + msurf_set_threshold(msurf, threshold); printf("threshold: %f\n", threshold); glutPostRedisplay(); break; diff --git a/examples/simple/simple.c b/examples/simple/simple.c index e32f315..daad90d 100644 --- a/examples/simple/simple.c +++ b/examples/simple/simple.c @@ -8,7 +8,9 @@ #include "metasurf.h" -float eval(float x, float y, float z); +float eval(struct metasurface *ms, float x, float y, float z); +void vertex(struct metasurface *ms, float x, float y, float z); +void normal(struct metasurface *ms, float x, float y, float z); void disp(void); void reshape(int x, int y); void keyb(unsigned char key, int x, int y); @@ -39,14 +41,13 @@ int main(int argc, char **argv) ms = msurf_create(); /* consider anything below the threshold (0 by default) to be inside */ - msurf_inside(ms, MSURF_LESS); + msurf_set_inside(ms, MSURF_LESS); /* set the evaluation callback */ msurf_eval_func(ms, eval); - /* pass any vertices and normals generated directly to OpenGL */ - msurf_vertex_func(ms, glVertex3f); - msurf_normal_func(ms, glNormal3f); + msurf_vertex_func(ms, vertex); + msurf_normal_func(ms, normal); /* slightly increase the bounds to avoid clipping the unit sphere */ - msurf_bounds(ms, -1.1, -1.1, -1.1, 1.1, 1.1, 1.1); + msurf_set_bounds(ms, -1.1, -1.1, -1.1, 1.1, 1.1, 1.1); glutMainLoop(); return 0; @@ -55,11 +56,23 @@ int main(int argc, char **argv) /* the unit sphere is implicitly defined as the locus of points in R3 satisfying * the equation: x^2 + y^2 + z^2 - 1 = 0 */ -float eval(float x, float y, float z) +float eval(struct metasurface *ms, float x, float y, float z) { return (x * x + y * y + z * z) - 1.0; } +void vertex(struct metasurface *ms, float x, float y, float z) +{ + /* pass any vertices generated directly to OpenGL */ + glVertex3f(x, y, z); +} + +void normal(struct metasurface *ms, float x, float y, float z) +{ + /* pass any normals generated directly to OpenGL */ + glNormal3f(x, y, z); +} + void disp(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); diff --git a/examples/volume/src/volume.c b/examples/volume/src/volume.c index f8c4a1c..ce8f8df 100644 --- a/examples/volume/src/volume.c +++ b/examples/volume/src/volume.c @@ -19,8 +19,8 @@ #include "cam.h" #include "metasurf.h" -float eval(float x, float y, float z); -void vertex(float x, float y, float z); +float eval(struct metasurface *ms, float x, float y, float z); +void vertex(struct metasurface *ms, float x, float y, float z); void render(void); void disp(void); void reshape(int x, int y); @@ -100,9 +100,9 @@ int main(int argc, char **argv) msurf = msurf_create(); msurf_eval_func(msurf, eval); msurf_vertex_func(msurf, vertex); - msurf_threshold(msurf, threshold); - msurf_resolution(msurf, xres, yres, num_slices); - msurf_bounds(msurf, -1, -1, -1, 1, 1, 1); + msurf_set_threshold(msurf, threshold); + msurf_set_resolution(msurf, xres, yres, num_slices); + msurf_set_bounds(msurf, -1, -1, -1, 1, 1, 1); glClearColor(0.6, 0.6, 0.6, 1.0); @@ -112,7 +112,7 @@ int main(int argc, char **argv) return 0; } -float eval(float x, float y, float z) +float eval(struct metasurface *ms, float x, float y, float z) { int px, py, slice; struct img_pixmap *img; @@ -134,14 +134,14 @@ float eval(float x, float y, float z) return *((unsigned char*)img->pixels + py * img->width + px) / 255.0; } -void vertex(float x, float y, float z) +void vertex(struct metasurface *ms, float x, float y, float z) { float dx = 1.0 / xres; float dy = 1.0 / yres; float dz = 1.0 / num_slices; - float dfdx = eval(x - dx, y, z) - eval(x + dx, y, z); - float dfdy = eval(x, y - dy, z) - eval(x, y + dy, z); - float dfdz = eval(x, y, z - dz) - eval(x, y, z + dz); + float dfdx = eval(ms, x - dx, y, z) - eval(ms, x + dx, y, z); + float dfdy = eval(ms, x, y - dy, z) - eval(ms, x, y + dy, z); + float dfdz = eval(ms, x, y, z - dz) - eval(ms, x, y, z + dz); glNormal3f(dfdx, dfdy, dfdz); glVertex3f(x, y, z); @@ -256,7 +256,7 @@ void keyb(unsigned char key, int x, int y) case '=': threshold += 0.05; - msurf_threshold(msurf, threshold); + msurf_set_threshold(msurf, threshold); printf("threshold: %f\n", threshold); glutPostRedisplay(); need_update = 1; @@ -264,7 +264,7 @@ void keyb(unsigned char key, int x, int y) case '-': threshold -= 0.05; - msurf_threshold(msurf, threshold); + msurf_set_threshold(msurf, threshold); printf("threshold: %f\n", threshold); glutPostRedisplay(); need_update = 1; diff --git a/src/metasurf.c b/src/metasurf.c index 322f4c3..85aae1c 100644 --- a/src/metasurf.c +++ b/src/metasurf.c @@ -1,6 +1,6 @@ /* metasurf - a library for implicit surface polygonization -Copyright (C) 2011 John Tsiombikas +Copyright (C) 2011-2015 John Tsiombikas This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -37,6 +37,7 @@ struct metasurface { msurf_eval_func_t eval; msurf_vertex_func_t vertex; msurf_normal_func_t normal; + void *udata; float dx, dy, dz; int flip; @@ -79,6 +80,7 @@ static int msurf_init(struct metasurface *ms) ms->eval = 0; ms->vertex = 0; ms->normal = 0; + ms->udata = 0; ms->min[0] = ms->min[1] = ms->min[2] = -1.0; ms->max[0] = ms->max[1] = ms->max[2] = 1.0; ms->res[0] = ms->res[1] = ms->res[2] = 40; @@ -90,7 +92,17 @@ static int msurf_init(struct metasurface *ms) return 0; } -void msurf_inside(struct metasurface *ms, int inside) +void msurf_set_user_data(struct metasurface *ms, void *udata) +{ + ms->udata = udata; +} + +void *msurf_get_user_data(struct metasurface *ms) +{ + return ms->udata; +} + +void msurf_set_inside(struct metasurface *ms, int inside) { switch(inside) { case MSURF_GREATER: @@ -106,6 +118,11 @@ void msurf_inside(struct metasurface *ms, int inside) } } +int msurf_get_inside(struct metasurface *ms) +{ + return ms->flip ? MSURF_LESS : MSURF_GREATER; +} + void msurf_eval_func(struct metasurface *ms, msurf_eval_func_t func) { ms->eval = func; @@ -121,7 +138,7 @@ void msurf_normal_func(struct metasurface *ms, msurf_normal_func_t func) ms->normal = func; } -void msurf_bounds(struct metasurface *ms, float xmin, float ymin, float zmin, float xmax, float ymax, float zmax) +void msurf_set_bounds(struct metasurface *ms, float xmin, float ymin, float zmin, float xmax, float ymax, float zmax) { ms->min[0] = xmin; ms->min[1] = ymin; @@ -131,18 +148,40 @@ void msurf_bounds(struct metasurface *ms, float xmin, float ymin, float zmin, fl ms->max[2] = zmax; } -void msurf_resolution(struct metasurface *ms, int xres, int yres, int zres) +void msurf_get_bounds(struct metasurface *ms, float *xmin, float *ymin, float *zmin, float *xmax, float *ymax, float *zmax) +{ + *xmin = ms->min[0]; + *ymin = ms->min[1]; + *zmin = ms->min[2]; + *xmax = ms->max[0]; + *ymax = ms->max[1]; + *zmax = ms->max[2]; +} + +void msurf_set_resolution(struct metasurface *ms, int xres, int yres, int zres) { ms->res[0] = xres; ms->res[1] = yres; ms->res[2] = zres; } -void msurf_threshold(struct metasurface *ms, float thres) +void msurf_get_resolution(struct metasurface *ms, int *xres, int *yres, int *zres) +{ + *xres = ms->res[0]; + *yres = ms->res[1]; + *zres = ms->res[2]; +} + +void msurf_set_threshold(struct metasurface *ms, float thres) { ms->thres = thres; } +float msurf_get_threshold(struct metasurface *ms) +{ + return ms->thres; +} + int msurf_polygonize(struct metasurface *ms) { @@ -211,7 +250,7 @@ static void process_cell(struct metasurface *ms, vec3 pos, vec3 sz) p[i][1] = pos[1] + sz[1] * offs[i][1]; p[i][2] = pos[2] + sz[2] * offs[i][0]; - val[i] = ms->eval(p[i][0], p[i][1], p[i][2]); + val[i] = ms->eval(ms, p[i][0], p[i][1], p[i][2]); } #ifdef USE_MTETRA @@ -266,20 +305,20 @@ static void process_cube(struct metasurface *ms, vec3 *pos, float *val) if(ms->normal) { float dfdx, dfdy, dfdz; - dfdx = ms->eval(v[0] - ms->dx, v[1], v[2]) - ms->eval(v[0] + ms->dx, v[1], v[2]); - dfdy = ms->eval(v[0], v[1] - ms->dy, v[2]) - ms->eval(v[0], v[1] + ms->dy, v[2]); - dfdz = ms->eval(v[0], v[1], v[2] - ms->dz) - ms->eval(v[0], v[1], v[2] + ms->dz); + dfdx = ms->eval(ms, v[0] - ms->dx, v[1], v[2]) - ms->eval(ms, v[0] + ms->dx, v[1], v[2]); + dfdy = ms->eval(ms, v[0], v[1] - ms->dy, v[2]) - ms->eval(ms, v[0], v[1] + ms->dy, v[2]); + dfdz = ms->eval(ms, v[0], v[1], v[2] - ms->dz) - ms->eval(ms, v[0], v[1], v[2] + ms->dz); if(ms->flip) { dfdx = -dfdx; dfdy = -dfdy; dfdz = -dfdz; } - ms->normal(dfdx, dfdy, dfdz); + ms->normal(ms, dfdx, dfdy, dfdz); } /* TODO multithreadied polygon emmit */ - ms->vertex(v[0], v[1], v[2]); + ms->vertex(ms, v[0], v[1], v[2]); } } } @@ -394,7 +433,7 @@ static void emmit(struct metasurface *ms, float v0, float v1, vec3 p0, vec3 p1, for(i=0; i<3; i++) { p[i] = p0[i] + (p1[i] - p0[i]) * t; } - ms->vertex(p[0], p[1], p[2]); + ms->vertex(ms, p[0], p[1], p[2]); /*for(i=0; i<3; i++) { ms->vbuf[ms->nverts][i] = p0[i] + (p1[i] - p0[i]) * t; @@ -405,7 +444,7 @@ static void emmit(struct metasurface *ms, float v0, float v1, vec3 p0, vec3 p1, for(i=0; i<3; i++) { int idx = rev ? (2 - i) : i; - ms->vertex(ms->vbuf[idx][0], ms->vbuf[idx][1], ms->vbuf[idx][2]); + ms->vertex(ms, ms->vbuf[idx][0], ms->vbuf[idx][1], ms->vbuf[idx][2]); } }*/ } diff --git a/src/metasurf.h b/src/metasurf.h index 5ffa65c..7cdd074 100644 --- a/src/metasurf.h +++ b/src/metasurf.h @@ -1,6 +1,6 @@ /* metasurf - a library for implicit surface polygonization -Copyright (C) 2011 John Tsiombikas +Copyright (C) 2011-2015 John Tsiombikas This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -24,9 +24,9 @@ along with this program. If not, see . struct metasurface; -typedef float (*msurf_eval_func_t)(float, float, float); -typedef void (*msurf_vertex_func_t)(float, float, float); -typedef void (*msurf_normal_func_t)(float, float, float); +typedef float (*msurf_eval_func_t)(struct metasurface *ms, float, float, float); +typedef void (*msurf_vertex_func_t)(struct metasurface *ms, float, float, float); +typedef void (*msurf_normal_func_t)(struct metasurface *ms, float, float, float); #ifdef __cplusplus extern "C" { @@ -35,8 +35,12 @@ extern "C" { struct metasurface *msurf_create(void); void msurf_free(struct metasurface *ms); +void msurf_set_user_data(struct metasurface *ms, void *udata); +void *msurf_get_user_data(struct metasurface *ms); + /* which is inside above or below the threshold */ -void msurf_inside(struct metasurface *ms, int inside); +void msurf_set_inside(struct metasurface *ms, int inside); +int msurf_get_inside(struct metasurface *ms); /* set a scalar field evaluator function */ void msurf_eval_func(struct metasurface *ms, msurf_eval_func_t func); @@ -50,15 +54,18 @@ void msurf_normal_func(struct metasurface *ms, msurf_normal_func_t func); /* set the bounding box (default: -1, -1, -1, 1, 1, 1) * keep this as tight as possible to avoid wasting grid resolution */ -void msurf_bounds(struct metasurface *ms, float xmin, float ymin, float zmin, float xmax, float ymax, float zmax); +void msurf_set_bounds(struct metasurface *ms, float xmin, float ymin, float zmin, float xmax, float ymax, float zmax); +void msurf_get_bounds(struct metasurface *ms, float *xmin, float *ymin, float *zmin, float *xmax, float *ymax, float *zmax); /* resolution of the 3D evaluation grid, the bigger, the better, the slower * (default: 40, 40, 40) */ -void msurf_resolution(struct metasurface *ms, int xres, int yres, int zres); +void msurf_set_resolution(struct metasurface *ms, int xres, int yres, int zres); +void msurf_get_resolution(struct metasurface *ms, int *xres, int *yres, int *zres); /* isosurface threshold value (default: 0) */ -void msurf_threshold(struct metasurface *ms, float thres); +void msurf_set_threshold(struct metasurface *ms, float thres); +float msurf_get_threshold(struct metasurface *ms); /* finally call this to perform the polygonization */