volmetrics

annotate src/main.cc @ 16:add30e2d5253

foo
author Eleni Maria Stea <elene.mst@gmail.com>
date Mon, 03 Feb 2014 02:52:46 +0200
parents a93c8aa85e05
children 0f4fff558737
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
elene@16 22 static bool init_xfer(void);
elene@16 23 static void display_xfer(void);
elene@16 24 static void reshape_xfer(int x, int y);
elene@16 25 static void motion_xfer(int x, int y);
elene@16 26
elene@16 27 static int mainwin_id, xferwin_id;
elene@16 28
eleni@0 29 static int win_xsz, win_ysz;
elene@9 30 static float cam_phi, cam_theta, cam_dist = 6;
elene@9 31 static std::vector<bool> key_state(256);
eleni@0 32
elene@11 33 static const char *vol_fname = "data/test1.vol";
elene@6 34
elene@6 35 static Volume *vol;
elene@9 36 static Mesh *mesh;
elene@12 37 static float cur_z, thres = 0.5, thres2 = 1.0;
elene@9 38
elene@9 39 static int use_orig_vol_res = 1;
elene@9 40 static int vol_res[3]; // volume sampling resolution x/y/z
elene@9 41
elene@9 42 static GLUI *ui;
eleni@1 43
eleni@0 44 int main(int argc, char **argv)
eleni@0 45 {
eleni@0 46 glutInit(&argc, argv);
elene@16 47 if(argv[1])
elene@16 48 vol_fname = argv[1];
elene@16 49
elene@16 50 if(!init()) {
elene@16 51 fprintf(stderr, "Failed to initialize program.\n");
elene@16 52 return 1;
elene@16 53 }
elene@16 54
elene@16 55 init_xfer();
elene@16 56
elene@16 57 glutMainLoop();
elene@16 58 return 0;
elene@16 59 }
elene@16 60
elene@16 61 static bool init()
elene@16 62 {
elene@7 63 glutInitWindowSize(512, 512);
elene@11 64 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
eleni@0 65
elene@16 66 mainwin_id = glutCreateWindow("CT scan");
eleni@0 67 glutDisplayFunc(display);
eleni@0 68 glutReshapeFunc(reshape);
eleni@0 69 glutKeyboardFunc(keyboard);
elene@9 70 glutKeyboardUpFunc(keyboard_up);
eleni@0 71 glutMouseFunc(mouse);
eleni@0 72 glutMotionFunc(motion);
eleni@0 73
eleni@0 74 glewInit();
eleni@0 75
elene@11 76 glEnable(GL_DEPTH_TEST);
elene@11 77 glEnable(GL_NORMALIZE);
elene@11 78
elene@11 79 glEnable(GL_LIGHTING); //TODO: shaders
elene@11 80 glEnable(GL_LIGHT0);
elene@11 81 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
elene@11 82
elene@9 83 vol = new Volume;
elene@11 84 if(!vol->load(vol_fname)) {
elene@11 85 fprintf(stderr, "Failed to load %s", vol_fname);
elene@9 86 return false;
elene@9 87 }
elene@9 88 mesh = new Mesh;
elene@9 89 cur_z = 0.5;
elene@9 90
elene@9 91 vol_res[0] = vol->get_slice(0)->get_width();
elene@9 92 vol_res[1] = vol->get_slice(0)->get_height();
elene@9 93 vol_res[2] = vol->get_slice_count();
elene@9 94
elene@9 95 if(!(ui = create_ui())) {
elene@9 96 return false;
elene@9 97 }
elene@9 98
elene@9 99 return true;
elene@9 100 }
elene@9 101
elene@9 102 static GLUI_Spinner *res_spin[3];
elene@9 103 static void toggle_use_orig(int id)
elene@9 104 {
elene@9 105 for(int i=0; i<3; i++) {
elene@9 106 if(use_orig_vol_res) {
elene@9 107 res_spin[i]->disable();
elene@9 108 } else {
elene@9 109 res_spin[i]->enable();
elene@9 110 }
elene@9 111 }
elene@9 112 }
elene@9 113 static void thres_change(int id)
elene@9 114 {
elene@9 115 static float prev_thres = thres;
elene@12 116 static float prev_thres2 = thres2;
elene@9 117
elene@12 118 if(prev_thres != thres || prev_thres2 != thres2) {
elene@9 119 prev_thres = thres;
elene@12 120 prev_thres2 = thres2;
elene@12 121 mesh->clear();
elene@12 122 }
elene@16 123
elene@16 124 glutSetWindow(xferwin_id);
elene@16 125 glutPostRedisplay();
elene@16 126 glutSetWindow(mainwin_id);
elene@16 127 glutPostRedisplay();
elene@12 128 }
elene@12 129 static void res_change(int id)
elene@12 130 {
elene@12 131 static float prev_resx = vol_res[0];
elene@12 132 static float prev_resy = vol_res[1];
elene@12 133 static float prev_resz = vol_res[2];
elene@12 134
elene@12 135 if(prev_resx != vol_res[0] || prev_resy != vol_res[1] || prev_resz != vol_res[2]) {
elene@12 136 prev_resx = vol_res[0];
elene@12 137 prev_resy = vol_res[1];
elene@12 138 prev_resz = vol_res[2];
elene@9 139 mesh->clear();
elene@9 140 }
elene@9 141 }
elene@10 142 static GLUI *create_ui()
elene@9 143 {
elene@9 144 GLUI *ui = GLUI_Master.create_glui("ui");
elene@9 145 assert(ui);
elene@9 146
elene@9 147 ui->set_main_gfx_window(glutGetWindow());
elene@9 148
elene@12 149 GLUI_Panel *thres_panel = ui->add_panel("iso thresholds");
elene@12 150
elene@12 151 GLUI_Spinner *thres_spin = ui->add_spinner_to_panel(thres_panel, "T1", GLUI_SPINNER_FLOAT, &thres, 0, thres_change);
elene@9 152 thres_spin->set_float_limits(0, 1);
elene@9 153
elene@12 154 GLUI_Spinner *thres2_spin = ui->add_spinner_to_panel(thres_panel, "T2", GLUI_SPINNER_FLOAT, &thres2, 0, thres_change);
elene@12 155 thres2_spin->set_float_limits(0, 1);
elene@12 156
elene@9 157 GLUI_Panel *res_panel = ui->add_panel("volume resolution");
elene@9 158
elene@9 159 ui->add_checkbox_to_panel(res_panel, "original resolution", &use_orig_vol_res, 0, toggle_use_orig);
elene@9 160
elene@9 161 static const char *res_spin_name[] = {"x", "y", "z"};
elene@9 162 for(int i=0; i<3; i++) {
elene@12 163 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 164 res_spin[i]->set_int_limits(8, 256); // TODO limits as arguments or config
elene@9 165 res_spin[i]->disable();
elene@9 166 }
elene@9 167
elene@9 168 return ui;
elene@9 169 }
elene@9 170
elene@10 171 static void display(void)
eleni@0 172 {
elene@9 173 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
elene@9 174
elene@9 175 glMatrixMode(GL_MODELVIEW);
elene@9 176 glLoadIdentity();
elene@9 177 glTranslatef(0, 0, -cam_dist);
elene@9 178 glRotatef(cam_phi, 1, 0, 0);
elene@9 179 glRotatef(cam_theta, 0, 1, 0);
elene@9 180
elene@9 181 /*
elene@6 182 glBindTexture(GL_TEXTURE_3D, vol->get_texture());
elene@6 183 glEnable(GL_TEXTURE_3D);
eleni@1 184 glBegin(GL_QUADS);
elene@6 185 glTexCoord3f(0, 0, cur_z); glVertex3f(-1, -1, 0);
elene@6 186 glTexCoord3f(0, 1, cur_z); glVertex3f(-1, 1, 0);
elene@6 187 glTexCoord3f(1, 1, cur_z); glVertex3f(1, 1, 0);
elene@6 188 glTexCoord3f(1, 0, cur_z); glVertex3f(1, -1, 0);
eleni@1 189 glEnd();
elene@6 190 glDisable(GL_TEXTURE_3D);
elene@9 191 */
eleni@0 192
elene@9 193 if(mesh->is_empty()) {
elene@9 194 printf("recalculating isosurface ... ");
elene@9 195 fflush(stdout);
elene@12 196 vol->create_mesh(mesh, thres, thres2, vol_res[0], vol_res[1], vol_res[2]);
elene@9 197 printf("done.\n");
elene@9 198 }
elene@9 199 mesh->draw();
elene@9 200
elene@9 201 //TODO: draw threshold
eleni@0 202 glutSwapBuffers();
eleni@0 203 assert(glGetError() == GL_NO_ERROR);
eleni@0 204 }
eleni@0 205
elene@10 206 static void reshape(int x, int y)
eleni@0 207 {
eleni@0 208 glViewport(0, 0, x, y);
elene@9 209 glMatrixMode(GL_PROJECTION);
elene@9 210 glLoadIdentity();
elene@9 211 gluPerspective(45, (float)x / (float)y, 0.5, 500);
elene@9 212
eleni@0 213 if(x != win_xsz || y != win_ysz) {
eleni@0 214 win_xsz = x;
eleni@0 215 win_ysz = y;
eleni@0 216 }
eleni@0 217 }
eleni@0 218
elene@10 219 static void keyboard(unsigned char key, int x, int y)
eleni@0 220 {
elene@9 221 key_state[(int)key] = true;
elene@9 222
eleni@0 223 switch(key) {
eleni@0 224 case 27:
eleni@0 225 exit(0);
elene@9 226 case 'w':
elene@9 227 {
elene@9 228 static bool wire;
elene@9 229 wire = !wire;
elene@9 230 glPolygonMode(GL_FRONT_AND_BACK, wire ? GL_LINE : GL_FILL);
elene@9 231 }
elene@9 232 break;
eleni@0 233 default:
eleni@0 234 break;
eleni@0 235 }
eleni@0 236 }
eleni@0 237
elene@10 238 static void keyboard_up(unsigned char key, int x, int y)
elene@9 239 {
elene@9 240 key_state[(int) key] = false;
elene@9 241 }
elene@9 242
eleni@0 243 static int prev_x, prev_y;
elene@9 244 static bool bn_state[32];
elene@12 245 static float prev_thres, prev_thres2;
elene@9 246
elene@10 247 static void mouse(int bn, int state, int x, int y)
eleni@0 248 {
eleni@0 249 prev_x = x;
eleni@0 250 prev_y = y;
elene@9 251
elene@9 252 bn_state[bn - GLUT_LEFT_BUTTON] = (state == GLUT_DOWN);
elene@9 253
elene@9 254 if(state == GLUT_DOWN) {
elene@9 255 prev_thres = thres;
elene@12 256 prev_thres2 = thres2;
elene@9 257 }
elene@9 258 else {
elene@12 259 if(thres != prev_thres || thres2 != prev_thres2) {
elene@9 260 mesh->clear();
elene@9 261 }
elene@9 262 }
eleni@0 263 }
eleni@0 264
elene@10 265 static void motion(int x, int y)
eleni@0 266 {
eleni@0 267 int dx = x - prev_x;
eleni@0 268 int dy = y - prev_y;
elene@9 269
elene@9 270 if(!dx && !dy)
elene@9 271 return;
elene@9 272
eleni@0 273 prev_x = x;
eleni@0 274 prev_y = y;
elene@6 275
elene@9 276 if(key_state[(int)'t']) {
elene@9 277 thres = (float)x / (float)win_xsz;
elene@9 278 printf("threshold: %f\n", thres);
elene@9 279
elene@9 280 glutPostRedisplay();
elene@9 281 return;
elene@9 282 }
elene@9 283
elene@9 284 // camera
elene@9 285 if(bn_state[0]) {
elene@9 286 if(key_state[(int)'z']) {
elene@9 287 //zoom the camera
elene@9 288
elene@9 289 cam_dist += dy * 0.1;
elene@9 290
elene@9 291 if(cam_dist < 0)
elene@9 292 cam_dist = 0;
elene@9 293 }
elene@9 294 else {
elene@9 295 //rotate the camera
elene@9 296
elene@9 297 cam_phi += dy * 0.5;
elene@9 298 cam_theta += dx * 0.5;
elene@9 299
elene@9 300 if(cam_phi > 90)
elene@9 301 cam_phi = 90;
elene@9 302 if(cam_phi < -90)
elene@9 303 cam_phi = -90;
elene@9 304 }
elene@9 305
elene@6 306 glutPostRedisplay();
elene@6 307 }
eleni@0 308 }
elene@16 309
elene@16 310 static bool init_xfer(void)
elene@16 311 {
elene@16 312 glutSetWindow(mainwin_id);
elene@16 313 int x = glutGet(GLUT_WINDOW_X);
elene@16 314 int y = glutGet(GLUT_WINDOW_Y) + glutGet(GLUT_WINDOW_HEIGHT);
elene@16 315
elene@16 316 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
elene@16 317 glutInitWindowSize(512, 100);
elene@16 318 glutInitWindowPosition(x, y);
elene@16 319
elene@16 320 xferwin_id = glutCreateWindow("Transfer Function");
elene@16 321 glutDisplayFunc(display_xfer);
elene@16 322 glutReshapeFunc(reshape_xfer);
elene@16 323 glutMotionFunc(motion_xfer);
elene@16 324
elene@16 325 return true;
elene@16 326 }
elene@16 327
elene@16 328 static void display_xfer(void)
elene@16 329 {
elene@16 330 glClear(GL_COLOR_BUFFER_BIT);
elene@16 331
elene@16 332 int num_val = glutGet(GLUT_WINDOW_WIDTH) / 4.0;
elene@16 333 float x = 0;
elene@16 334 float dx = 1.0 / num_val;
elene@16 335 float low, high;
elene@16 336 if(thres < thres2) {
elene@16 337 low = thres;
elene@16 338 high = thres2;
elene@16 339 }
elene@16 340 else {
elene@16 341 low = thres2;
elene@16 342 high = thres;
elene@16 343 }
elene@16 344
elene@16 345 glBegin(GL_QUADS);
elene@16 346 for(int i=0; i<num_val; i++) {
elene@16 347 float val = transfer_function(x, low, high);
elene@16 348 glColor3f(val, val, val);
elene@16 349 glVertex3f(x, 1.0, 0.0);
elene@16 350 glVertex3f(x, 0.0, 0.0);
elene@16 351
elene@16 352 val = transfer_function(x + dx, low, high);
elene@16 353 glColor3f(val, val, val);
elene@16 354 glVertex3f(x + dx, 0.0, 0.0);
elene@16 355 glVertex3f(x + dx, 1.0, 0.0);
elene@16 356 x += dx;
elene@16 357 }
elene@16 358 glEnd();
elene@16 359
elene@16 360 glutSwapBuffers();
elene@16 361 assert(glGetError() == GL_NO_ERROR);
elene@16 362 }
elene@16 363
elene@16 364 static void reshape_xfer(int x, int y)
elene@16 365 {
elene@16 366 glViewport(0.0, 0.0, x, y);
elene@16 367 glMatrixMode(GL_PROJECTION);
elene@16 368 glLoadIdentity();
elene@16 369 glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
elene@16 370 }
elene@16 371
elene@16 372 static void motion_xfer(int x, int y)
elene@16 373 {
elene@16 374 //to pontiki sto kontinotero akro
elene@16 375 //glutPostRedisplay k sta 2 win
elene@16 376 }