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"
|