volmetrics

annotate src/main.cc @ 9:40febfed6cff

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