glviewvol

annotate src/viewer.cc @ 14:0d2447b9c512

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