# HG changeset patch # User John Tsiombikas # Date 1419824496 -7200 # Node ID 04330eb80b363e013fbe6113962d2f438d8d505d # Parent 32c4a7160350fbfed3151ebddf40311c729634cc lots of stuff diff -r 32c4a7160350 -r 04330eb80b36 Makefile --- a/Makefile Sun Dec 28 21:48:15 2014 +0200 +++ b/Makefile Mon Dec 29 05:41:36 2014 +0200 @@ -5,7 +5,7 @@ bin = dicomview -#opt = -O3 -ffast-math +opt = -O3 -ffast-math dbg = -g def = -DUSE_GLUT #inc = diff -r 32c4a7160350 -r 04330eb80b36 sdr/fast.p.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdr/fast.p.glsl Mon Dec 29 05:41:36 2014 +0200 @@ -0,0 +1,11 @@ +uniform sampler3D vol_tex; +uniform sampler1D xfer_tex; + +void main() +{ + vec4 voxel = texture3D(vol_tex, gl_TexCoord[0].xyz); + vec4 color = texture1D(xfer_tex, voxel.a); + + gl_FragColor.rgb = color.rgb; + gl_FragColor.a = 1.0; +} diff -r 32c4a7160350 -r 04330eb80b36 sdr/fast.v.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdr/fast.v.glsl Mon Dec 29 05:41:36 2014 +0200 @@ -0,0 +1,5 @@ +void main() +{ + gl_Position = ftransform(); + gl_TexCoord[0] = gl_MultiTexCoord0; +} diff -r 32c4a7160350 -r 04330eb80b36 src/curve.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/curve.cc Mon Dec 29 05:41:36 2014 +0200 @@ -0,0 +1,106 @@ +#include +#include "curve.h" + +#define CLAMP(x, low, high) std::min(std::max(x, low), high) +#define INDEX(x) ((x) * 65535.0) + +void Curve::set_point(float t, float val) +{ + uint16_t x = INDEX(CLAMP(t, 0.0, 1.0)); + set_point_int(x, val); +} + +static bool cpcmp(const CurvePoint &a, const CurvePoint &b) +{ + return a.t_int < b.t_int; +} + +void Curve::set_point_int(uint16_t ti, float val) +{ + CurvePoint *p = get_point_at(ti); + if(p) { + p->value = val; + } else { + CurvePoint p; + p.t_int = ti; + p.value = val; + cp.push_back(p); + std::sort(cp.begin(), cp.end(), cpcmp); + } +} + +bool Curve::delete_point(uint16_t ti) +{ + int sz = (int)cp.size(); + for(int i=0; i= cp.size()) { + return 0; + } + return &cp[idx]; +} + +const CurvePoint *Curve::get_point(int idx) const +{ + if(idx < 0 || idx >= cp.size()) { + return 0; + } + return &cp[idx]; +} + +int Curve::get_num_points() const +{ + return (int)cp.size(); +} + +CurvePoint *Curve::get_point_at(uint16_t ti) +{ + int sz = (int)cp.size(); + for(int i=0; i::const_iterator it; + it = std::lower_bound(cp.begin(), cp.end(), p, cpcmp); + if(ti >= it->t_int || it == cp.begin()) { + return it->value; + } + + std::vector::const_iterator prev = it - 1; + + float t = (float)(ti - prev->t_int) / (float)(it->t_int - prev->t_int); + return prev->value + (it->value - prev->value) * t; +} diff -r 32c4a7160350 -r 04330eb80b36 src/curve.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/curve.h Mon Dec 29 05:41:36 2014 +0200 @@ -0,0 +1,33 @@ +#ifndef CURVE_H_ +#define CURVE_H_ + +#include +#include + +struct CurvePoint { + uint16_t t_int; // save time as an integer to allow exact lookup and change + float value; +}; + +class Curve { +private: + std::vector cp; + +public: + void set_point(float t, float val); + void set_point_int(uint16_t ti, float val); + + bool delete_point(uint16_t ti); + + CurvePoint *get_point(int idx); + const CurvePoint *get_point(int idx) const; + int get_num_points() const; + + CurvePoint *get_point_at(uint16_t ti); + const CurvePoint *get_point_at(uint16_t ti) const; + + float value(float t) const; + float value_int(uint16_t ti) const; +}; + +#endif // CURVE_H_ diff -r 32c4a7160350 -r 04330eb80b36 src/dicomview.cc --- a/src/dicomview.cc Sun Dec 28 21:48:15 2014 +0200 +++ b/src/dicomview.cc Mon Dec 29 05:41:36 2014 +0200 @@ -1,12 +1,17 @@ #include +#include #include "opengl.h" #include "dicomview.h" #include "rend_fast.h" #include "opt.h" #include "volume.h" +#include "xfer_view.h" static int win_width, win_height; static float cam_theta, cam_phi, cam_dist = 6; +static int splitter_y = -1; + +#define SPLITTER_WIDTH 5 static Renderer *rend; static Volume *vol; @@ -41,11 +46,17 @@ vol = voxvol; rend->set_volume(vol); + if(!xfview_init(rend)) { + return -1; + } + return 0; } void cleanup() { + xfview_destroy(); + rend->destroy(); delete rend; delete vol; @@ -55,16 +66,66 @@ { glClear(GL_COLOR_BUFFER_BIT); + // render the main view + glViewport(0, win_height - splitter_y, win_width, splitter_y); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(50.0, (float)win_width / (float)splitter_y, 0.1, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0, 0, -cam_dist); + glRotatef(cam_phi, 1, 0, 0); + glRotatef(cam_theta, 0, 1, 0); + rend->update(0); rend->render(); + + // draw the transfer function view + glViewport(0, 0, win_width, win_height - splitter_y); + + xfview_draw(); + + // draw the GUI + glViewport(0, 0, win_width, win_height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, win_width, win_height, 0, -1, 1); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glBegin(GL_QUADS); + glColor3f(1, 1, 1); + glVertex2f(0, splitter_y + SPLITTER_WIDTH / 2); + glVertex2f(win_width, splitter_y + SPLITTER_WIDTH / 2); + glVertex2f(win_width, splitter_y - SPLITTER_WIDTH / 2); + glVertex2f(0, splitter_y - SPLITTER_WIDTH / 2); + glEnd(); + + swap_buffers(); } void ev_reshape(int x, int y) { + if(splitter_y < 0) { // not initialized yet + splitter_y = (int)(y * 0.85); + } else { + // calculate where the splitter was relative to the window height + // and based on that, it's new position + float split = (float)splitter_y / (float)win_height; + splitter_y = (int)(y * split); + } + win_width = x; win_height = y; glViewport(0, 0, x, y); + if(rend) { + rend->reshape(x, y); + } } void ev_keyboard(int key, int press, int x, int y) @@ -77,12 +138,60 @@ } } +static bool bnstate[8]; +static int prev_x, prev_y; + +#define ON_SPLITTER(y) (abs(y - splitter_y) <= SPLITTER_WIDTH / 2) +static bool splitter_dragging; + void ev_mouse_button(int bn, int press, int x, int y) { + bnstate[bn] = press != 0; + prev_x = x; + prev_y = y; + + splitter_dragging = bn == 0 && press && ON_SPLITTER(y); + + if(!splitter_dragging && y > splitter_y) { + xfview_button(bn, press, x, y); + } } void ev_mouse_motion(int x, int y) { + int dx = x - prev_x; + int dy = y - prev_y; + prev_x = x; + prev_y = y; + + if((dx | dy) == 0) return; + + if(splitter_dragging) { + splitter_y += dy; + redisplay(); + return; + } + + if(y > splitter_y) { + xfview_motion(x, y); + return; + } + + // main view motion handling + if(bnstate[0]) { + cam_theta += dx * 0.5; + cam_phi += dy * 0.5; + + if(cam_phi < -90) cam_phi = -90; + if(cam_phi > 90) cam_phi = 90; + redisplay(); + } + if(bnstate[2]) { + cam_dist += dy * 0.1; + + if(cam_dist < 0.0) cam_dist = 0.0; + redisplay(); + } } } // extern "C" diff -r 32c4a7160350 -r 04330eb80b36 src/dicomview.h --- a/src/dicomview.h Sun Dec 28 21:48:15 2014 +0200 +++ b/src/dicomview.h Mon Dec 29 05:41:36 2014 +0200 @@ -18,6 +18,7 @@ void swap_buffers(); void redisplay(); void quit(); +void get_window_size(int *xsz, int *ysz); #ifdef __cplusplus } diff -r 32c4a7160350 -r 04330eb80b36 src/main.cc --- a/src/main.cc Sun Dec 28 21:48:15 2014 +0200 +++ b/src/main.cc Mon Dec 29 05:41:36 2014 +0200 @@ -20,6 +20,8 @@ static void mouse(int bn, int state, int x, int y); static void motion(int x, int y); +static int win_width, win_height; + int main(int argc, char **argv) { glutInit(&argc, argv); @@ -65,6 +67,12 @@ exit(0); } +void get_window_size(int *xsz, int *ysz) +{ + *xsz = win_width; + *ysz = win_height; +} + static void display() { ev_display(); @@ -72,6 +80,8 @@ static void reshape(int x, int y) { + win_width = x; + win_height = y; ev_reshape(x, y); } diff -r 32c4a7160350 -r 04330eb80b36 src/rend_fast.cc --- a/src/rend_fast.cc Sun Dec 28 21:48:15 2014 +0200 +++ b/src/rend_fast.cc Mon Dec 29 05:41:36 2014 +0200 @@ -1,25 +1,58 @@ +#include #include "opengl.h" #include "rend_fast.h" +#include "sdr.h" + +#define XFER_MAP_SZ 1024 + +static unsigned int sdr; +static bool have_tex_float; RendererFast::RendererFast() { - vol_tex = 0; - vol_tex_valid = false; + vol_tex = xfer_tex = 0; + vol_tex_valid = xfer_tex_valid = false; } bool RendererFast::init() { + if(!sdr) { + if(!(sdr = create_program_load("sdr/fast.v.glsl", "sdr/fast.p.glsl"))) { + return false; + } + have_tex_float = GLEW_ARB_texture_float; + } + glGenTextures(1, &vol_tex); glBindTexture(GL_TEXTURE_3D, vol_tex); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glGenTextures(1, &xfer_tex); + glBindTexture(GL_TEXTURE_1D, xfer_tex); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage1D(GL_TEXTURE_1D, 0, have_tex_float ? GL_RGB16F : GL_RGB, XFER_MAP_SZ, 0, GL_RGB, GL_FLOAT, 0); + return true; } void RendererFast::destroy() { glDeleteTextures(1, &vol_tex); + glDeleteTextures(1, &xfer_tex); +} + +void RendererFast::set_volume(Volume *vol) +{ + vol_tex_valid = false; + Renderer::set_volume(vol); +} + +Curve &RendererFast::transfer_curve(int color) +{ + xfer_tex_valid = false; + return Renderer::transfer_curve(color); } void RendererFast::update(unsigned int msec) @@ -37,6 +70,9 @@ xsz = ysz = zsz = 256; } + printf("updating 3D texture data (%dx%dx%d) ... ", xsz, ysz, zsz); + fflush(stdout); + int int_fmt = GLEW_ARB_texture_float ? GL_RGBA16F_ARB : GL_RGBA; glBindTexture(GL_TEXTURE_3D, vol_tex); @@ -45,13 +81,13 @@ float *slice = new float[xsz * ysz * 4]; for(int i=0; ivaluef(x, y, z); @@ -61,16 +97,37 @@ pptr[0] = pptr[0] * 0.5 + 0.5; pptr[1] = pptr[1] * 0.5 + 0.5; pptr[2] = pptr[2] * 0.5 + 0.5; + + pptr += 4; } } glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i, xsz, ysz, 1, GL_RGBA, GL_FLOAT, slice); } + printf("done\n"); + delete [] slice; vol_tex_valid = true; } + + if(!xfer_tex_valid) { + float pixels[XFER_MAP_SZ * 3]; + float *pptr = pixels; + + for(int i=0; i #include "renderer.h" Renderer::Renderer() @@ -5,6 +6,15 @@ vol = 0; view_width = 512; view_height = 512; + + for(int i=0; i<3; i++) { + xfer[i].set_point(0, 0); + xfer[i].set_point(1, 1); + } + + for(int i=0; i +#include +#include +#include +#include +#include +#include + +#if defined(unix) || defined(__unix__) +#include +#include +#endif /* unix */ + +#include "sdr.h" + +static const char *sdrtypestr(unsigned int sdrtype); + +unsigned int create_vertex_shader(const char *src) +{ + return create_shader(src, GL_VERTEX_SHADER); +} + +unsigned int create_pixel_shader(const char *src) +{ + return create_shader(src, GL_FRAGMENT_SHADER); +} + +unsigned int create_tessctl_shader(const char *src) +{ +#ifdef GL_TESS_CONTROL_SHADER + return create_shader(src, GL_TESS_CONTROL_SHADER); +#else + return 0; +#endif +} + +unsigned int create_tesseval_shader(const char *src) +{ +#ifdef GL_TESS_EVALUATION_SHADER + return create_shader(src, GL_TESS_EVALUATION_SHADER); +#else + return 0; +#endif +} + +unsigned int create_geometry_shader(const char *src) +{ +#ifdef GL_GEOMETRY_SHADER + return create_shader(src, GL_GEOMETRY_SHADER); +#else + return 0; +#endif +} + +unsigned int create_shader(const char *src, unsigned int sdr_type) +{ + unsigned int sdr; + int success, info_len; + char *info_str = 0; + GLenum err; + + sdr = glCreateShader(sdr_type); + assert(glGetError() == GL_NO_ERROR); + glShaderSource(sdr, 1, &src, 0); + err = glGetError(); + assert(err == GL_NO_ERROR); + glCompileShader(sdr); + assert(glGetError() == GL_NO_ERROR); + + glGetShaderiv(sdr, GL_COMPILE_STATUS, &success); + assert(glGetError() == GL_NO_ERROR); + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); + assert(glGetError() == GL_NO_ERROR); + + if(info_len) { + if((info_str = malloc(info_len + 1))) { + glGetShaderInfoLog(sdr, info_len, 0, info_str); + assert(glGetError() == GL_NO_ERROR); + info_str[info_len] = 0; + } + } + + if(success) { + fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str); + } else { + fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str); + glDeleteShader(sdr); + sdr = 0; + } + + free(info_str); + return sdr; +} + +void free_shader(unsigned int sdr) +{ + glDeleteShader(sdr); +} + +unsigned int load_vertex_shader(const char *fname) +{ + return load_shader(fname, GL_VERTEX_SHADER); +} + +unsigned int load_pixel_shader(const char *fname) +{ + return load_shader(fname, GL_FRAGMENT_SHADER); +} + +unsigned int load_tessctl_shader(const char *fname) +{ +#ifdef GL_TESS_CONTROL_SHADER + return load_shader(fname, GL_TESS_CONTROL_SHADER); +#else + return 0; +#endif +} + +unsigned int load_tesseval_shader(const char *fname) +{ +#ifdef GL_TESS_EVALUATION_SHADER + return load_shader(fname, GL_TESS_EVALUATION_SHADER); +#else + return 0; +#endif +} + +unsigned int load_geometry_shader(const char *fname) +{ +#ifdef GL_GEOMETRY_SHADER + return load_shader(fname, GL_GEOMETRY_SHADER); +#else + return 0; +#endif +} + +unsigned int load_shader(const char *fname, unsigned int sdr_type) +{ +#if defined(unix) || defined(__unix__) + struct stat st; +#endif + unsigned int sdr; + size_t filesize; + FILE *fp; + char *src; + + if(!(fp = fopen(fname, "rb"))) { + fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno)); + return 0; + } + +#if defined(unix) || defined(__unix__) + fstat(fileno(fp), &st); + filesize = st.st_size; +#else + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + fseek(fp, 0, SEEK_SET); +#endif /* unix */ + + if(!(src = malloc(filesize + 1))) { + fclose(fp); + return 0; + } + fread(src, 1, filesize, fp); + src[filesize] = 0; + fclose(fp); + + fprintf(stderr, "compiling %s shader: %s... ", sdrtypestr(sdr_type), fname); + sdr = create_shader(src, sdr_type); + + free(src); + return sdr; +} + + +unsigned int get_vertex_shader(const char *fname) +{ + return get_shader(fname, GL_VERTEX_SHADER); +} + +unsigned int get_pixel_shader(const char *fname) +{ + return get_shader(fname, GL_FRAGMENT_SHADER); +} + +unsigned int get_tessctl_shader(const char *fname) +{ +#ifdef GL_TESS_CONTROL_SHADER + return get_shader(fname, GL_TESS_CONTROL_SHADER); +#else + return 0; +#endif +} + +unsigned int get_tesseval_shader(const char *fname) +{ +#ifdef GL_TESS_EVALUATION_SHADER + return get_shader(fname, GL_TESS_EVALUATION_SHADER); +#else + return 0; +#endif +} + +unsigned int get_geometry_shader(const char *fname) +{ +#ifdef GL_GEOMETRY_SHADER + return get_shader(fname, GL_GEOMETRY_SHADER); +#else + return 0; +#endif +} + +unsigned int get_shader(const char *fname, unsigned int sdr_type) +{ + unsigned int sdr; + if(!(sdr = load_shader(fname, sdr_type))) { + return 0; + } + return sdr; +} + + +/* ---- gpu programs ---- */ + +unsigned int create_program(void) +{ + unsigned int prog = glCreateProgram(); + assert(glGetError() == GL_NO_ERROR); + return prog; +} + +unsigned int create_program_link(unsigned int sdr0, ...) +{ + unsigned int prog, sdr; + va_list ap; + + if(!(prog = create_program())) { + return 0; + } + + attach_shader(prog, sdr0); + if(glGetError()) { + return 0; + } + + va_start(ap, sdr0); + while((sdr = va_arg(ap, unsigned int))) { + attach_shader(prog, sdr); + if(glGetError()) { + return 0; + } + } + va_end(ap); + + if(link_program(prog) == -1) { + free_program(prog); + return 0; + } + return prog; +} + +unsigned int create_program_load(const char *vfile, const char *pfile) +{ + unsigned int vs = 0, ps = 0; + + if(vfile && *vfile && !(vs = get_vertex_shader(vfile))) { + return 0; + } + if(pfile && *pfile && !(ps = get_pixel_shader(pfile))) { + return 0; + } + return create_program_link(vs, ps, 0); +} + +void free_program(unsigned int sdr) +{ + glDeleteProgram(sdr); +} + +void attach_shader(unsigned int prog, unsigned int sdr) +{ + if(prog && sdr) { + glAttachShader(prog, sdr); + assert(glGetError() == GL_NO_ERROR); + } +} + +int link_program(unsigned int prog) +{ + int linked, info_len, retval = 0; + char *info_str = 0; + + glLinkProgram(prog); + assert(glGetError() == GL_NO_ERROR); + glGetProgramiv(prog, GL_LINK_STATUS, &linked); + assert(glGetError() == GL_NO_ERROR); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); + assert(glGetError() == GL_NO_ERROR); + + if(info_len) { + if((info_str = malloc(info_len + 1))) { + glGetProgramInfoLog(prog, info_len, 0, info_str); + assert(glGetError() == GL_NO_ERROR); + info_str[info_len] = 0; + } + } + + if(linked) { + fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str); + } else { + fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str); + retval = -1; + } + + free(info_str); + return retval; +} + +int bind_program(unsigned int prog) +{ + GLenum err; + + glUseProgram(prog); + if(prog && (err = glGetError()) != GL_NO_ERROR) { + /* maybe the program is not linked, try linking first */ + if(err == GL_INVALID_OPERATION) { + if(link_program(prog) == -1) { + return -1; + } + glUseProgram(prog); + return glGetError() == GL_NO_ERROR ? 0 : -1; + } + return -1; + } + return 0; +} + +/* ugly but I'm not going to write the same bloody code over and over */ +#define BEGIN_UNIFORM_CODE \ + int loc, curr_prog; \ + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \ + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { \ + return -1; \ + } \ + if((loc = glGetUniformLocation(prog, name)) != -1) + +#define END_UNIFORM_CODE \ + if((unsigned int)curr_prog != prog) { \ + bind_program(curr_prog); \ + } \ + return loc == -1 ? -1 : 0 + +int set_uniform_int(unsigned int prog, const char *name, int val) +{ + BEGIN_UNIFORM_CODE { + glUniform1i(loc, val); + } + END_UNIFORM_CODE; +} + +int set_uniform_float(unsigned int prog, const char *name, float val) +{ + BEGIN_UNIFORM_CODE { + glUniform1f(loc, val); + } + END_UNIFORM_CODE; +} + +int set_uniform_float2(unsigned int prog, const char *name, float x, float y) +{ + BEGIN_UNIFORM_CODE { + glUniform2f(loc, x, y); + } + END_UNIFORM_CODE; +} + +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z) +{ + BEGIN_UNIFORM_CODE { + glUniform3f(loc, x, y, z); + } + END_UNIFORM_CODE; +} + +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w) +{ + BEGIN_UNIFORM_CODE { + glUniform4f(loc, x, y, z, w); + } + END_UNIFORM_CODE; +} + +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat) +{ + BEGIN_UNIFORM_CODE { + glUniformMatrix4fv(loc, 1, GL_FALSE, mat); + } + END_UNIFORM_CODE; +} + +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat) +{ + BEGIN_UNIFORM_CODE { + glUniformMatrix4fv(loc, 1, GL_TRUE, mat); + } + END_UNIFORM_CODE; +} + +int get_attrib_loc(unsigned int prog, const char *name) +{ + int loc, curr_prog; + + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { + return -1; + } + + loc = glGetAttribLocation(prog, (char*)name); + + if((unsigned int)curr_prog != prog) { + bind_program(curr_prog); + } + return loc; +} + +void set_attrib_float3(int attr_loc, float x, float y, float z) +{ + glVertexAttrib3f(attr_loc, x, y, z); +} + +static const char *sdrtypestr(unsigned int sdrtype) +{ + switch(sdrtype) { + case GL_VERTEX_SHADER: + return "vertex"; + case GL_FRAGMENT_SHADER: + return "pixel"; +#ifdef GL_TESS_CONTROL_SHADER + case GL_TESS_CONTROL_SHADER: + return "tessellation control"; +#endif +#ifdef GL_TESS_EVALUATION_SHADER + case GL_TESS_EVALUATION_SHADER: + return "tessellation evaluation"; +#endif +#ifdef GL_GEOMETRY_SHADER + case GL_GEOMETRY_SHADER: + return "geometry"; +#endif + + default: + break; + } + return ""; +} diff -r 32c4a7160350 -r 04330eb80b36 src/sdr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdr.h Mon Dec 29 05:41:36 2014 +0200 @@ -0,0 +1,59 @@ +#ifndef SDR_H_ +#define SDR_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* ---- shaders ---- */ +unsigned int create_vertex_shader(const char *src); +unsigned int create_pixel_shader(const char *src); +unsigned int create_tessctl_shader(const char *src); +unsigned int create_tesseval_shader(const char *src); +unsigned int create_geometry_shader(const char *src); +unsigned int create_shader(const char *src, unsigned int sdr_type); +void free_shader(unsigned int sdr); + +unsigned int load_vertex_shader(const char *fname); +unsigned int load_pixel_shader(const char *fname); +unsigned int load_tessctl_shader(const char *fname); +unsigned int load_tesseval_shader(const char *fname); +unsigned int load_geometry_shader(const char *fname); +unsigned int load_shader(const char *src, unsigned int sdr_type); + +unsigned int get_vertex_shader(const char *fname); +unsigned int get_pixel_shader(const char *fname); +unsigned int get_tessctl_shader(const char *fname); +unsigned int get_tesseval_shader(const char *fname); +unsigned int get_geometry_shader(const char *fname); +unsigned int get_shader(const char *fname, unsigned int sdr_type); + +int add_shader(const char *fname, unsigned int sdr); +int remove_shader(const char *fname); + +/* ---- gpu programs ---- */ +unsigned int create_program(void); +unsigned int create_program_link(unsigned int sdr0, ...); +unsigned int create_program_load(const char *vfile, const char *pfile); +void free_program(unsigned int sdr); + +void attach_shader(unsigned int prog, unsigned int sdr); +int link_program(unsigned int prog); +int bind_program(unsigned int prog); + +int set_uniform_int(unsigned int prog, const char *name, int val); +int set_uniform_float(unsigned int prog, const char *name, float val); +int set_uniform_float2(unsigned int prog, const char *name, float x, float y); +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z); +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w); +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat); +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat); + +int get_attrib_loc(unsigned int prog, const char *name); +void set_attrib_float3(int attr_loc, float x, float y, float z); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SDR_H_ */ diff -r 32c4a7160350 -r 04330eb80b36 src/volume.cc --- a/src/volume.cc Sun Dec 28 21:48:15 2014 +0200 +++ b/src/volume.cc Mon Dec 29 05:41:36 2014 +0200 @@ -99,6 +99,7 @@ prefix = 0; } + printf("loading volume dataset: %s\n", fname); FILE *fp = fopen(fname, "r"); if(!fp) { fprintf(stderr, "failed to open file: %s: %s\n", fname, strerror(errno)); @@ -110,6 +111,7 @@ char *line = strip_space(buf); sprintf(path, "%s/%s", prefix, line); + printf(" loading slice %d: %s\n", (int)slices.size(), path); Image img; if(!img.load(path)) { slices.clear(); diff -r 32c4a7160350 -r 04330eb80b36 src/xfer_view.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xfer_view.cc Mon Dec 29 05:41:36 2014 +0200 @@ -0,0 +1,124 @@ +#include +#include "opengl.h" +#include "xfer_view.h" +#include "dicomview.h" + +static Renderer *rend; + +static int act_color = 3; +static CurvePoint *cpsel[3]; + +bool xfview_init(Renderer *rendarg) +{ + rend = rendarg; + return true; +} + +void xfview_destroy() +{ +} + +void xfview_draw() +{ + float line_color[][3] = { + { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 1, 1, 1 } + }; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + int xsz, ysz; + get_window_size(&xsz, &ysz); + int nsamples = xsz / 4; + + // paint the background a faint version of the selected color + glBegin(GL_QUADS); + glColor3f(line_color[act_color][0] * 0.1, line_color[act_color][1] * 0.1, line_color[act_color][2] * 0.1); + glVertex2f(-1, -1); + glVertex2f(1, -1); + glVertex2f(1, 1); + glVertex2f(-1, 1); + glEnd(); + + glEnable(GL_POINT_SMOOTH); + glEnable(GL_LINE_SMOOTH); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // draw selection outline + if(act_color < 3) { + glPointSize(13.0); + glLineWidth(5.0); + + const Curve &sel_curve = rend->transfer_curve(act_color); + glColor3f(0.7, 0.7, 0.7); + glBegin(GL_LINE_STRIP); + for(int i=0; it_int / 65535.0 - 1.0; + glVertex2f(x, p->value * 2.0 - 1.0); + } + glEnd(); + } + + + // draw curves and points + glPointSize(9.0); + glLineWidth(2.0); + + for(int i=0; i<3; i++) { + int idx; + if(act_color < 3) { + idx = (i + act_color + 1) % 3; + } else { + idx = i; + } + + const Curve &xfer = rend->transfer_curve(idx); + glColor3fv(line_color[idx]); + + glBegin(GL_LINE_STRIP); + for(int j=0; jt_int / 65535.0 - 1.0; + glVertex2f(x, p->value * 2.0 - 1.0); + } + glEnd(); + } + + glDisable(GL_BLEND); +} + +void xfview_button(int bn, int press, int x, int y) +{ + if(bn == 2 && press) { + act_color = (act_color + 1) % 4; + redisplay(); + return; + } + + if(press) { + } +} + +void xfview_motion(int x, int y) +{ +} diff -r 32c4a7160350 -r 04330eb80b36 src/xfer_view.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xfer_view.h Mon Dec 29 05:41:36 2014 +0200 @@ -0,0 +1,14 @@ +#ifndef XFER_VIEW_H_ +#define XFER_VIEW_H_ + +#include "renderer.h" + +bool xfview_init(Renderer *rend); +void xfview_destroy(); + +void xfview_draw(); + +void xfview_button(int bn, int press, int x, int y); +void xfview_motion(int x, int y); + +#endif // XFER_VIEW_H_