volmetrics

annotate src/main.cc @ 12:1272e3335608

using 2 thresholds (sigmoid functions) custom resolution in polygonization
author Eleni Maria Stea <elene.mst@gmail.com>
date Sun, 02 Feb 2014 02:18:08 +0200
parents c5af275b6a60
children a93c8aa85e05
rev   line source
eleni@0 1 #include <GL/glew.h>
eleni@0 2 #include <GL/glut.h>
elene@9 3 #include <GL/glui.h>
eleni@0 4
eleni@0 5 #include <stdio.h>
eleni@0 6 #include <assert.h>
eleni@0 7
elene@9 8 #include <vector>
elene@9 9
elene@9 10 #include "mesh.h"
elene@6 11 #include "volume.h"
eleni@1 12
elene@10 13 static bool init(void);
elene@10 14 static GLUI *create_ui(void);
elene@10 15 static void display(void);
elene@10 16 static void reshape(int x, int y);
elene@10 17 static void keyboard(unsigned char key, int x, int y);
elene@10 18 static void keyboard_up(unsigned char key, int x, int y);
elene@10 19 static void mouse(int button, int state, int x, int y);
elene@10 20 static void motion(int x, int y);
eleni@0 21
eleni@0 22 static int win_xsz, win_ysz;
elene@9 23 static float cam_phi, cam_theta, cam_dist = 6;
elene@9 24 static std::vector<bool> key_state(256);
eleni@0 25
elene@11 26 static const char *vol_fname = "data/test1.vol";
elene@6 27
elene@6 28 static Volume *vol;
elene@9 29 static Mesh *mesh;
elene@12 30 static float cur_z, thres = 0.5, thres2 = 1.0;
elene@9 31
elene@9 32 static int use_orig_vol_res = 1;
elene@9 33 static int vol_res[3]; // volume sampling resolution x/y/z
elene@9 34
elene@9 35 static GLUI *ui;
eleni@1 36
eleni@0 37 int main(int argc, char **argv)
eleni@0 38 {
eleni@0 39 glutInit(&argc, argv);
elene@7 40 glutInitWindowSize(512, 512);
elene@11 41 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
eleni@0 42
elene@11 43 if(argv[1])
elene@11 44 vol_fname = argv[1];
eleni@0 45
eleni@0 46 glutCreateWindow("My Colonoscopie OEO!");
eleni@0 47
eleni@0 48 glutDisplayFunc(display);
eleni@0 49 glutReshapeFunc(reshape);
eleni@0 50 glutKeyboardFunc(keyboard);
elene@9 51 glutKeyboardUpFunc(keyboard_up);
eleni@0 52 glutMouseFunc(mouse);
eleni@0 53 glutMotionFunc(motion);
eleni@0 54
eleni@0 55 glewInit();
eleni@1 56 if(!init()) {
eleni@1 57 fprintf(stderr, "Failed to initialize La votre Colonoscopie\n");
eleni@1 58 return 1;
eleni@1 59 }
eleni@0 60
eleni@0 61 //call init
eleni@0 62
eleni@0 63 glutMainLoop();
eleni@0 64 return 0;
eleni@0 65 }
eleni@0 66
elene@10 67 static bool init()
elene@9 68 {
elene@11 69 glEnable(GL_DEPTH_TEST);
elene@11 70 glEnable(GL_NORMALIZE);
elene@11 71
elene@11 72 glEnable(GL_LIGHTING); //TODO: shaders
elene@11 73 glEnable(GL_LIGHT0);
elene@11 74 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
elene@11 75
elene@9 76 vol = new Volume;
elene@11 77 if(!vol->load(vol_fname)) {
elene@11 78 fprintf(stderr, "Failed to load %s", vol_fname);
elene@9 79 return false;
elene@9 80 }
elene@9 81 mesh = new Mesh;
elene@9 82 cur_z = 0.5;
elene@9 83
elene@9 84 vol_res[0] = vol->get_slice(0)->get_width();
elene@9 85 vol_res[1] = vol->get_slice(0)->get_height();
elene@9 86 vol_res[2] = vol->get_slice_count();
elene@9 87
elene@9 88 if(!(ui = create_ui())) {
elene@9 89 return false;
elene@9 90 }
elene@9 91
elene@9 92 return true;
elene@9 93 }
elene@9 94
elene@9 95 static GLUI_Spinner *res_spin[3];
elene@9 96 static void toggle_use_orig(int id)
elene@9 97 {
elene@9 98 for(int i=0; i<3; i++) {
elene@9 99 if(use_orig_vol_res) {
elene@9 100 res_spin[i]->disable();
elene@9 101 } else {
elene@9 102 res_spin[i]->enable();
elene@9 103 }
elene@9 104 }
elene@9 105 }
elene@9 106 static void thres_change(int id)
elene@9 107 {
elene@9 108 static float prev_thres = thres;
elene@12 109 static float prev_thres2 = thres2;
elene@9 110
elene@12 111 if(prev_thres != thres || prev_thres2 != thres2) {
elene@9 112 prev_thres = thres;
elene@12 113 prev_thres2 = thres2;
elene@12 114 mesh->clear();
elene@12 115 }
elene@12 116 }
elene@12 117 static void res_change(int id)
elene@12 118 {
elene@12 119 static float prev_resx = vol_res[0];
elene@12 120 static float prev_resy = vol_res[1];
elene@12 121 static float prev_resz = vol_res[2];
elene@12 122
elene@12 123 if(prev_resx != vol_res[0] || prev_resy != vol_res[1] || prev_resz != vol_res[2]) {
elene@12 124 prev_resx = vol_res[0];
elene@12 125 prev_resy = vol_res[1];
elene@12 126 prev_resz = vol_res[2];
elene@9 127 mesh->clear();
elene@9 128 }
elene@9 129 }
elene@10 130 static GLUI *create_ui()
elene@9 131 {
elene@9 132 GLUI *ui = GLUI_Master.create_glui("ui");
elene@9 133 assert(ui);
elene@9 134
elene@9 135 ui->set_main_gfx_window(glutGetWindow());
elene@9 136
elene@12 137 GLUI_Panel *thres_panel = ui->add_panel("iso thresholds");
elene@12 138
elene@12 139 GLUI_Spinner *thres_spin = ui->add_spinner_to_panel(thres_panel, "T1", GLUI_SPINNER_FLOAT, &thres, 0, thres_change);
elene@9 140 thres_spin->set_float_limits(0, 1);
elene@9 141
elene@12 142 GLUI_Spinner *thres2_spin = ui->add_spinner_to_panel(thres_panel, "T2", GLUI_SPINNER_FLOAT, &thres2, 0, thres_change);
elene@12 143 thres2_spin->set_float_limits(0, 1);
elene@12 144
elene@9 145 GLUI_Panel *res_panel = ui->add_panel("volume resolution");
elene@9 146
elene@9 147 ui->add_checkbox_to_panel(res_panel, "original resolution", &use_orig_vol_res, 0, toggle_use_orig);
elene@9 148
elene@9 149 static const char *res_spin_name[] = {"x", "y", "z"};
elene@9 150 for(int i=0; i<3; i++) {
elene@12 151 res_spin[i] = ui->add_spinner_to_panel(res_panel, res_spin_name[i], GLUI_SPINNER_INT, vol_res + i, 0, res_change);
elene@9 152 res_spin[i]->set_int_limits(8, 256); // TODO limits as arguments or config
elene@9 153 res_spin[i]->disable();
elene@9 154 }
elene@9 155
elene@9 156 return ui;
elene@9 157 }
elene@9 158
elene@10 159 static void display(void)
eleni@0 160 {
elene@9 161 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
elene@9 162
elene@9 163 glMatrixMode(GL_MODELVIEW);
elene@9 164 glLoadIdentity();
elene@9 165 glTranslatef(0, 0, -cam_dist);
elene@9 166 glRotatef(cam_phi, 1, 0, 0);
elene@9 167 glRotatef(cam_theta, 0, 1, 0);
elene@9 168
elene@9 169 /*
elene@6 170 glBindTexture(GL_TEXTURE_3D, vol->get_texture());
elene@6 171 glEnable(GL_TEXTURE_3D);
eleni@1 172 glBegin(GL_QUADS);
elene@6 173 glTexCoord3f(0, 0, cur_z); glVertex3f(-1, -1, 0);
elene@6 174 glTexCoord3f(0, 1, cur_z); glVertex3f(-1, 1, 0);
elene@6 175 glTexCoord3f(1, 1, cur_z); glVertex3f(1, 1, 0);
elene@6 176 glTexCoord3f(1, 0, cur_z); glVertex3f(1, -1, 0);
eleni@1 177 glEnd();
elene@6 178 glDisable(GL_TEXTURE_3D);
elene@9 179 */
eleni@0 180
elene@9 181 if(mesh->is_empty()) {
elene@9 182 printf("recalculating isosurface ... ");
elene@9 183 fflush(stdout);
elene@12 184 vol->create_mesh(mesh, thres, thres2, vol_res[0], vol_res[1], vol_res[2]);
elene@9 185 printf("done.\n");
elene@9 186 }
elene@9 187 mesh->draw();
elene@9 188
elene@9 189 //TODO: draw threshold
eleni@0 190 glutSwapBuffers();
eleni@0 191 assert(glGetError() == GL_NO_ERROR);
eleni@0 192 }
eleni@0 193
elene@10 194 static void reshape(int x, int y)
eleni@0 195 {
eleni@0 196 glViewport(0, 0, x, y);
elene@9 197 glMatrixMode(GL_PROJECTION);
elene@9 198 glLoadIdentity();
elene@9 199 gluPerspective(45, (float)x / (float)y, 0.5, 500);
elene@9 200
eleni@0 201 if(x != win_xsz || y != win_ysz) {
eleni@0 202 win_xsz = x;
eleni@0 203 win_ysz = y;
eleni@0 204 }
eleni@0 205 }
eleni@0 206
elene@10 207 static void keyboard(unsigned char key, int x, int y)
eleni@0 208 {
elene@9 209 key_state[(int)key] = true;
elene@9 210
eleni@0 211 switch(key) {
eleni@0 212 case 27:
eleni@0 213 exit(0);
elene@9 214 case 'w':
elene@9 215 {
elene@9 216 static bool wire;
elene@9 217 wire = !wire;
elene@9 218 glPolygonMode(GL_FRONT_AND_BACK, wire ? GL_LINE : GL_FILL);
elene@9 219 }
elene@9 220 break;
eleni@0 221 default:
eleni@0 222 break;
eleni@0 223 }
eleni@0 224 }
eleni@0 225
elene@10 226 static void keyboard_up(unsigned char key, int x, int y)
elene@9 227 {
elene@9 228 key_state[(int) key] = false;
elene@9 229 }
elene@9 230
eleni@0 231 static int prev_x, prev_y;
elene@9 232 static bool bn_state[32];
elene@12 233 static float prev_thres, prev_thres2;
elene@9 234
elene@10 235 static void mouse(int bn, int state, int x, int y)
eleni@0 236 {
eleni@0 237 prev_x = x;
eleni@0 238 prev_y = y;
elene@9 239
elene@9 240 bn_state[bn - GLUT_LEFT_BUTTON] = (state == GLUT_DOWN);
elene@9 241
elene@9 242 if(state == GLUT_DOWN) {
elene@9 243 prev_thres = thres;
elene@12 244 prev_thres2 = thres2;
elene@9 245 }
elene@9 246 else {
elene@12 247 if(thres != prev_thres || thres2 != prev_thres2) {
elene@9 248 mesh->clear();
elene@9 249 }
elene@9 250 }
eleni@0 251 }
eleni@0 252
elene@10 253 static void motion(int x, int y)
eleni@0 254 {
eleni@0 255 int dx = x - prev_x;
eleni@0 256 int dy = y - prev_y;
elene@9 257
elene@9 258 if(!dx && !dy)
elene@9 259 return;
elene@9 260
eleni@0 261 prev_x = x;
eleni@0 262 prev_y = y;
elene@6 263
elene@9 264 if(key_state[(int)'t']) {
elene@9 265 thres = (float)x / (float)win_xsz;
elene@9 266 printf("threshold: %f\n", thres);
elene@9 267
elene@9 268 glutPostRedisplay();
elene@9 269 return;
elene@9 270 }
elene@9 271
elene@9 272 // camera
elene@9 273 if(bn_state[0]) {
elene@9 274 if(key_state[(int)'z']) {
elene@9 275 //zoom the camera
elene@9 276
elene@9 277 cam_dist += dy * 0.1;
elene@9 278
elene@9 279 if(cam_dist < 0)
elene@9 280 cam_dist = 0;
elene@9 281 }
elene@9 282 else {
elene@9 283 //rotate the camera
elene@9 284
elene@9 285 cam_phi += dy * 0.5;
elene@9 286 cam_theta += dx * 0.5;
elene@9 287
elene@9 288 if(cam_phi > 90)
elene@9 289 cam_phi = 90;
elene@9 290 if(cam_phi < -90)
elene@9 291 cam_phi = -90;
elene@9 292 }
elene@9 293
elene@6 294 glutPostRedisplay();
elene@6 295 }
eleni@0 296 }