glviewvol

annotate src/xfer_view.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@4 18 #include <stdio.h>
nuclear@7 19 #include <math.h>
nuclear@4 20 #include "opengl.h"
nuclear@4 21 #include "xfer_view.h"
nuclear@11 22 #include "viewer.h"
nuclear@14 23 #include "volume.h"
nuclear@14 24
nuclear@14 25 static void draw_histogram();
nuclear@4 26
nuclear@6 27 static TransferFunc *xfer;
nuclear@14 28 static Volume *vol;
nuclear@4 29
nuclear@7 30 static int act_color = -1;
nuclear@7 31 static int grabbed_handle = -1;
nuclear@7 32 static int mousex, mousey;
nuclear@4 33
nuclear@6 34 bool xfview_init(TransferFunc *xferarg)
nuclear@4 35 {
nuclear@6 36 xfer = xferarg;
nuclear@4 37 return true;
nuclear@4 38 }
nuclear@4 39
nuclear@4 40 void xfview_destroy()
nuclear@4 41 {
nuclear@4 42 }
nuclear@4 43
nuclear@14 44 void xfview_set_volume(Volume *volarg)
nuclear@14 45 {
nuclear@14 46 vol = volarg;
nuclear@14 47 }
nuclear@14 48
nuclear@4 49 void xfview_draw()
nuclear@4 50 {
nuclear@4 51 float line_color[][3] = {
nuclear@4 52 { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 1, 1, 1 }
nuclear@4 53 };
nuclear@4 54
nuclear@4 55 glMatrixMode(GL_PROJECTION);
nuclear@4 56 glLoadIdentity();
nuclear@7 57 glOrtho(0, 1, 0, 1, -1, 1);
nuclear@7 58
nuclear@4 59 glMatrixMode(GL_MODELVIEW);
nuclear@4 60 glLoadIdentity();
nuclear@4 61
nuclear@4 62 int xsz, ysz;
nuclear@4 63 get_window_size(&xsz, &ysz);
nuclear@4 64 int nsamples = xsz / 4;
nuclear@4 65
nuclear@4 66 // paint the background a faint version of the selected color
nuclear@4 67 glBegin(GL_QUADS);
nuclear@7 68 int cidx = act_color == -1 ? 3 : act_color;
nuclear@7 69 glColor3f(line_color[cidx][0] * 0.1, line_color[cidx][1] * 0.1, line_color[cidx][2] * 0.1);
nuclear@4 70 glVertex2f(-1, -1);
nuclear@4 71 glVertex2f(1, -1);
nuclear@4 72 glVertex2f(1, 1);
nuclear@4 73 glVertex2f(-1, 1);
nuclear@4 74 glEnd();
nuclear@4 75
nuclear@14 76 draw_histogram();
nuclear@14 77
nuclear@4 78 glEnable(GL_LINE_SMOOTH);
nuclear@4 79
nuclear@4 80 glEnable(GL_BLEND);
nuclear@4 81 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
nuclear@4 82
nuclear@7 83 // draw handles on the selected curve
nuclear@7 84 TransferWindow *xfwin = dynamic_cast<TransferWindow*>(xfer);
nuclear@7 85 if(xfwin) {
nuclear@7 86 float dx = 1.0 / (float)xsz;
nuclear@7 87 float cursor = (float)mousex / (float)xsz;
nuclear@7 88 float low[3], high[3];
nuclear@7 89 xfwin->get_interval_rgba(low, high);
nuclear@7 90
nuclear@7 91 if(act_color == -1) { // all curves
nuclear@7 92 int nearest = xfwin->nearest_handle(-1, cursor);
nuclear@7 93
nuclear@7 94 if(grabbed_handle != -1) {
nuclear@7 95 glBegin(GL_LINES);
nuclear@7 96 glColor3f(0.8, 0.8, 0.8);
nuclear@7 97 for(int i=0; i<3; i++) {
nuclear@7 98 float x = xfwin->get_handle(i, nearest);
nuclear@7 99 float rad = xfwin->get_soft_radius();
nuclear@7 100 glVertex2f(x - rad, 0.5);
nuclear@7 101 glVertex2f(x + rad, 0.5);
nuclear@7 102 glVertex2f(x - rad, 0.4);
nuclear@7 103 glVertex2f(x - rad, 0.6);
nuclear@7 104 glVertex2f(x + rad, 0.4);
nuclear@7 105 glVertex2f(x + rad, 0.6);
nuclear@7 106 }
nuclear@7 107 glEnd();
nuclear@7 108 }
nuclear@7 109
nuclear@7 110 // draw handles on all lines, highlighting the nearest side of all of them
nuclear@7 111 glBegin(GL_QUADS);
nuclear@7 112 glColor3f(1, 1, 1);
nuclear@7 113
nuclear@7 114 for(int i=0; i<3; i++) {
nuclear@7 115 float x = nearest == TransferWindow::HANDLE_LOW ? low[i] : high[i];
nuclear@7 116 glVertex2f(x - 2.0 * dx, -1);
nuclear@7 117 glVertex2f(x + 2.0 * dx, -1);
nuclear@7 118 glVertex2f(x + 2.0 * dx, 1);
nuclear@7 119 glVertex2f(x - 2.0 * dx, 1);
nuclear@7 120 }
nuclear@7 121 for(int i=0; i<3; i++) {
nuclear@7 122 glColor3fv(line_color[i]);
nuclear@7 123 glVertex2f(low[i] - dx, -1);
nuclear@7 124 glVertex2f(low[i] + dx, -1);
nuclear@7 125 glVertex2f(low[i] + dx, 1);
nuclear@7 126 glVertex2f(low[i] - dx, 1);
nuclear@7 127 glVertex2f(high[i] - dx, -1);
nuclear@7 128 glVertex2f(high[i] + dx, -1);
nuclear@7 129 glVertex2f(high[i] + dx, 1);
nuclear@7 130 glVertex2f(high[i] - dx, 1);
nuclear@7 131 }
nuclear@7 132 glEnd();
nuclear@7 133
nuclear@7 134 } else {
nuclear@7 135 int nearest = xfwin->nearest_handle(act_color, cursor);
nuclear@7 136 float x = nearest == TransferWindow::HANDLE_LOW ? low[act_color] : high[act_color];
nuclear@7 137
nuclear@7 138 if(grabbed_handle != -1) {
nuclear@7 139 float x = xfwin->get_handle(act_color, nearest);
nuclear@7 140 float rad = xfwin->get_soft_radius();
nuclear@7 141
nuclear@7 142 glBegin(GL_LINES);
nuclear@7 143 glColor3f(0.8, 0.8, 0.8);
nuclear@7 144 glVertex2f(x - rad, 0.5);
nuclear@7 145 glVertex2f(x + rad, 0.5);
nuclear@7 146 glVertex2f(x - rad, 0.4);
nuclear@7 147 glVertex2f(x - rad, 0.6);
nuclear@7 148 glVertex2f(x + rad, 0.4);
nuclear@7 149 glVertex2f(x + rad, 0.6);
nuclear@7 150 glEnd();
nuclear@7 151 }
nuclear@7 152
nuclear@7 153
nuclear@7 154 glBegin(GL_QUADS);
nuclear@7 155 glColor3f(1, 1, 1);
nuclear@7 156 glVertex2f(x - 2.0 * dx, -1);
nuclear@7 157 glVertex2f(x + 2.0 * dx, -1);
nuclear@7 158 glVertex2f(x + 2.0 * dx, 1);
nuclear@7 159 glVertex2f(x - 2.0 * dx, 1);
nuclear@7 160
nuclear@7 161 glColor3fv(line_color[act_color]);
nuclear@7 162 for(int i=0; i<2; i++) {
nuclear@7 163 glVertex2f(x - dx, -1);
nuclear@7 164 glVertex2f(x + dx, -1);
nuclear@7 165 glVertex2f(x + dx, 1);
nuclear@7 166 glVertex2f(x - dx, 1);
nuclear@7 167 x = nearest == TransferWindow::HANDLE_LOW ? high[act_color] : low[act_color];
nuclear@7 168 }
nuclear@7 169 glEnd();
nuclear@7 170 }
nuclear@7 171 }
nuclear@7 172
nuclear@6 173 // draw curve
nuclear@4 174 glLineWidth(2.0);
nuclear@4 175
nuclear@7 176 for(int i=0; i<4; i++) {
nuclear@4 177 int idx;
nuclear@7 178 if(act_color == -1) {
nuclear@7 179 idx = i;
nuclear@4 180 } else {
nuclear@7 181 idx = (i + act_color + 1) % 4;
nuclear@4 182 }
nuclear@4 183
nuclear@4 184 glColor3fv(line_color[idx]);
nuclear@4 185
nuclear@4 186 glBegin(GL_LINE_STRIP);
nuclear@4 187 for(int j=0; j<nsamples; j++) {
nuclear@4 188 float t = (float)j / (float)(nsamples - 1);
nuclear@6 189 float vval[4];
nuclear@4 190
nuclear@7 191 if(idx < 3) {
nuclear@7 192 xfer->map(t, vval);
nuclear@7 193 } else {
nuclear@7 194 vval[3] = xfer->map(t);
nuclear@7 195 }
nuclear@7 196
nuclear@7 197 glVertex2f(t, vval[idx]);
nuclear@4 198 }
nuclear@4 199 glEnd();
nuclear@4 200 }
nuclear@4 201
nuclear@4 202 glDisable(GL_BLEND);
nuclear@4 203 }
nuclear@4 204
nuclear@14 205 #define HIST_SAMPLES 256
nuclear@14 206
nuclear@14 207 static void draw_histogram()
nuclear@14 208 {
nuclear@14 209 VoxelVolume *voxvol = dynamic_cast<VoxelVolume*>(vol);
nuclear@14 210 if(!voxvol) return;
nuclear@14 211
nuclear@14 212 float *hist = voxvol->calc_histogram(HIST_SAMPLES);
nuclear@14 213 if(!hist) return;
nuclear@14 214
nuclear@14 215 float max_y = 0.0f;
nuclear@14 216 for(int i=0; i<HIST_SAMPLES; i++) {
nuclear@14 217 if(hist[i] > max_y) {
nuclear@14 218 max_y = hist[i];
nuclear@14 219 }
nuclear@14 220 }
nuclear@14 221
nuclear@14 222 float dx = 1.0 / (float)HIST_SAMPLES;
nuclear@14 223 glBegin(GL_QUADS);
nuclear@14 224 glColor3f(0.6, 0.6, 0.6);
nuclear@14 225 for(int i=0; i<HIST_SAMPLES; i++) {
nuclear@14 226 float x0 = (float)i / (float)HIST_SAMPLES;
nuclear@14 227 float x1 = x0 + dx;
nuclear@14 228
nuclear@14 229 float y = hist[i] / max_y;
nuclear@14 230
nuclear@14 231 glVertex2f(x0, 0);
nuclear@14 232 glVertex2f(x1, 0);
nuclear@14 233 glVertex2f(x1, y);
nuclear@14 234 glVertex2f(x0, y);
nuclear@14 235 }
nuclear@14 236 glEnd();
nuclear@14 237 }
nuclear@14 238
nuclear@7 239 static int prev_x, prev_y;
nuclear@7 240
nuclear@4 241 void xfview_button(int bn, int press, int x, int y)
nuclear@4 242 {
nuclear@7 243 prev_x = x;
nuclear@7 244 prev_y = y;
nuclear@7 245
nuclear@7 246 if(bn == 2 && press && grabbed_handle == -1) {
nuclear@7 247 act_color = (act_color + 2) % 4 - 1;
nuclear@4 248 redisplay();
nuclear@4 249 return;
nuclear@4 250 }
nuclear@4 251
nuclear@7 252 if(bn == 0) {
nuclear@7 253 int xsz, ysz;
nuclear@7 254 get_window_size(&xsz, &ysz);
nuclear@7 255
nuclear@7 256 TransferWindow *xfwin = dynamic_cast<TransferWindow*>(xfer);
nuclear@7 257 if(xfwin && press) {
nuclear@7 258 float cursor = (float)x / (float)xsz;
nuclear@7 259 float low[3], high[3];
nuclear@7 260 xfwin->get_interval_rgba(low, high);
nuclear@7 261
nuclear@7 262 // grab the nearest handle
nuclear@7 263 grabbed_handle = xfwin->nearest_handle(act_color, cursor);
nuclear@5 264 } else {
nuclear@7 265 grabbed_handle = -1;
nuclear@5 266 }
nuclear@7 267 redisplay();
nuclear@4 268 }
nuclear@4 269 }
nuclear@4 270
nuclear@4 271 void xfview_motion(int x, int y)
nuclear@4 272 {
nuclear@7 273 mousex = x;
nuclear@7 274 mousey = y;
nuclear@7 275
nuclear@7 276 int dx = x - prev_x;
nuclear@7 277 int dy = y - prev_y;
nuclear@7 278 prev_x = x;
nuclear@7 279 prev_y = y;
nuclear@7 280
nuclear@7 281 if(grabbed_handle != -1) {
nuclear@7 282 TransferWindow *xfwin = dynamic_cast<TransferWindow*>(xfer);
nuclear@7 283 if(!xfwin) return;
nuclear@7 284
nuclear@7 285 int xsz, ysz;
nuclear@7 286 get_window_size(&xsz, &ysz);
nuclear@7 287
nuclear@7 288 if(get_modifiers()) {
nuclear@7 289 float soft = xfwin->get_soft_radius() + dy * 0.01;
nuclear@7 290 if(soft < 0.0) soft = 0.0;
nuclear@7 291 xfwin->set_soft_radius(soft);
nuclear@7 292 } else {
nuclear@7 293 float pos = (float)x / (float)xsz;
nuclear@7 294 xfwin->set_handle(act_color, grabbed_handle, pos);
nuclear@7 295 }
nuclear@7 296 }
nuclear@7 297
nuclear@7 298 redisplay();
nuclear@4 299 }