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_