glviewvol
changeset 4:04330eb80b36
lots of stuff
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 29 Dec 2014 05:41:36 +0200 |
parents | 32c4a7160350 |
children | 5417c25cb238 |
files | Makefile sdr/fast.p.glsl sdr/fast.v.glsl src/curve.cc src/curve.h src/dicomview.cc src/dicomview.h src/main.cc src/rend_fast.cc src/rend_fast.h src/renderer.cc src/renderer.h src/sdr.c src/sdr.h src/volume.cc src/xfer_view.cc src/xfer_view.h |
diffstat | 17 files changed, 1067 insertions(+), 12 deletions(-) [+] |
line diff
1.1 --- a/Makefile Sun Dec 28 21:48:15 2014 +0200 1.2 +++ b/Makefile Mon Dec 29 05:41:36 2014 +0200 1.3 @@ -5,7 +5,7 @@ 1.4 1.5 bin = dicomview 1.6 1.7 -#opt = -O3 -ffast-math 1.8 +opt = -O3 -ffast-math 1.9 dbg = -g 1.10 def = -DUSE_GLUT 1.11 #inc =
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/sdr/fast.p.glsl Mon Dec 29 05:41:36 2014 +0200 2.3 @@ -0,0 +1,11 @@ 2.4 +uniform sampler3D vol_tex; 2.5 +uniform sampler1D xfer_tex; 2.6 + 2.7 +void main() 2.8 +{ 2.9 + vec4 voxel = texture3D(vol_tex, gl_TexCoord[0].xyz); 2.10 + vec4 color = texture1D(xfer_tex, voxel.a); 2.11 + 2.12 + gl_FragColor.rgb = color.rgb; 2.13 + gl_FragColor.a = 1.0; 2.14 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/sdr/fast.v.glsl Mon Dec 29 05:41:36 2014 +0200 3.3 @@ -0,0 +1,5 @@ 3.4 +void main() 3.5 +{ 3.6 + gl_Position = ftransform(); 3.7 + gl_TexCoord[0] = gl_MultiTexCoord0; 3.8 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/curve.cc Mon Dec 29 05:41:36 2014 +0200 4.3 @@ -0,0 +1,106 @@ 4.4 +#include <algorithm> 4.5 +#include "curve.h" 4.6 + 4.7 +#define CLAMP(x, low, high) std::min<float>(std::max<float>(x, low), high) 4.8 +#define INDEX(x) ((x) * 65535.0) 4.9 + 4.10 +void Curve::set_point(float t, float val) 4.11 +{ 4.12 + uint16_t x = INDEX(CLAMP(t, 0.0, 1.0)); 4.13 + set_point_int(x, val); 4.14 +} 4.15 + 4.16 +static bool cpcmp(const CurvePoint &a, const CurvePoint &b) 4.17 +{ 4.18 + return a.t_int < b.t_int; 4.19 +} 4.20 + 4.21 +void Curve::set_point_int(uint16_t ti, float val) 4.22 +{ 4.23 + CurvePoint *p = get_point_at(ti); 4.24 + if(p) { 4.25 + p->value = val; 4.26 + } else { 4.27 + CurvePoint p; 4.28 + p.t_int = ti; 4.29 + p.value = val; 4.30 + cp.push_back(p); 4.31 + std::sort(cp.begin(), cp.end(), cpcmp); 4.32 + } 4.33 +} 4.34 + 4.35 +bool Curve::delete_point(uint16_t ti) 4.36 +{ 4.37 + int sz = (int)cp.size(); 4.38 + for(int i=0; i<sz; i++) { 4.39 + if(cp[i].t_int == ti) { 4.40 + cp.erase(cp.begin() + i); 4.41 + return true; 4.42 + } 4.43 + } 4.44 + return false; 4.45 +} 4.46 + 4.47 +CurvePoint *Curve::get_point(int idx) 4.48 +{ 4.49 + if(idx < 0 || idx >= cp.size()) { 4.50 + return 0; 4.51 + } 4.52 + return &cp[idx]; 4.53 +} 4.54 + 4.55 +const CurvePoint *Curve::get_point(int idx) const 4.56 +{ 4.57 + if(idx < 0 || idx >= cp.size()) { 4.58 + return 0; 4.59 + } 4.60 + return &cp[idx]; 4.61 +} 4.62 + 4.63 +int Curve::get_num_points() const 4.64 +{ 4.65 + return (int)cp.size(); 4.66 +} 4.67 + 4.68 +CurvePoint *Curve::get_point_at(uint16_t ti) 4.69 +{ 4.70 + int sz = (int)cp.size(); 4.71 + for(int i=0; i<sz; i++) { 4.72 + if(cp[i].t_int == ti) { 4.73 + return &cp[i]; 4.74 + } 4.75 + } 4.76 + return 0; 4.77 +} 4.78 + 4.79 +const CurvePoint *Curve::get_point_at(uint16_t ti) const 4.80 +{ 4.81 + int sz = (int)cp.size(); 4.82 + for(int i=0; i<sz; i++) { 4.83 + if(cp[i].t_int == ti) { 4.84 + return &cp[i]; 4.85 + } 4.86 + } 4.87 + return 0; 4.88 +} 4.89 + 4.90 +float Curve::value(float t) const 4.91 +{ 4.92 + uint16_t x = INDEX(CLAMP(t, 0.0, 1.0)); 4.93 + return value_int(x); 4.94 +} 4.95 + 4.96 +float Curve::value_int(uint16_t ti) const 4.97 +{ 4.98 + CurvePoint p = { ti, 0 }; 4.99 + std::vector<CurvePoint>::const_iterator it; 4.100 + it = std::lower_bound(cp.begin(), cp.end(), p, cpcmp); 4.101 + if(ti >= it->t_int || it == cp.begin()) { 4.102 + return it->value; 4.103 + } 4.104 + 4.105 + std::vector<CurvePoint>::const_iterator prev = it - 1; 4.106 + 4.107 + float t = (float)(ti - prev->t_int) / (float)(it->t_int - prev->t_int); 4.108 + return prev->value + (it->value - prev->value) * t; 4.109 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/curve.h Mon Dec 29 05:41:36 2014 +0200 5.3 @@ -0,0 +1,33 @@ 5.4 +#ifndef CURVE_H_ 5.5 +#define CURVE_H_ 5.6 + 5.7 +#include <vector> 5.8 +#include <inttypes.h> 5.9 + 5.10 +struct CurvePoint { 5.11 + uint16_t t_int; // save time as an integer to allow exact lookup and change 5.12 + float value; 5.13 +}; 5.14 + 5.15 +class Curve { 5.16 +private: 5.17 + std::vector<CurvePoint> cp; 5.18 + 5.19 +public: 5.20 + void set_point(float t, float val); 5.21 + void set_point_int(uint16_t ti, float val); 5.22 + 5.23 + bool delete_point(uint16_t ti); 5.24 + 5.25 + CurvePoint *get_point(int idx); 5.26 + const CurvePoint *get_point(int idx) const; 5.27 + int get_num_points() const; 5.28 + 5.29 + CurvePoint *get_point_at(uint16_t ti); 5.30 + const CurvePoint *get_point_at(uint16_t ti) const; 5.31 + 5.32 + float value(float t) const; 5.33 + float value_int(uint16_t ti) const; 5.34 +}; 5.35 + 5.36 +#endif // CURVE_H_
6.1 --- a/src/dicomview.cc Sun Dec 28 21:48:15 2014 +0200 6.2 +++ b/src/dicomview.cc Mon Dec 29 05:41:36 2014 +0200 6.3 @@ -1,12 +1,17 @@ 6.4 #include <stdio.h> 6.5 +#include <stdlib.h> 6.6 #include "opengl.h" 6.7 #include "dicomview.h" 6.8 #include "rend_fast.h" 6.9 #include "opt.h" 6.10 #include "volume.h" 6.11 +#include "xfer_view.h" 6.12 6.13 static int win_width, win_height; 6.14 static float cam_theta, cam_phi, cam_dist = 6; 6.15 +static int splitter_y = -1; 6.16 + 6.17 +#define SPLITTER_WIDTH 5 6.18 6.19 static Renderer *rend; 6.20 static Volume *vol; 6.21 @@ -41,11 +46,17 @@ 6.22 vol = voxvol; 6.23 rend->set_volume(vol); 6.24 6.25 + if(!xfview_init(rend)) { 6.26 + return -1; 6.27 + } 6.28 + 6.29 return 0; 6.30 } 6.31 6.32 void cleanup() 6.33 { 6.34 + xfview_destroy(); 6.35 + 6.36 rend->destroy(); 6.37 delete rend; 6.38 delete vol; 6.39 @@ -55,16 +66,66 @@ 6.40 { 6.41 glClear(GL_COLOR_BUFFER_BIT); 6.42 6.43 + // render the main view 6.44 + glViewport(0, win_height - splitter_y, win_width, splitter_y); 6.45 + 6.46 + glMatrixMode(GL_PROJECTION); 6.47 + glLoadIdentity(); 6.48 + gluPerspective(50.0, (float)win_width / (float)splitter_y, 0.1, 100.0); 6.49 + 6.50 + glMatrixMode(GL_MODELVIEW); 6.51 + glLoadIdentity(); 6.52 + glTranslatef(0, 0, -cam_dist); 6.53 + glRotatef(cam_phi, 1, 0, 0); 6.54 + glRotatef(cam_theta, 0, 1, 0); 6.55 + 6.56 rend->update(0); 6.57 rend->render(); 6.58 + 6.59 + // draw the transfer function view 6.60 + glViewport(0, 0, win_width, win_height - splitter_y); 6.61 + 6.62 + xfview_draw(); 6.63 + 6.64 + // draw the GUI 6.65 + glViewport(0, 0, win_width, win_height); 6.66 + 6.67 + glMatrixMode(GL_PROJECTION); 6.68 + glLoadIdentity(); 6.69 + glOrtho(0, win_width, win_height, 0, -1, 1); 6.70 + 6.71 + glMatrixMode(GL_MODELVIEW); 6.72 + glLoadIdentity(); 6.73 + 6.74 + glBegin(GL_QUADS); 6.75 + glColor3f(1, 1, 1); 6.76 + glVertex2f(0, splitter_y + SPLITTER_WIDTH / 2); 6.77 + glVertex2f(win_width, splitter_y + SPLITTER_WIDTH / 2); 6.78 + glVertex2f(win_width, splitter_y - SPLITTER_WIDTH / 2); 6.79 + glVertex2f(0, splitter_y - SPLITTER_WIDTH / 2); 6.80 + glEnd(); 6.81 + 6.82 + swap_buffers(); 6.83 } 6.84 6.85 void ev_reshape(int x, int y) 6.86 { 6.87 + if(splitter_y < 0) { // not initialized yet 6.88 + splitter_y = (int)(y * 0.85); 6.89 + } else { 6.90 + // calculate where the splitter was relative to the window height 6.91 + // and based on that, it's new position 6.92 + float split = (float)splitter_y / (float)win_height; 6.93 + splitter_y = (int)(y * split); 6.94 + } 6.95 + 6.96 win_width = x; 6.97 win_height = y; 6.98 6.99 glViewport(0, 0, x, y); 6.100 + if(rend) { 6.101 + rend->reshape(x, y); 6.102 + } 6.103 } 6.104 6.105 void ev_keyboard(int key, int press, int x, int y) 6.106 @@ -77,12 +138,60 @@ 6.107 } 6.108 } 6.109 6.110 +static bool bnstate[8]; 6.111 +static int prev_x, prev_y; 6.112 + 6.113 +#define ON_SPLITTER(y) (abs(y - splitter_y) <= SPLITTER_WIDTH / 2) 6.114 +static bool splitter_dragging; 6.115 + 6.116 void ev_mouse_button(int bn, int press, int x, int y) 6.117 { 6.118 + bnstate[bn] = press != 0; 6.119 + prev_x = x; 6.120 + prev_y = y; 6.121 + 6.122 + splitter_dragging = bn == 0 && press && ON_SPLITTER(y); 6.123 + 6.124 + if(!splitter_dragging && y > splitter_y) { 6.125 + xfview_button(bn, press, x, y); 6.126 + } 6.127 } 6.128 6.129 void ev_mouse_motion(int x, int y) 6.130 { 6.131 + int dx = x - prev_x; 6.132 + int dy = y - prev_y; 6.133 + prev_x = x; 6.134 + prev_y = y; 6.135 + 6.136 + if((dx | dy) == 0) return; 6.137 + 6.138 + if(splitter_dragging) { 6.139 + splitter_y += dy; 6.140 + redisplay(); 6.141 + return; 6.142 + } 6.143 + 6.144 + if(y > splitter_y) { 6.145 + xfview_motion(x, y); 6.146 + return; 6.147 + } 6.148 + 6.149 + // main view motion handling 6.150 + if(bnstate[0]) { 6.151 + cam_theta += dx * 0.5; 6.152 + cam_phi += dy * 0.5; 6.153 + 6.154 + if(cam_phi < -90) cam_phi = -90; 6.155 + if(cam_phi > 90) cam_phi = 90; 6.156 + redisplay(); 6.157 + } 6.158 + if(bnstate[2]) { 6.159 + cam_dist += dy * 0.1; 6.160 + 6.161 + if(cam_dist < 0.0) cam_dist = 0.0; 6.162 + redisplay(); 6.163 + } 6.164 } 6.165 6.166 } // extern "C"
7.1 --- a/src/dicomview.h Sun Dec 28 21:48:15 2014 +0200 7.2 +++ b/src/dicomview.h Mon Dec 29 05:41:36 2014 +0200 7.3 @@ -18,6 +18,7 @@ 7.4 void swap_buffers(); 7.5 void redisplay(); 7.6 void quit(); 7.7 +void get_window_size(int *xsz, int *ysz); 7.8 7.9 #ifdef __cplusplus 7.10 }
8.1 --- a/src/main.cc Sun Dec 28 21:48:15 2014 +0200 8.2 +++ b/src/main.cc Mon Dec 29 05:41:36 2014 +0200 8.3 @@ -20,6 +20,8 @@ 8.4 static void mouse(int bn, int state, int x, int y); 8.5 static void motion(int x, int y); 8.6 8.7 +static int win_width, win_height; 8.8 + 8.9 int main(int argc, char **argv) 8.10 { 8.11 glutInit(&argc, argv); 8.12 @@ -65,6 +67,12 @@ 8.13 exit(0); 8.14 } 8.15 8.16 +void get_window_size(int *xsz, int *ysz) 8.17 +{ 8.18 + *xsz = win_width; 8.19 + *ysz = win_height; 8.20 +} 8.21 + 8.22 static void display() 8.23 { 8.24 ev_display(); 8.25 @@ -72,6 +80,8 @@ 8.26 8.27 static void reshape(int x, int y) 8.28 { 8.29 + win_width = x; 8.30 + win_height = y; 8.31 ev_reshape(x, y); 8.32 } 8.33
9.1 --- a/src/rend_fast.cc Sun Dec 28 21:48:15 2014 +0200 9.2 +++ b/src/rend_fast.cc Mon Dec 29 05:41:36 2014 +0200 9.3 @@ -1,25 +1,58 @@ 9.4 +#include <stdio.h> 9.5 #include "opengl.h" 9.6 #include "rend_fast.h" 9.7 +#include "sdr.h" 9.8 + 9.9 +#define XFER_MAP_SZ 1024 9.10 + 9.11 +static unsigned int sdr; 9.12 +static bool have_tex_float; 9.13 9.14 RendererFast::RendererFast() 9.15 { 9.16 - vol_tex = 0; 9.17 - vol_tex_valid = false; 9.18 + vol_tex = xfer_tex = 0; 9.19 + vol_tex_valid = xfer_tex_valid = false; 9.20 } 9.21 9.22 bool RendererFast::init() 9.23 { 9.24 + if(!sdr) { 9.25 + if(!(sdr = create_program_load("sdr/fast.v.glsl", "sdr/fast.p.glsl"))) { 9.26 + return false; 9.27 + } 9.28 + have_tex_float = GLEW_ARB_texture_float; 9.29 + } 9.30 + 9.31 glGenTextures(1, &vol_tex); 9.32 glBindTexture(GL_TEXTURE_3D, vol_tex); 9.33 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 9.34 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 9.35 9.36 + glGenTextures(1, &xfer_tex); 9.37 + glBindTexture(GL_TEXTURE_1D, xfer_tex); 9.38 + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 9.39 + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 9.40 + glTexImage1D(GL_TEXTURE_1D, 0, have_tex_float ? GL_RGB16F : GL_RGB, XFER_MAP_SZ, 0, GL_RGB, GL_FLOAT, 0); 9.41 + 9.42 return true; 9.43 } 9.44 9.45 void RendererFast::destroy() 9.46 { 9.47 glDeleteTextures(1, &vol_tex); 9.48 + glDeleteTextures(1, &xfer_tex); 9.49 +} 9.50 + 9.51 +void RendererFast::set_volume(Volume *vol) 9.52 +{ 9.53 + vol_tex_valid = false; 9.54 + Renderer::set_volume(vol); 9.55 +} 9.56 + 9.57 +Curve &RendererFast::transfer_curve(int color) 9.58 +{ 9.59 + xfer_tex_valid = false; 9.60 + return Renderer::transfer_curve(color); 9.61 } 9.62 9.63 void RendererFast::update(unsigned int msec) 9.64 @@ -37,6 +70,9 @@ 9.65 xsz = ysz = zsz = 256; 9.66 } 9.67 9.68 + printf("updating 3D texture data (%dx%dx%d) ... ", xsz, ysz, zsz); 9.69 + fflush(stdout); 9.70 + 9.71 int int_fmt = GLEW_ARB_texture_float ? GL_RGBA16F_ARB : GL_RGBA; 9.72 9.73 glBindTexture(GL_TEXTURE_3D, vol_tex); 9.74 @@ -45,13 +81,13 @@ 9.75 float *slice = new float[xsz * ysz * 4]; 9.76 9.77 for(int i=0; i<zsz; i++) { 9.78 - float z = (float)i / (float)(zsz - 1); 9.79 + float z = (float)i; 9.80 float *pptr = slice; 9.81 9.82 for(int j=0; j<ysz; j++) { 9.83 - float y = (float)j / (float)(ysz - 1); 9.84 + float y = (float)j; 9.85 for(int k=0; k<xsz; k++) { 9.86 - float x = (float)k / (float)(xsz - 1); 9.87 + float x = (float)k; 9.88 9.89 // value in alpha channel 9.90 pptr[3] = vol->valuef(x, y, z); 9.91 @@ -61,16 +97,37 @@ 9.92 pptr[0] = pptr[0] * 0.5 + 0.5; 9.93 pptr[1] = pptr[1] * 0.5 + 0.5; 9.94 pptr[2] = pptr[2] * 0.5 + 0.5; 9.95 + 9.96 + pptr += 4; 9.97 } 9.98 } 9.99 9.100 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i, xsz, ysz, 1, GL_RGBA, GL_FLOAT, slice); 9.101 } 9.102 9.103 + printf("done\n"); 9.104 + 9.105 delete [] slice; 9.106 9.107 vol_tex_valid = true; 9.108 } 9.109 + 9.110 + if(!xfer_tex_valid) { 9.111 + float pixels[XFER_MAP_SZ * 3]; 9.112 + float *pptr = pixels; 9.113 + 9.114 + for(int i=0; i<XFER_MAP_SZ; i++) { 9.115 + float x = (float)i / (float)(XFER_MAP_SZ - 1); 9.116 + *pptr++ = xfer[0].value(x); 9.117 + *pptr++ = xfer[1].value(x); 9.118 + *pptr++ = xfer[2].value(x); 9.119 + } 9.120 + 9.121 + glBindTexture(GL_TEXTURE_1D, xfer_tex); 9.122 + glTexSubImage1D(GL_TEXTURE_1D, 0, 0, XFER_MAP_SZ, GL_RGB, GL_FLOAT, pixels); 9.123 + 9.124 + xfer_tex_valid = true; 9.125 + } 9.126 } 9.127 9.128 void RendererFast::render() const 9.129 @@ -87,14 +144,25 @@ 9.130 glPushMatrix(); 9.131 glLoadIdentity(); 9.132 9.133 + glUseProgram(sdr); 9.134 + 9.135 + glActiveTexture(GL_TEXTURE0); 9.136 glBindTexture(GL_TEXTURE_3D, vol_tex); 9.137 + glActiveTexture(GL_TEXTURE1); 9.138 + glBindTexture(GL_TEXTURE_1D, xfer_tex); 9.139 + 9.140 + set_uniform_int(sdr, "vol_tex", 0); 9.141 + set_uniform_int(sdr, "xfer_tex", 1); 9.142 + 9.143 glBegin(GL_QUADS); 9.144 - glTexCoord3f(0, 0, 0); glVertex2f(-1, -1); 9.145 - glTexCoord3f(1, 0, 0); glVertex2f(1, -1); 9.146 - glTexCoord3f(1, 1, 0); glVertex2f(1, 1); 9.147 - glTexCoord3f(0, 1, 0); glVertex2f(-1, 1); 9.148 + glTexCoord3f(0, 0, 0.5); glVertex2f(-1, -1); 9.149 + glTexCoord3f(1, 0, 0.5); glVertex2f(1, -1); 9.150 + glTexCoord3f(1, 1, 0.5); glVertex2f(1, 1); 9.151 + glTexCoord3f(0, 1, 0.5); glVertex2f(-1, 1); 9.152 glEnd(); 9.153 9.154 + glUseProgram(0); 9.155 + 9.156 glMatrixMode(GL_PROJECTION); 9.157 glPopMatrix(); 9.158 glMatrixMode(GL_MODELVIEW);
10.1 --- a/src/rend_fast.h Sun Dec 28 21:48:15 2014 +0200 10.2 +++ b/src/rend_fast.h Mon Dec 29 05:41:36 2014 +0200 10.3 @@ -5,8 +5,8 @@ 10.4 10.5 class RendererFast : public Renderer { 10.6 private: 10.7 - unsigned int vol_tex; 10.8 - bool vol_tex_valid; 10.9 + unsigned int vol_tex, xfer_tex; 10.10 + bool vol_tex_valid, xfer_tex_valid; 10.11 10.12 public: 10.13 RendererFast(); 10.14 @@ -14,6 +14,9 @@ 10.15 bool init(); 10.16 void destroy(); 10.17 10.18 + void set_volume(Volume *vol); 10.19 + Curve &transfer_curve(int color); 10.20 + 10.21 void update(unsigned int msec); 10.22 void render() const; 10.23 };
11.1 --- a/src/renderer.cc Sun Dec 28 21:48:15 2014 +0200 11.2 +++ b/src/renderer.cc Mon Dec 29 05:41:36 2014 +0200 11.3 @@ -1,3 +1,4 @@ 11.4 +#include <math.h> 11.5 #include "renderer.h" 11.6 11.7 Renderer::Renderer() 11.8 @@ -5,6 +6,15 @@ 11.9 vol = 0; 11.10 view_width = 512; 11.11 view_height = 512; 11.12 + 11.13 + for(int i=0; i<3; i++) { 11.14 + xfer[i].set_point(0, 0); 11.15 + xfer[i].set_point(1, 1); 11.16 + } 11.17 + 11.18 + for(int i=0; i<MAX_CLIP_PLANES; i++) { 11.19 + disable_clipping_plane(i); 11.20 + } 11.21 } 11.22 11.23 Renderer::~Renderer() 11.24 @@ -31,6 +41,37 @@ 11.25 return vol; 11.26 } 11.27 11.28 +Curve &Renderer::transfer_curve(int color) 11.29 +{ 11.30 + return xfer[color]; 11.31 +} 11.32 + 11.33 +const Curve &Renderer::transfer_curve(int color) const 11.34 +{ 11.35 + return xfer[color]; 11.36 +} 11.37 + 11.38 +void Renderer::set_clipping_plane(int idx, float nx, float ny, float nz, float dist) 11.39 +{ 11.40 + float len = sqrt(nx * nx + ny * ny + nz * nz); 11.41 + if(len != 0.0) { 11.42 + nx /= len; 11.43 + ny /= len; 11.44 + nz /= len; 11.45 + } 11.46 + clip_plane[idx][0] = nx; 11.47 + clip_plane[idx][1] = ny; 11.48 + clip_plane[idx][2] = nz; 11.49 + clip_plane[idx][3] = dist; 11.50 +} 11.51 + 11.52 +void Renderer::disable_clipping_plane(int idx) 11.53 +{ 11.54 + clip_plane[idx][0] = clip_plane[idx][2] = 0; 11.55 + clip_plane[idx][1] = 1; 11.56 + clip_plane[idx][3] = -1; 11.57 +} 11.58 + 11.59 void Renderer::reshape(int x, int y) 11.60 { 11.61 view_width = x;
12.1 --- a/src/renderer.h Sun Dec 28 21:48:15 2014 +0200 12.2 +++ b/src/renderer.h Mon Dec 29 05:41:36 2014 +0200 12.3 @@ -2,12 +2,19 @@ 12.4 #define RENDERER_H_ 12.5 12.6 #include "volume.h" 12.7 +#include "curve.h" 12.8 + 12.9 +#define MAX_CLIP_PLANES 4 12.10 12.11 class Renderer { 12.12 protected: 12.13 int view_width, view_height; 12.14 Volume *vol; 12.15 12.16 + float clip_plane[MAX_CLIP_PLANES][4]; // nx,ny,nz,dist 12.17 + 12.18 + Curve xfer[3]; // rgb transfer function 12.19 + 12.20 public: 12.21 Renderer(); 12.22 virtual ~Renderer(); 12.23 @@ -18,6 +25,12 @@ 12.24 virtual void set_volume(Volume *vol); 12.25 virtual Volume *get_volume() const; 12.26 12.27 + virtual Curve &transfer_curve(int color); 12.28 + virtual const Curve &transfer_curve(int color) const; 12.29 + 12.30 + virtual void set_clipping_plane(int idx, float nx, float ny, float nz, float dist); 12.31 + virtual void disable_clipping_plane(int idx); 12.32 + 12.33 virtual void reshape(int x, int y); 12.34 12.35 virtual void update(unsigned int msec);
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/src/sdr.c Mon Dec 29 05:41:36 2014 +0200 13.3 @@ -0,0 +1,456 @@ 13.4 +#include <stdio.h> 13.5 +#include <stdlib.h> 13.6 +#include <string.h> 13.7 +#include <errno.h> 13.8 +#include <stdarg.h> 13.9 +#include <assert.h> 13.10 +#include <GL/glew.h> 13.11 + 13.12 +#if defined(unix) || defined(__unix__) 13.13 +#include <unistd.h> 13.14 +#include <sys/stat.h> 13.15 +#endif /* unix */ 13.16 + 13.17 +#include "sdr.h" 13.18 + 13.19 +static const char *sdrtypestr(unsigned int sdrtype); 13.20 + 13.21 +unsigned int create_vertex_shader(const char *src) 13.22 +{ 13.23 + return create_shader(src, GL_VERTEX_SHADER); 13.24 +} 13.25 + 13.26 +unsigned int create_pixel_shader(const char *src) 13.27 +{ 13.28 + return create_shader(src, GL_FRAGMENT_SHADER); 13.29 +} 13.30 + 13.31 +unsigned int create_tessctl_shader(const char *src) 13.32 +{ 13.33 +#ifdef GL_TESS_CONTROL_SHADER 13.34 + return create_shader(src, GL_TESS_CONTROL_SHADER); 13.35 +#else 13.36 + return 0; 13.37 +#endif 13.38 +} 13.39 + 13.40 +unsigned int create_tesseval_shader(const char *src) 13.41 +{ 13.42 +#ifdef GL_TESS_EVALUATION_SHADER 13.43 + return create_shader(src, GL_TESS_EVALUATION_SHADER); 13.44 +#else 13.45 + return 0; 13.46 +#endif 13.47 +} 13.48 + 13.49 +unsigned int create_geometry_shader(const char *src) 13.50 +{ 13.51 +#ifdef GL_GEOMETRY_SHADER 13.52 + return create_shader(src, GL_GEOMETRY_SHADER); 13.53 +#else 13.54 + return 0; 13.55 +#endif 13.56 +} 13.57 + 13.58 +unsigned int create_shader(const char *src, unsigned int sdr_type) 13.59 +{ 13.60 + unsigned int sdr; 13.61 + int success, info_len; 13.62 + char *info_str = 0; 13.63 + GLenum err; 13.64 + 13.65 + sdr = glCreateShader(sdr_type); 13.66 + assert(glGetError() == GL_NO_ERROR); 13.67 + glShaderSource(sdr, 1, &src, 0); 13.68 + err = glGetError(); 13.69 + assert(err == GL_NO_ERROR); 13.70 + glCompileShader(sdr); 13.71 + assert(glGetError() == GL_NO_ERROR); 13.72 + 13.73 + glGetShaderiv(sdr, GL_COMPILE_STATUS, &success); 13.74 + assert(glGetError() == GL_NO_ERROR); 13.75 + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); 13.76 + assert(glGetError() == GL_NO_ERROR); 13.77 + 13.78 + if(info_len) { 13.79 + if((info_str = malloc(info_len + 1))) { 13.80 + glGetShaderInfoLog(sdr, info_len, 0, info_str); 13.81 + assert(glGetError() == GL_NO_ERROR); 13.82 + info_str[info_len] = 0; 13.83 + } 13.84 + } 13.85 + 13.86 + if(success) { 13.87 + fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str); 13.88 + } else { 13.89 + fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str); 13.90 + glDeleteShader(sdr); 13.91 + sdr = 0; 13.92 + } 13.93 + 13.94 + free(info_str); 13.95 + return sdr; 13.96 +} 13.97 + 13.98 +void free_shader(unsigned int sdr) 13.99 +{ 13.100 + glDeleteShader(sdr); 13.101 +} 13.102 + 13.103 +unsigned int load_vertex_shader(const char *fname) 13.104 +{ 13.105 + return load_shader(fname, GL_VERTEX_SHADER); 13.106 +} 13.107 + 13.108 +unsigned int load_pixel_shader(const char *fname) 13.109 +{ 13.110 + return load_shader(fname, GL_FRAGMENT_SHADER); 13.111 +} 13.112 + 13.113 +unsigned int load_tessctl_shader(const char *fname) 13.114 +{ 13.115 +#ifdef GL_TESS_CONTROL_SHADER 13.116 + return load_shader(fname, GL_TESS_CONTROL_SHADER); 13.117 +#else 13.118 + return 0; 13.119 +#endif 13.120 +} 13.121 + 13.122 +unsigned int load_tesseval_shader(const char *fname) 13.123 +{ 13.124 +#ifdef GL_TESS_EVALUATION_SHADER 13.125 + return load_shader(fname, GL_TESS_EVALUATION_SHADER); 13.126 +#else 13.127 + return 0; 13.128 +#endif 13.129 +} 13.130 + 13.131 +unsigned int load_geometry_shader(const char *fname) 13.132 +{ 13.133 +#ifdef GL_GEOMETRY_SHADER 13.134 + return load_shader(fname, GL_GEOMETRY_SHADER); 13.135 +#else 13.136 + return 0; 13.137 +#endif 13.138 +} 13.139 + 13.140 +unsigned int load_shader(const char *fname, unsigned int sdr_type) 13.141 +{ 13.142 +#if defined(unix) || defined(__unix__) 13.143 + struct stat st; 13.144 +#endif 13.145 + unsigned int sdr; 13.146 + size_t filesize; 13.147 + FILE *fp; 13.148 + char *src; 13.149 + 13.150 + if(!(fp = fopen(fname, "rb"))) { 13.151 + fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno)); 13.152 + return 0; 13.153 + } 13.154 + 13.155 +#if defined(unix) || defined(__unix__) 13.156 + fstat(fileno(fp), &st); 13.157 + filesize = st.st_size; 13.158 +#else 13.159 + fseek(fp, 0, SEEK_END); 13.160 + filesize = ftell(fp); 13.161 + fseek(fp, 0, SEEK_SET); 13.162 +#endif /* unix */ 13.163 + 13.164 + if(!(src = malloc(filesize + 1))) { 13.165 + fclose(fp); 13.166 + return 0; 13.167 + } 13.168 + fread(src, 1, filesize, fp); 13.169 + src[filesize] = 0; 13.170 + fclose(fp); 13.171 + 13.172 + fprintf(stderr, "compiling %s shader: %s... ", sdrtypestr(sdr_type), fname); 13.173 + sdr = create_shader(src, sdr_type); 13.174 + 13.175 + free(src); 13.176 + return sdr; 13.177 +} 13.178 + 13.179 + 13.180 +unsigned int get_vertex_shader(const char *fname) 13.181 +{ 13.182 + return get_shader(fname, GL_VERTEX_SHADER); 13.183 +} 13.184 + 13.185 +unsigned int get_pixel_shader(const char *fname) 13.186 +{ 13.187 + return get_shader(fname, GL_FRAGMENT_SHADER); 13.188 +} 13.189 + 13.190 +unsigned int get_tessctl_shader(const char *fname) 13.191 +{ 13.192 +#ifdef GL_TESS_CONTROL_SHADER 13.193 + return get_shader(fname, GL_TESS_CONTROL_SHADER); 13.194 +#else 13.195 + return 0; 13.196 +#endif 13.197 +} 13.198 + 13.199 +unsigned int get_tesseval_shader(const char *fname) 13.200 +{ 13.201 +#ifdef GL_TESS_EVALUATION_SHADER 13.202 + return get_shader(fname, GL_TESS_EVALUATION_SHADER); 13.203 +#else 13.204 + return 0; 13.205 +#endif 13.206 +} 13.207 + 13.208 +unsigned int get_geometry_shader(const char *fname) 13.209 +{ 13.210 +#ifdef GL_GEOMETRY_SHADER 13.211 + return get_shader(fname, GL_GEOMETRY_SHADER); 13.212 +#else 13.213 + return 0; 13.214 +#endif 13.215 +} 13.216 + 13.217 +unsigned int get_shader(const char *fname, unsigned int sdr_type) 13.218 +{ 13.219 + unsigned int sdr; 13.220 + if(!(sdr = load_shader(fname, sdr_type))) { 13.221 + return 0; 13.222 + } 13.223 + return sdr; 13.224 +} 13.225 + 13.226 + 13.227 +/* ---- gpu programs ---- */ 13.228 + 13.229 +unsigned int create_program(void) 13.230 +{ 13.231 + unsigned int prog = glCreateProgram(); 13.232 + assert(glGetError() == GL_NO_ERROR); 13.233 + return prog; 13.234 +} 13.235 + 13.236 +unsigned int create_program_link(unsigned int sdr0, ...) 13.237 +{ 13.238 + unsigned int prog, sdr; 13.239 + va_list ap; 13.240 + 13.241 + if(!(prog = create_program())) { 13.242 + return 0; 13.243 + } 13.244 + 13.245 + attach_shader(prog, sdr0); 13.246 + if(glGetError()) { 13.247 + return 0; 13.248 + } 13.249 + 13.250 + va_start(ap, sdr0); 13.251 + while((sdr = va_arg(ap, unsigned int))) { 13.252 + attach_shader(prog, sdr); 13.253 + if(glGetError()) { 13.254 + return 0; 13.255 + } 13.256 + } 13.257 + va_end(ap); 13.258 + 13.259 + if(link_program(prog) == -1) { 13.260 + free_program(prog); 13.261 + return 0; 13.262 + } 13.263 + return prog; 13.264 +} 13.265 + 13.266 +unsigned int create_program_load(const char *vfile, const char *pfile) 13.267 +{ 13.268 + unsigned int vs = 0, ps = 0; 13.269 + 13.270 + if(vfile && *vfile && !(vs = get_vertex_shader(vfile))) { 13.271 + return 0; 13.272 + } 13.273 + if(pfile && *pfile && !(ps = get_pixel_shader(pfile))) { 13.274 + return 0; 13.275 + } 13.276 + return create_program_link(vs, ps, 0); 13.277 +} 13.278 + 13.279 +void free_program(unsigned int sdr) 13.280 +{ 13.281 + glDeleteProgram(sdr); 13.282 +} 13.283 + 13.284 +void attach_shader(unsigned int prog, unsigned int sdr) 13.285 +{ 13.286 + if(prog && sdr) { 13.287 + glAttachShader(prog, sdr); 13.288 + assert(glGetError() == GL_NO_ERROR); 13.289 + } 13.290 +} 13.291 + 13.292 +int link_program(unsigned int prog) 13.293 +{ 13.294 + int linked, info_len, retval = 0; 13.295 + char *info_str = 0; 13.296 + 13.297 + glLinkProgram(prog); 13.298 + assert(glGetError() == GL_NO_ERROR); 13.299 + glGetProgramiv(prog, GL_LINK_STATUS, &linked); 13.300 + assert(glGetError() == GL_NO_ERROR); 13.301 + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); 13.302 + assert(glGetError() == GL_NO_ERROR); 13.303 + 13.304 + if(info_len) { 13.305 + if((info_str = malloc(info_len + 1))) { 13.306 + glGetProgramInfoLog(prog, info_len, 0, info_str); 13.307 + assert(glGetError() == GL_NO_ERROR); 13.308 + info_str[info_len] = 0; 13.309 + } 13.310 + } 13.311 + 13.312 + if(linked) { 13.313 + fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str); 13.314 + } else { 13.315 + fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str); 13.316 + retval = -1; 13.317 + } 13.318 + 13.319 + free(info_str); 13.320 + return retval; 13.321 +} 13.322 + 13.323 +int bind_program(unsigned int prog) 13.324 +{ 13.325 + GLenum err; 13.326 + 13.327 + glUseProgram(prog); 13.328 + if(prog && (err = glGetError()) != GL_NO_ERROR) { 13.329 + /* maybe the program is not linked, try linking first */ 13.330 + if(err == GL_INVALID_OPERATION) { 13.331 + if(link_program(prog) == -1) { 13.332 + return -1; 13.333 + } 13.334 + glUseProgram(prog); 13.335 + return glGetError() == GL_NO_ERROR ? 0 : -1; 13.336 + } 13.337 + return -1; 13.338 + } 13.339 + return 0; 13.340 +} 13.341 + 13.342 +/* ugly but I'm not going to write the same bloody code over and over */ 13.343 +#define BEGIN_UNIFORM_CODE \ 13.344 + int loc, curr_prog; \ 13.345 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \ 13.346 + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { \ 13.347 + return -1; \ 13.348 + } \ 13.349 + if((loc = glGetUniformLocation(prog, name)) != -1) 13.350 + 13.351 +#define END_UNIFORM_CODE \ 13.352 + if((unsigned int)curr_prog != prog) { \ 13.353 + bind_program(curr_prog); \ 13.354 + } \ 13.355 + return loc == -1 ? -1 : 0 13.356 + 13.357 +int set_uniform_int(unsigned int prog, const char *name, int val) 13.358 +{ 13.359 + BEGIN_UNIFORM_CODE { 13.360 + glUniform1i(loc, val); 13.361 + } 13.362 + END_UNIFORM_CODE; 13.363 +} 13.364 + 13.365 +int set_uniform_float(unsigned int prog, const char *name, float val) 13.366 +{ 13.367 + BEGIN_UNIFORM_CODE { 13.368 + glUniform1f(loc, val); 13.369 + } 13.370 + END_UNIFORM_CODE; 13.371 +} 13.372 + 13.373 +int set_uniform_float2(unsigned int prog, const char *name, float x, float y) 13.374 +{ 13.375 + BEGIN_UNIFORM_CODE { 13.376 + glUniform2f(loc, x, y); 13.377 + } 13.378 + END_UNIFORM_CODE; 13.379 +} 13.380 + 13.381 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z) 13.382 +{ 13.383 + BEGIN_UNIFORM_CODE { 13.384 + glUniform3f(loc, x, y, z); 13.385 + } 13.386 + END_UNIFORM_CODE; 13.387 +} 13.388 + 13.389 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w) 13.390 +{ 13.391 + BEGIN_UNIFORM_CODE { 13.392 + glUniform4f(loc, x, y, z, w); 13.393 + } 13.394 + END_UNIFORM_CODE; 13.395 +} 13.396 + 13.397 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat) 13.398 +{ 13.399 + BEGIN_UNIFORM_CODE { 13.400 + glUniformMatrix4fv(loc, 1, GL_FALSE, mat); 13.401 + } 13.402 + END_UNIFORM_CODE; 13.403 +} 13.404 + 13.405 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat) 13.406 +{ 13.407 + BEGIN_UNIFORM_CODE { 13.408 + glUniformMatrix4fv(loc, 1, GL_TRUE, mat); 13.409 + } 13.410 + END_UNIFORM_CODE; 13.411 +} 13.412 + 13.413 +int get_attrib_loc(unsigned int prog, const char *name) 13.414 +{ 13.415 + int loc, curr_prog; 13.416 + 13.417 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); 13.418 + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { 13.419 + return -1; 13.420 + } 13.421 + 13.422 + loc = glGetAttribLocation(prog, (char*)name); 13.423 + 13.424 + if((unsigned int)curr_prog != prog) { 13.425 + bind_program(curr_prog); 13.426 + } 13.427 + return loc; 13.428 +} 13.429 + 13.430 +void set_attrib_float3(int attr_loc, float x, float y, float z) 13.431 +{ 13.432 + glVertexAttrib3f(attr_loc, x, y, z); 13.433 +} 13.434 + 13.435 +static const char *sdrtypestr(unsigned int sdrtype) 13.436 +{ 13.437 + switch(sdrtype) { 13.438 + case GL_VERTEX_SHADER: 13.439 + return "vertex"; 13.440 + case GL_FRAGMENT_SHADER: 13.441 + return "pixel"; 13.442 +#ifdef GL_TESS_CONTROL_SHADER 13.443 + case GL_TESS_CONTROL_SHADER: 13.444 + return "tessellation control"; 13.445 +#endif 13.446 +#ifdef GL_TESS_EVALUATION_SHADER 13.447 + case GL_TESS_EVALUATION_SHADER: 13.448 + return "tessellation evaluation"; 13.449 +#endif 13.450 +#ifdef GL_GEOMETRY_SHADER 13.451 + case GL_GEOMETRY_SHADER: 13.452 + return "geometry"; 13.453 +#endif 13.454 + 13.455 + default: 13.456 + break; 13.457 + } 13.458 + return "<unknown>"; 13.459 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/src/sdr.h Mon Dec 29 05:41:36 2014 +0200 14.3 @@ -0,0 +1,59 @@ 14.4 +#ifndef SDR_H_ 14.5 +#define SDR_H_ 14.6 + 14.7 +#ifdef __cplusplus 14.8 +extern "C" { 14.9 +#endif /* __cplusplus */ 14.10 + 14.11 +/* ---- shaders ---- */ 14.12 +unsigned int create_vertex_shader(const char *src); 14.13 +unsigned int create_pixel_shader(const char *src); 14.14 +unsigned int create_tessctl_shader(const char *src); 14.15 +unsigned int create_tesseval_shader(const char *src); 14.16 +unsigned int create_geometry_shader(const char *src); 14.17 +unsigned int create_shader(const char *src, unsigned int sdr_type); 14.18 +void free_shader(unsigned int sdr); 14.19 + 14.20 +unsigned int load_vertex_shader(const char *fname); 14.21 +unsigned int load_pixel_shader(const char *fname); 14.22 +unsigned int load_tessctl_shader(const char *fname); 14.23 +unsigned int load_tesseval_shader(const char *fname); 14.24 +unsigned int load_geometry_shader(const char *fname); 14.25 +unsigned int load_shader(const char *src, unsigned int sdr_type); 14.26 + 14.27 +unsigned int get_vertex_shader(const char *fname); 14.28 +unsigned int get_pixel_shader(const char *fname); 14.29 +unsigned int get_tessctl_shader(const char *fname); 14.30 +unsigned int get_tesseval_shader(const char *fname); 14.31 +unsigned int get_geometry_shader(const char *fname); 14.32 +unsigned int get_shader(const char *fname, unsigned int sdr_type); 14.33 + 14.34 +int add_shader(const char *fname, unsigned int sdr); 14.35 +int remove_shader(const char *fname); 14.36 + 14.37 +/* ---- gpu programs ---- */ 14.38 +unsigned int create_program(void); 14.39 +unsigned int create_program_link(unsigned int sdr0, ...); 14.40 +unsigned int create_program_load(const char *vfile, const char *pfile); 14.41 +void free_program(unsigned int sdr); 14.42 + 14.43 +void attach_shader(unsigned int prog, unsigned int sdr); 14.44 +int link_program(unsigned int prog); 14.45 +int bind_program(unsigned int prog); 14.46 + 14.47 +int set_uniform_int(unsigned int prog, const char *name, int val); 14.48 +int set_uniform_float(unsigned int prog, const char *name, float val); 14.49 +int set_uniform_float2(unsigned int prog, const char *name, float x, float y); 14.50 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z); 14.51 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w); 14.52 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat); 14.53 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat); 14.54 + 14.55 +int get_attrib_loc(unsigned int prog, const char *name); 14.56 +void set_attrib_float3(int attr_loc, float x, float y, float z); 14.57 + 14.58 +#ifdef __cplusplus 14.59 +} 14.60 +#endif /* __cplusplus */ 14.61 + 14.62 +#endif /* SDR_H_ */
15.1 --- a/src/volume.cc Sun Dec 28 21:48:15 2014 +0200 15.2 +++ b/src/volume.cc Mon Dec 29 05:41:36 2014 +0200 15.3 @@ -99,6 +99,7 @@ 15.4 prefix = 0; 15.5 } 15.6 15.7 + printf("loading volume dataset: %s\n", fname); 15.8 FILE *fp = fopen(fname, "r"); 15.9 if(!fp) { 15.10 fprintf(stderr, "failed to open file: %s: %s\n", fname, strerror(errno)); 15.11 @@ -110,6 +111,7 @@ 15.12 char *line = strip_space(buf); 15.13 sprintf(path, "%s/%s", prefix, line); 15.14 15.15 + printf(" loading slice %d: %s\n", (int)slices.size(), path); 15.16 Image img; 15.17 if(!img.load(path)) { 15.18 slices.clear();
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/src/xfer_view.cc Mon Dec 29 05:41:36 2014 +0200 16.3 @@ -0,0 +1,124 @@ 16.4 +#include <stdio.h> 16.5 +#include "opengl.h" 16.6 +#include "xfer_view.h" 16.7 +#include "dicomview.h" 16.8 + 16.9 +static Renderer *rend; 16.10 + 16.11 +static int act_color = 3; 16.12 +static CurvePoint *cpsel[3]; 16.13 + 16.14 +bool xfview_init(Renderer *rendarg) 16.15 +{ 16.16 + rend = rendarg; 16.17 + return true; 16.18 +} 16.19 + 16.20 +void xfview_destroy() 16.21 +{ 16.22 +} 16.23 + 16.24 +void xfview_draw() 16.25 +{ 16.26 + float line_color[][3] = { 16.27 + { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 1, 1, 1 } 16.28 + }; 16.29 + 16.30 + glMatrixMode(GL_PROJECTION); 16.31 + glLoadIdentity(); 16.32 + glMatrixMode(GL_MODELVIEW); 16.33 + glLoadIdentity(); 16.34 + 16.35 + int xsz, ysz; 16.36 + get_window_size(&xsz, &ysz); 16.37 + int nsamples = xsz / 4; 16.38 + 16.39 + // paint the background a faint version of the selected color 16.40 + glBegin(GL_QUADS); 16.41 + glColor3f(line_color[act_color][0] * 0.1, line_color[act_color][1] * 0.1, line_color[act_color][2] * 0.1); 16.42 + glVertex2f(-1, -1); 16.43 + glVertex2f(1, -1); 16.44 + glVertex2f(1, 1); 16.45 + glVertex2f(-1, 1); 16.46 + glEnd(); 16.47 + 16.48 + glEnable(GL_POINT_SMOOTH); 16.49 + glEnable(GL_LINE_SMOOTH); 16.50 + 16.51 + glEnable(GL_BLEND); 16.52 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 16.53 + 16.54 + // draw selection outline 16.55 + if(act_color < 3) { 16.56 + glPointSize(13.0); 16.57 + glLineWidth(5.0); 16.58 + 16.59 + const Curve &sel_curve = rend->transfer_curve(act_color); 16.60 + glColor3f(0.7, 0.7, 0.7); 16.61 + glBegin(GL_LINE_STRIP); 16.62 + for(int i=0; i<nsamples; i++) { 16.63 + float t = (float)i / (float)(nsamples - 1); 16.64 + float val = sel_curve.value(t); 16.65 + glVertex2f(t * 2.0 - 1.0, val * 2.0 - 1.0); 16.66 + } 16.67 + glEnd(); 16.68 + glBegin(GL_POINTS); 16.69 + for(int i=0; i<sel_curve.get_num_points(); i++) { 16.70 + const CurvePoint *p = sel_curve.get_point(i); 16.71 + float x = 2.0 * (float)p->t_int / 65535.0 - 1.0; 16.72 + glVertex2f(x, p->value * 2.0 - 1.0); 16.73 + } 16.74 + glEnd(); 16.75 + } 16.76 + 16.77 + 16.78 + // draw curves and points 16.79 + glPointSize(9.0); 16.80 + glLineWidth(2.0); 16.81 + 16.82 + for(int i=0; i<3; i++) { 16.83 + int idx; 16.84 + if(act_color < 3) { 16.85 + idx = (i + act_color + 1) % 3; 16.86 + } else { 16.87 + idx = i; 16.88 + } 16.89 + 16.90 + const Curve &xfer = rend->transfer_curve(idx); 16.91 + glColor3fv(line_color[idx]); 16.92 + 16.93 + glBegin(GL_LINE_STRIP); 16.94 + for(int j=0; j<nsamples; j++) { 16.95 + float t = (float)j / (float)(nsamples - 1); 16.96 + float val = xfer.value(t); 16.97 + glVertex2f(t * 2.0 - 1.0, val * 2.0 - 1.0); 16.98 + } 16.99 + glEnd(); 16.100 + 16.101 + glBegin(GL_POINTS); 16.102 + for(int j=0; j<xfer.get_num_points(); j++) { 16.103 + const CurvePoint *p = xfer.get_point(j); 16.104 + float x = 2.0 * (float)p->t_int / 65535.0 - 1.0; 16.105 + glVertex2f(x, p->value * 2.0 - 1.0); 16.106 + } 16.107 + glEnd(); 16.108 + } 16.109 + 16.110 + glDisable(GL_BLEND); 16.111 +} 16.112 + 16.113 +void xfview_button(int bn, int press, int x, int y) 16.114 +{ 16.115 + if(bn == 2 && press) { 16.116 + act_color = (act_color + 1) % 4; 16.117 + redisplay(); 16.118 + return; 16.119 + } 16.120 + 16.121 + if(press) { 16.122 + } 16.123 +} 16.124 + 16.125 +void xfview_motion(int x, int y) 16.126 +{ 16.127 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/src/xfer_view.h Mon Dec 29 05:41:36 2014 +0200 17.3 @@ -0,0 +1,14 @@ 17.4 +#ifndef XFER_VIEW_H_ 17.5 +#define XFER_VIEW_H_ 17.6 + 17.7 +#include "renderer.h" 17.8 + 17.9 +bool xfview_init(Renderer *rend); 17.10 +void xfview_destroy(); 17.11 + 17.12 +void xfview_draw(); 17.13 + 17.14 +void xfview_button(int bn, int press, int x, int y); 17.15 +void xfview_motion(int x, int y); 17.16 + 17.17 +#endif // XFER_VIEW_H_