glviewvol

annotate src/dicomview.cc @ 10:89efc666105c

mostly done
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 31 Dec 2014 05:21:47 +0200
parents fb6d93471352
children
rev   line source
nuclear@3 1 #include <stdio.h>
nuclear@4 2 #include <stdlib.h>
nuclear@0 3 #include "opengl.h"
nuclear@0 4 #include "dicomview.h"
nuclear@1 5 #include "rend_fast.h"
nuclear@3 6 #include "opt.h"
nuclear@3 7 #include "volume.h"
nuclear@4 8 #include "xfer_view.h"
nuclear@0 9
nuclear@1 10 static int win_width, win_height;
nuclear@8 11 static float cam_theta, cam_phi, cam_dist = 4;
nuclear@8 12 static float pre_rot = -90;
nuclear@4 13 static int splitter_y = -1;
nuclear@4 14
nuclear@4 15 #define SPLITTER_WIDTH 5
nuclear@0 16
nuclear@1 17 static Renderer *rend;
nuclear@3 18 static Volume *vol;
nuclear@6 19 static TransferFunc *xfer;
nuclear@1 20
nuclear@0 21 extern "C" {
nuclear@0 22
nuclear@0 23 int init()
nuclear@0 24 {
nuclear@3 25 if(!opt.fname) {
nuclear@3 26 fprintf(stderr, "you must specify the volume data filename\n");
nuclear@1 27 return -1;
nuclear@1 28 }
nuclear@1 29
nuclear@3 30 switch(opt.rend_type) {
nuclear@3 31 case REND_FAST:
nuclear@3 32 rend = new RendererFast;
nuclear@3 33 break;
nuclear@3 34 default:
nuclear@3 35 return -1;
nuclear@3 36 }
nuclear@3 37
nuclear@3 38 if(!rend->init()) {
nuclear@3 39 fprintf(stderr, "renderer initialization failed\n");
nuclear@3 40 return -1;
nuclear@3 41 }
nuclear@3 42
nuclear@3 43 VoxelVolume *voxvol = new VoxelVolume;
nuclear@3 44 if(!voxvol->load(opt.fname)) {
nuclear@3 45 fprintf(stderr, "failed to load volume data from: %s\n", opt.fname);
nuclear@3 46 return -1;
nuclear@3 47 }
nuclear@3 48 vol = voxvol;
nuclear@3 49 rend->set_volume(vol);
nuclear@3 50
nuclear@6 51 xfer = new TransferWindow;
nuclear@6 52 rend->set_transfer_function(xfer);
nuclear@6 53
nuclear@6 54 if(!xfview_init(xfer)) {
nuclear@4 55 return -1;
nuclear@4 56 }
nuclear@4 57
nuclear@1 58 return 0;
nuclear@0 59 }
nuclear@0 60
nuclear@0 61 void cleanup()
nuclear@0 62 {
nuclear@4 63 xfview_destroy();
nuclear@4 64
nuclear@1 65 rend->destroy();
nuclear@1 66 delete rend;
nuclear@3 67 delete vol;
nuclear@6 68 delete xfer;
nuclear@0 69 }
nuclear@0 70
nuclear@0 71 void ev_display()
nuclear@0 72 {
nuclear@0 73 glClear(GL_COLOR_BUFFER_BIT);
nuclear@1 74
nuclear@4 75 // render the main view
nuclear@4 76 glViewport(0, win_height - splitter_y, win_width, splitter_y);
nuclear@4 77
nuclear@4 78 glMatrixMode(GL_PROJECTION);
nuclear@4 79 glLoadIdentity();
nuclear@4 80 gluPerspective(50.0, (float)win_width / (float)splitter_y, 0.1, 100.0);
nuclear@4 81
nuclear@4 82 glMatrixMode(GL_MODELVIEW);
nuclear@4 83 glLoadIdentity();
nuclear@4 84 glTranslatef(0, 0, -cam_dist);
nuclear@8 85 glRotatef(cam_phi + pre_rot, 1, 0, 0);
nuclear@4 86 glRotatef(cam_theta, 0, 1, 0);
nuclear@4 87
nuclear@1 88 rend->update(0);
nuclear@1 89 rend->render();
nuclear@4 90
nuclear@4 91 // draw the transfer function view
nuclear@4 92 glViewport(0, 0, win_width, win_height - splitter_y);
nuclear@4 93
nuclear@4 94 xfview_draw();
nuclear@4 95
nuclear@4 96 // draw the GUI
nuclear@4 97 glViewport(0, 0, win_width, win_height);
nuclear@4 98
nuclear@4 99 glMatrixMode(GL_PROJECTION);
nuclear@4 100 glLoadIdentity();
nuclear@4 101 glOrtho(0, win_width, win_height, 0, -1, 1);
nuclear@4 102
nuclear@4 103 glMatrixMode(GL_MODELVIEW);
nuclear@4 104 glLoadIdentity();
nuclear@4 105
nuclear@4 106 glBegin(GL_QUADS);
nuclear@4 107 glColor3f(1, 1, 1);
nuclear@4 108 glVertex2f(0, splitter_y + SPLITTER_WIDTH / 2);
nuclear@4 109 glVertex2f(win_width, splitter_y + SPLITTER_WIDTH / 2);
nuclear@4 110 glVertex2f(win_width, splitter_y - SPLITTER_WIDTH / 2);
nuclear@4 111 glVertex2f(0, splitter_y - SPLITTER_WIDTH / 2);
nuclear@4 112 glEnd();
nuclear@4 113
nuclear@4 114 swap_buffers();
nuclear@0 115 }
nuclear@0 116
nuclear@0 117 void ev_reshape(int x, int y)
nuclear@0 118 {
nuclear@4 119 if(splitter_y < 0) { // not initialized yet
nuclear@4 120 splitter_y = (int)(y * 0.85);
nuclear@4 121 } else {
nuclear@4 122 // calculate where the splitter was relative to the window height
nuclear@4 123 // and based on that, it's new position
nuclear@4 124 float split = (float)splitter_y / (float)win_height;
nuclear@4 125 splitter_y = (int)(y * split);
nuclear@4 126 }
nuclear@4 127
nuclear@0 128 win_width = x;
nuclear@0 129 win_height = y;
nuclear@0 130
nuclear@1 131 glViewport(0, 0, x, y);
nuclear@4 132 if(rend) {
nuclear@4 133 rend->reshape(x, y);
nuclear@4 134 }
nuclear@0 135 }
nuclear@0 136
nuclear@10 137 static bool zscaling;
nuclear@10 138
nuclear@1 139 void ev_keyboard(int key, int press, int x, int y)
nuclear@1 140 {
nuclear@8 141 RendererFast *fr;
nuclear@8 142
nuclear@10 143 switch(key) {
nuclear@10 144 case 27:
nuclear@10 145 if(press) {
nuclear@1 146 quit();
nuclear@10 147 }
nuclear@10 148 break;
nuclear@8 149
nuclear@10 150 case 'z':
nuclear@10 151 case 'Z':
nuclear@10 152 zscaling = press;
nuclear@10 153 break;
nuclear@10 154
nuclear@10 155 case '=':
nuclear@10 156 if(press && (fr = dynamic_cast<RendererFast*>(rend))) {
nuclear@10 157 int n = fr->get_proxy_count();
nuclear@10 158 int add = n / 4;
nuclear@10 159 n += add < 1 ? 1 : add;
nuclear@10 160 printf("proxy count: %d\n", n);
nuclear@10 161 fr->set_proxy_count(n);
nuclear@8 162 redisplay();
nuclear@10 163 }
nuclear@10 164 break;
nuclear@8 165
nuclear@10 166 case '-':
nuclear@10 167 if(press && (fr = dynamic_cast<RendererFast*>(rend))) {
nuclear@10 168 int n = fr->get_proxy_count();
nuclear@10 169 int sub = n / 4;
nuclear@10 170 n -= sub < 1 ? 1 : sub;
nuclear@8 171
nuclear@10 172 if(n < 1) n = 1;
nuclear@8 173
nuclear@10 174 printf("proxy count: %d\n", n);
nuclear@10 175 fr->set_proxy_count(n);
nuclear@8 176 redisplay();
nuclear@10 177 }
nuclear@10 178 break;
nuclear@8 179
nuclear@10 180 default:
nuclear@10 181 break;
nuclear@1 182 }
nuclear@1 183 }
nuclear@1 184
nuclear@4 185 static bool bnstate[8];
nuclear@4 186 static int prev_x, prev_y;
nuclear@4 187
nuclear@4 188 #define ON_SPLITTER(y) (abs(y - splitter_y) <= SPLITTER_WIDTH / 2)
nuclear@4 189 static bool splitter_dragging;
nuclear@4 190
nuclear@1 191 void ev_mouse_button(int bn, int press, int x, int y)
nuclear@1 192 {
nuclear@4 193 bnstate[bn] = press != 0;
nuclear@4 194 prev_x = x;
nuclear@4 195 prev_y = y;
nuclear@4 196
nuclear@4 197 splitter_dragging = bn == 0 && press && ON_SPLITTER(y);
nuclear@4 198
nuclear@4 199 if(!splitter_dragging && y > splitter_y) {
nuclear@4 200 xfview_button(bn, press, x, y);
nuclear@4 201 }
nuclear@1 202 }
nuclear@1 203
nuclear@1 204 void ev_mouse_motion(int x, int y)
nuclear@1 205 {
nuclear@4 206 int dx = x - prev_x;
nuclear@4 207 int dy = y - prev_y;
nuclear@4 208 prev_x = x;
nuclear@4 209 prev_y = y;
nuclear@4 210
nuclear@4 211 if((dx | dy) == 0) return;
nuclear@4 212
nuclear@10 213 if(bnstate[0] && zscaling) {
nuclear@10 214 float s = rend->get_zscale() + (float)dy / (float)win_height;
nuclear@10 215 rend->set_zscale(s < 0.0 ? 0.0 : s);
nuclear@10 216 redisplay();
nuclear@10 217 return;
nuclear@10 218 }
nuclear@10 219
nuclear@4 220 if(splitter_dragging) {
nuclear@4 221 splitter_y += dy;
nuclear@4 222 redisplay();
nuclear@4 223 return;
nuclear@4 224 }
nuclear@4 225
nuclear@4 226 if(y > splitter_y) {
nuclear@4 227 xfview_motion(x, y);
nuclear@4 228 return;
nuclear@4 229 }
nuclear@4 230
nuclear@4 231 // main view motion handling
nuclear@4 232 if(bnstate[0]) {
nuclear@4 233 cam_theta += dx * 0.5;
nuclear@4 234 cam_phi += dy * 0.5;
nuclear@4 235
nuclear@4 236 if(cam_phi < -90) cam_phi = -90;
nuclear@4 237 if(cam_phi > 90) cam_phi = 90;
nuclear@4 238 redisplay();
nuclear@4 239 }
nuclear@4 240 if(bnstate[2]) {
nuclear@4 241 cam_dist += dy * 0.1;
nuclear@4 242
nuclear@4 243 if(cam_dist < 0.0) cam_dist = 0.0;
nuclear@4 244 redisplay();
nuclear@4 245 }
nuclear@1 246 }
nuclear@0 247
nuclear@0 248 } // extern "C"