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@0
|
11 static float cam_theta, cam_phi, cam_dist = 6;
|
nuclear@4
|
12 static int splitter_y = -1;
|
nuclear@4
|
13
|
nuclear@4
|
14 #define SPLITTER_WIDTH 5
|
nuclear@0
|
15
|
nuclear@1
|
16 static Renderer *rend;
|
nuclear@3
|
17 static Volume *vol;
|
nuclear@1
|
18
|
nuclear@0
|
19 extern "C" {
|
nuclear@0
|
20
|
nuclear@0
|
21 int init()
|
nuclear@0
|
22 {
|
nuclear@3
|
23 if(!opt.fname) {
|
nuclear@3
|
24 fprintf(stderr, "you must specify the volume data filename\n");
|
nuclear@1
|
25 return -1;
|
nuclear@1
|
26 }
|
nuclear@1
|
27
|
nuclear@3
|
28 switch(opt.rend_type) {
|
nuclear@3
|
29 case REND_FAST:
|
nuclear@3
|
30 rend = new RendererFast;
|
nuclear@3
|
31 break;
|
nuclear@3
|
32 default:
|
nuclear@3
|
33 return -1;
|
nuclear@3
|
34 }
|
nuclear@3
|
35
|
nuclear@3
|
36 if(!rend->init()) {
|
nuclear@3
|
37 fprintf(stderr, "renderer initialization failed\n");
|
nuclear@3
|
38 return -1;
|
nuclear@3
|
39 }
|
nuclear@3
|
40
|
nuclear@3
|
41 VoxelVolume *voxvol = new VoxelVolume;
|
nuclear@3
|
42 if(!voxvol->load(opt.fname)) {
|
nuclear@3
|
43 fprintf(stderr, "failed to load volume data from: %s\n", opt.fname);
|
nuclear@3
|
44 return -1;
|
nuclear@3
|
45 }
|
nuclear@3
|
46 vol = voxvol;
|
nuclear@3
|
47 rend->set_volume(vol);
|
nuclear@3
|
48
|
nuclear@4
|
49 if(!xfview_init(rend)) {
|
nuclear@4
|
50 return -1;
|
nuclear@4
|
51 }
|
nuclear@4
|
52
|
nuclear@1
|
53 return 0;
|
nuclear@0
|
54 }
|
nuclear@0
|
55
|
nuclear@0
|
56 void cleanup()
|
nuclear@0
|
57 {
|
nuclear@4
|
58 xfview_destroy();
|
nuclear@4
|
59
|
nuclear@1
|
60 rend->destroy();
|
nuclear@1
|
61 delete rend;
|
nuclear@3
|
62 delete vol;
|
nuclear@0
|
63 }
|
nuclear@0
|
64
|
nuclear@0
|
65 void ev_display()
|
nuclear@0
|
66 {
|
nuclear@0
|
67 glClear(GL_COLOR_BUFFER_BIT);
|
nuclear@1
|
68
|
nuclear@4
|
69 // render the main view
|
nuclear@4
|
70 glViewport(0, win_height - splitter_y, win_width, splitter_y);
|
nuclear@4
|
71
|
nuclear@4
|
72 glMatrixMode(GL_PROJECTION);
|
nuclear@4
|
73 glLoadIdentity();
|
nuclear@4
|
74 gluPerspective(50.0, (float)win_width / (float)splitter_y, 0.1, 100.0);
|
nuclear@4
|
75
|
nuclear@4
|
76 glMatrixMode(GL_MODELVIEW);
|
nuclear@4
|
77 glLoadIdentity();
|
nuclear@4
|
78 glTranslatef(0, 0, -cam_dist);
|
nuclear@4
|
79 glRotatef(cam_phi, 1, 0, 0);
|
nuclear@4
|
80 glRotatef(cam_theta, 0, 1, 0);
|
nuclear@4
|
81
|
nuclear@1
|
82 rend->update(0);
|
nuclear@1
|
83 rend->render();
|
nuclear@4
|
84
|
nuclear@4
|
85 // draw the transfer function view
|
nuclear@4
|
86 glViewport(0, 0, win_width, win_height - splitter_y);
|
nuclear@4
|
87
|
nuclear@4
|
88 xfview_draw();
|
nuclear@4
|
89
|
nuclear@4
|
90 // draw the GUI
|
nuclear@4
|
91 glViewport(0, 0, win_width, win_height);
|
nuclear@4
|
92
|
nuclear@4
|
93 glMatrixMode(GL_PROJECTION);
|
nuclear@4
|
94 glLoadIdentity();
|
nuclear@4
|
95 glOrtho(0, win_width, win_height, 0, -1, 1);
|
nuclear@4
|
96
|
nuclear@4
|
97 glMatrixMode(GL_MODELVIEW);
|
nuclear@4
|
98 glLoadIdentity();
|
nuclear@4
|
99
|
nuclear@4
|
100 glBegin(GL_QUADS);
|
nuclear@4
|
101 glColor3f(1, 1, 1);
|
nuclear@4
|
102 glVertex2f(0, splitter_y + SPLITTER_WIDTH / 2);
|
nuclear@4
|
103 glVertex2f(win_width, splitter_y + SPLITTER_WIDTH / 2);
|
nuclear@4
|
104 glVertex2f(win_width, splitter_y - SPLITTER_WIDTH / 2);
|
nuclear@4
|
105 glVertex2f(0, splitter_y - SPLITTER_WIDTH / 2);
|
nuclear@4
|
106 glEnd();
|
nuclear@4
|
107
|
nuclear@4
|
108 swap_buffers();
|
nuclear@0
|
109 }
|
nuclear@0
|
110
|
nuclear@0
|
111 void ev_reshape(int x, int y)
|
nuclear@0
|
112 {
|
nuclear@4
|
113 if(splitter_y < 0) { // not initialized yet
|
nuclear@4
|
114 splitter_y = (int)(y * 0.85);
|
nuclear@4
|
115 } else {
|
nuclear@4
|
116 // calculate where the splitter was relative to the window height
|
nuclear@4
|
117 // and based on that, it's new position
|
nuclear@4
|
118 float split = (float)splitter_y / (float)win_height;
|
nuclear@4
|
119 splitter_y = (int)(y * split);
|
nuclear@4
|
120 }
|
nuclear@4
|
121
|
nuclear@0
|
122 win_width = x;
|
nuclear@0
|
123 win_height = y;
|
nuclear@0
|
124
|
nuclear@1
|
125 glViewport(0, 0, x, y);
|
nuclear@4
|
126 if(rend) {
|
nuclear@4
|
127 rend->reshape(x, y);
|
nuclear@4
|
128 }
|
nuclear@0
|
129 }
|
nuclear@0
|
130
|
nuclear@1
|
131 void ev_keyboard(int key, int press, int x, int y)
|
nuclear@1
|
132 {
|
nuclear@1
|
133 if(press) {
|
nuclear@1
|
134 switch(key) {
|
nuclear@1
|
135 case 27:
|
nuclear@1
|
136 quit();
|
nuclear@1
|
137 }
|
nuclear@1
|
138 }
|
nuclear@1
|
139 }
|
nuclear@1
|
140
|
nuclear@4
|
141 static bool bnstate[8];
|
nuclear@4
|
142 static int prev_x, prev_y;
|
nuclear@4
|
143
|
nuclear@4
|
144 #define ON_SPLITTER(y) (abs(y - splitter_y) <= SPLITTER_WIDTH / 2)
|
nuclear@4
|
145 static bool splitter_dragging;
|
nuclear@4
|
146
|
nuclear@1
|
147 void ev_mouse_button(int bn, int press, int x, int y)
|
nuclear@1
|
148 {
|
nuclear@4
|
149 bnstate[bn] = press != 0;
|
nuclear@4
|
150 prev_x = x;
|
nuclear@4
|
151 prev_y = y;
|
nuclear@4
|
152
|
nuclear@4
|
153 splitter_dragging = bn == 0 && press && ON_SPLITTER(y);
|
nuclear@4
|
154
|
nuclear@4
|
155 if(!splitter_dragging && y > splitter_y) {
|
nuclear@4
|
156 xfview_button(bn, press, x, y);
|
nuclear@4
|
157 }
|
nuclear@1
|
158 }
|
nuclear@1
|
159
|
nuclear@1
|
160 void ev_mouse_motion(int x, int y)
|
nuclear@1
|
161 {
|
nuclear@4
|
162 int dx = x - prev_x;
|
nuclear@4
|
163 int dy = y - prev_y;
|
nuclear@4
|
164 prev_x = x;
|
nuclear@4
|
165 prev_y = y;
|
nuclear@4
|
166
|
nuclear@4
|
167 if((dx | dy) == 0) return;
|
nuclear@4
|
168
|
nuclear@4
|
169 if(splitter_dragging) {
|
nuclear@4
|
170 splitter_y += dy;
|
nuclear@4
|
171 redisplay();
|
nuclear@4
|
172 return;
|
nuclear@4
|
173 }
|
nuclear@4
|
174
|
nuclear@4
|
175 if(y > splitter_y) {
|
nuclear@4
|
176 xfview_motion(x, y);
|
nuclear@4
|
177 return;
|
nuclear@4
|
178 }
|
nuclear@4
|
179
|
nuclear@4
|
180 // main view motion handling
|
nuclear@4
|
181 if(bnstate[0]) {
|
nuclear@4
|
182 cam_theta += dx * 0.5;
|
nuclear@4
|
183 cam_phi += dy * 0.5;
|
nuclear@4
|
184
|
nuclear@4
|
185 if(cam_phi < -90) cam_phi = -90;
|
nuclear@4
|
186 if(cam_phi > 90) cam_phi = 90;
|
nuclear@4
|
187 redisplay();
|
nuclear@4
|
188 }
|
nuclear@4
|
189 if(bnstate[2]) {
|
nuclear@4
|
190 cam_dist += dy * 0.1;
|
nuclear@4
|
191
|
nuclear@4
|
192 if(cam_dist < 0.0) cam_dist = 0.0;
|
nuclear@4
|
193 redisplay();
|
nuclear@4
|
194 }
|
nuclear@1
|
195 }
|
nuclear@0
|
196
|
nuclear@0
|
197 } // extern "C"
|