glviewvol

view src/viewer.cc @ 12:773f89037a35

added copyright headers
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 31 Dec 2014 07:57:04 +0200
parents 73edd1b7c2da
children 0d2447b9c512
line source
1 /*
2 glviewvol is an OpenGL 3D volume data viewer
3 Copyright (C) 2014 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include "opengl.h"
21 #include "viewer.h"
22 #include "rend_fast.h"
23 #include "opt.h"
24 #include "volume.h"
25 #include "xfer_view.h"
27 static int win_width, win_height;
28 static float cam_theta, cam_phi, cam_dist = 4;
29 static float pre_rot = -90;
30 static int splitter_y = -1;
32 #define SPLITTER_WIDTH 5
34 static Renderer *rend;
35 static Volume *vol;
36 static TransferFunc *xfer;
38 extern "C" {
40 int init()
41 {
42 if(!opt.fname) {
43 fprintf(stderr, "you must specify the volume data filename\n");
44 return -1;
45 }
47 switch(opt.rend_type) {
48 case REND_FAST:
49 rend = new RendererFast;
50 break;
51 default:
52 return -1;
53 }
55 if(!rend->init()) {
56 fprintf(stderr, "renderer initialization failed\n");
57 return -1;
58 }
60 VoxelVolume *voxvol = new VoxelVolume;
61 if(!voxvol->load(opt.fname)) {
62 fprintf(stderr, "failed to load volume data from: %s\n", opt.fname);
63 return -1;
64 }
65 vol = voxvol;
66 rend->set_volume(vol);
68 xfer = new TransferWindow;
69 rend->set_transfer_function(xfer);
71 if(!xfview_init(xfer)) {
72 return -1;
73 }
75 return 0;
76 }
78 void cleanup()
79 {
80 xfview_destroy();
82 rend->destroy();
83 delete rend;
84 delete vol;
85 delete xfer;
86 }
88 void ev_display()
89 {
90 glClear(GL_COLOR_BUFFER_BIT);
92 // render the main view
93 glViewport(0, win_height - splitter_y, win_width, splitter_y);
95 glMatrixMode(GL_PROJECTION);
96 glLoadIdentity();
97 gluPerspective(50.0, (float)win_width / (float)splitter_y, 0.1, 100.0);
99 glMatrixMode(GL_MODELVIEW);
100 glLoadIdentity();
101 glTranslatef(0, 0, -cam_dist);
102 glRotatef(cam_phi + pre_rot, 1, 0, 0);
103 glRotatef(cam_theta, 0, 1, 0);
105 rend->update(0);
106 rend->render();
108 // draw the transfer function view
109 glViewport(0, 0, win_width, win_height - splitter_y);
111 xfview_draw();
113 // draw the GUI
114 glViewport(0, 0, win_width, win_height);
116 glMatrixMode(GL_PROJECTION);
117 glLoadIdentity();
118 glOrtho(0, win_width, win_height, 0, -1, 1);
120 glMatrixMode(GL_MODELVIEW);
121 glLoadIdentity();
123 glBegin(GL_QUADS);
124 glColor3f(1, 1, 1);
125 glVertex2f(0, splitter_y + SPLITTER_WIDTH / 2);
126 glVertex2f(win_width, splitter_y + SPLITTER_WIDTH / 2);
127 glVertex2f(win_width, splitter_y - SPLITTER_WIDTH / 2);
128 glVertex2f(0, splitter_y - SPLITTER_WIDTH / 2);
129 glEnd();
131 swap_buffers();
132 }
134 void ev_reshape(int x, int y)
135 {
136 if(splitter_y < 0) { // not initialized yet
137 splitter_y = (int)(y * 0.85);
138 } else {
139 // calculate where the splitter was relative to the window height
140 // and based on that, it's new position
141 float split = (float)splitter_y / (float)win_height;
142 splitter_y = (int)(y * split);
143 }
145 win_width = x;
146 win_height = y;
148 glViewport(0, 0, x, y);
149 if(rend) {
150 rend->reshape(x, y);
151 }
152 }
154 static bool zscaling;
156 void ev_keyboard(int key, int press, int x, int y)
157 {
158 RendererFast *fr;
160 switch(key) {
161 case 27:
162 if(press) {
163 quit();
164 }
165 break;
167 case 'z':
168 case 'Z':
169 zscaling = press;
170 break;
172 case '=':
173 if(press && (fr = dynamic_cast<RendererFast*>(rend))) {
174 int n = fr->get_proxy_count();
175 int add = n / 4;
176 n += add < 1 ? 1 : add;
177 printf("proxy count: %d\n", n);
178 fr->set_proxy_count(n);
179 redisplay();
180 }
181 break;
183 case '-':
184 if(press && (fr = dynamic_cast<RendererFast*>(rend))) {
185 int n = fr->get_proxy_count();
186 int sub = n / 4;
187 n -= sub < 1 ? 1 : sub;
189 if(n < 1) n = 1;
191 printf("proxy count: %d\n", n);
192 fr->set_proxy_count(n);
193 redisplay();
194 }
195 break;
197 default:
198 break;
199 }
200 }
202 static bool bnstate[8];
203 static int prev_x, prev_y;
205 #define ON_SPLITTER(y) (abs(y - splitter_y) <= SPLITTER_WIDTH / 2)
206 static bool splitter_dragging;
208 void ev_mouse_button(int bn, int press, int x, int y)
209 {
210 bnstate[bn] = press != 0;
211 prev_x = x;
212 prev_y = y;
214 splitter_dragging = bn == 0 && press && ON_SPLITTER(y);
216 if(!splitter_dragging && y > splitter_y) {
217 xfview_button(bn, press, x, y);
218 }
219 }
221 void ev_mouse_motion(int x, int y)
222 {
223 int dx = x - prev_x;
224 int dy = y - prev_y;
225 prev_x = x;
226 prev_y = y;
228 if((dx | dy) == 0) return;
230 if(bnstate[0] && zscaling) {
231 float s = rend->get_zscale() + (float)dy / (float)win_height;
232 rend->set_zscale(s < 0.0 ? 0.0 : s);
233 redisplay();
234 return;
235 }
237 if(splitter_dragging) {
238 splitter_y += dy;
239 redisplay();
240 return;
241 }
243 if(y > splitter_y) {
244 xfview_motion(x, y);
245 return;
246 }
248 // main view motion handling
249 if(bnstate[0]) {
250 cam_theta += dx * 0.5;
251 cam_phi += dy * 0.5;
253 if(cam_phi < -90) cam_phi = -90;
254 if(cam_phi > 90) cam_phi = 90;
255 redisplay();
256 }
257 if(bnstate[2]) {
258 cam_dist += dy * 0.1;
260 if(cam_dist < 0.0) cam_dist = 0.0;
261 redisplay();
262 }
263 }
265 } // extern "C"