volmetrics

annotate src/main.cc @ 11:c5af275b6a60

fixed normals
author Eleni Maria Stea <elene.mst@gmail.com>
date Mon, 27 Jan 2014 01:22:02 +0200
parents 8ffa6d61eb56
children 1272e3335608
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@9 30 static float cur_z, thres = 0.5;
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@9 109
elene@9 110 if(prev_thres != thres) {
elene@9 111 prev_thres = thres;
elene@9 112 mesh->clear();
elene@9 113 }
elene@9 114 }
elene@10 115 static GLUI *create_ui()
elene@9 116 {
elene@9 117 GLUI *ui = GLUI_Master.create_glui("ui");
elene@9 118 assert(ui);
elene@9 119
elene@9 120 ui->set_main_gfx_window(glutGetWindow());
elene@9 121
elene@9 122 GLUI_Spinner *thres_spin = ui->add_spinner("iso threshold", GLUI_SPINNER_FLOAT, &thres, 0, thres_change);
elene@9 123 thres_spin->set_float_limits(0, 1);
elene@9 124
elene@9 125 GLUI_Panel *res_panel = ui->add_panel("volume resolution");
elene@9 126
elene@9 127 ui->add_checkbox_to_panel(res_panel, "original resolution", &use_orig_vol_res, 0, toggle_use_orig);
elene@9 128
elene@9 129 static const char *res_spin_name[] = {"x", "y", "z"};
elene@9 130 for(int i=0; i<3; i++) {
elene@9 131 res_spin[i] = ui->add_spinner_to_panel(res_panel, res_spin_name[i], GLUI_SPINNER_INT, vol_res + i);
elene@9 132 res_spin[i]->set_int_limits(8, 256); // TODO limits as arguments or config
elene@9 133 res_spin[i]->disable();
elene@9 134 }
elene@9 135
elene@9 136 return ui;
elene@9 137 }
elene@9 138
elene@10 139 static void display(void)
eleni@0 140 {
elene@9 141 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
elene@9 142
elene@9 143 glMatrixMode(GL_MODELVIEW);
elene@9 144 glLoadIdentity();
elene@9 145 glTranslatef(0, 0, -cam_dist);
elene@9 146 glRotatef(cam_phi, 1, 0, 0);
elene@9 147 glRotatef(cam_theta, 0, 1, 0);
elene@9 148
elene@9 149 /*
elene@6 150 glBindTexture(GL_TEXTURE_3D, vol->get_texture());
elene@6 151 glEnable(GL_TEXTURE_3D);
eleni@1 152 glBegin(GL_QUADS);
elene@6 153 glTexCoord3f(0, 0, cur_z); glVertex3f(-1, -1, 0);
elene@6 154 glTexCoord3f(0, 1, cur_z); glVertex3f(-1, 1, 0);
elene@6 155 glTexCoord3f(1, 1, cur_z); glVertex3f(1, 1, 0);
elene@6 156 glTexCoord3f(1, 0, cur_z); glVertex3f(1, -1, 0);
eleni@1 157 glEnd();
elene@6 158 glDisable(GL_TEXTURE_3D);
elene@9 159 */
eleni@0 160
elene@9 161 if(mesh->is_empty()) {
elene@9 162 printf("recalculating isosurface ... ");
elene@9 163 fflush(stdout);
elene@9 164 vol->create_mesh(mesh, thres);
elene@9 165 printf("done.\n");
elene@9 166 }
elene@9 167 mesh->draw();
elene@9 168
elene@9 169 //TODO: draw threshold
eleni@0 170 glutSwapBuffers();
eleni@0 171 assert(glGetError() == GL_NO_ERROR);
eleni@0 172 }
eleni@0 173
elene@10 174 static void reshape(int x, int y)
eleni@0 175 {
eleni@0 176 glViewport(0, 0, x, y);
elene@9 177 glMatrixMode(GL_PROJECTION);
elene@9 178 glLoadIdentity();
elene@9 179 gluPerspective(45, (float)x / (float)y, 0.5, 500);
elene@9 180
eleni@0 181 if(x != win_xsz || y != win_ysz) {
eleni@0 182 win_xsz = x;
eleni@0 183 win_ysz = y;
eleni@0 184 }
eleni@0 185 }
eleni@0 186
elene@10 187 static void keyboard(unsigned char key, int x, int y)
eleni@0 188 {
elene@9 189 key_state[(int)key] = true;
elene@9 190
eleni@0 191 switch(key) {
eleni@0 192 case 27:
eleni@0 193 exit(0);
elene@9 194 case 'w':
elene@9 195 {
elene@9 196 static bool wire;
elene@9 197 wire = !wire;
elene@9 198 glPolygonMode(GL_FRONT_AND_BACK, wire ? GL_LINE : GL_FILL);
elene@9 199 }
elene@9 200 break;
eleni@0 201 default:
eleni@0 202 break;
eleni@0 203 }
eleni@0 204 }
eleni@0 205
elene@10 206 static void keyboard_up(unsigned char key, int x, int y)
elene@9 207 {
elene@9 208 key_state[(int) key] = false;
elene@9 209 }
elene@9 210
eleni@0 211 static int prev_x, prev_y;
elene@9 212 static bool bn_state[32];
elene@9 213 static float prev_thres;
elene@9 214
elene@10 215 static void mouse(int bn, int state, int x, int y)
eleni@0 216 {
eleni@0 217 prev_x = x;
eleni@0 218 prev_y = y;
elene@9 219
elene@9 220 bn_state[bn - GLUT_LEFT_BUTTON] = (state == GLUT_DOWN);
elene@9 221
elene@9 222 if(state == GLUT_DOWN) {
elene@9 223 prev_thres = thres;
elene@9 224 }
elene@9 225 else {
elene@9 226 if(thres != prev_thres) {
elene@9 227 mesh->clear();
elene@9 228 }
elene@9 229 }
eleni@0 230 }
eleni@0 231
elene@10 232 static void motion(int x, int y)
eleni@0 233 {
eleni@0 234 int dx = x - prev_x;
eleni@0 235 int dy = y - prev_y;
elene@9 236
elene@9 237 if(!dx && !dy)
elene@9 238 return;
elene@9 239
eleni@0 240 prev_x = x;
eleni@0 241 prev_y = y;
elene@6 242
elene@9 243 if(key_state[(int)'t']) {
elene@9 244 thres = (float)x / (float)win_xsz;
elene@9 245 printf("threshold: %f\n", thres);
elene@9 246
elene@9 247 glutPostRedisplay();
elene@9 248 return;
elene@9 249 }
elene@9 250
elene@9 251 // camera
elene@9 252 if(bn_state[0]) {
elene@9 253 if(key_state[(int)'z']) {
elene@9 254 //zoom the camera
elene@9 255
elene@9 256 cam_dist += dy * 0.1;
elene@9 257
elene@9 258 if(cam_dist < 0)
elene@9 259 cam_dist = 0;
elene@9 260 }
elene@9 261 else {
elene@9 262 //rotate the camera
elene@9 263
elene@9 264 cam_phi += dy * 0.5;
elene@9 265 cam_theta += dx * 0.5;
elene@9 266
elene@9 267 if(cam_phi > 90)
elene@9 268 cam_phi = 90;
elene@9 269 if(cam_phi < -90)
elene@9 270 cam_phi = -90;
elene@9 271 }
elene@9 272
elene@6 273 glutPostRedisplay();
elene@6 274 }
eleni@0 275 }