metasurf

changeset 3:52664d3451ad

added volume rendering example
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 25 Oct 2011 13:30:03 +0300
parents 9ab057fba0c5
children 2c575855f707
files examples/metaballs/src/metaballs.c examples/volume/Makefile examples/volume/sdr/frag.glsl examples/volume/sdr/vert.glsl examples/volume/src/cam.c examples/volume/src/cam.h examples/volume/src/sdr.c examples/volume/src/sdr.h examples/volume/src/volume.c
diffstat 9 files changed, 1106 insertions(+), 1 deletions(-) [+]
line diff
     1.1 --- a/examples/metaballs/src/metaballs.c	Tue Oct 25 08:59:07 2011 +0300
     1.2 +++ b/examples/metaballs/src/metaballs.c	Tue Oct 25 13:30:03 2011 +0300
     1.3 @@ -31,7 +31,6 @@
     1.4  int num_mballs = sizeof mball / sizeof *mball;
     1.5  
     1.6  float eval(float x, float y, float z);
     1.7 -float eval_cached(float x, float y, float z);
     1.8  void vertex(float x, float y, float z);
     1.9  void render(void);
    1.10  void disp(void);
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/examples/volume/Makefile	Tue Oct 25 13:30:03 2011 +0300
     2.3 @@ -0,0 +1,34 @@
     2.4 +src = $(wildcard src/*.c)
     2.5 +obj = $(src:.c=.o)
     2.6 +dep = $(obj:.o=.d)
     2.7 +bin = volume
     2.8 +
     2.9 +# uncomment the following line to disable shaders (for old systems like SGI or whatever)
    2.10 +#nosdr = -DNO_SHADERS
    2.11 +
    2.12 +CC = gcc
    2.13 +CFLAGS = -pedantic -Wall -g -I../../src $(nosdr)
    2.14 +LDFLAGS = -L../.. -lmetasurf $(libgl) -limago
    2.15 +
    2.16 +ifeq ($(shell uname -s), Darwin)
    2.17 +	libgl = -framework OpenGL -framework GLUT -lGLEW
    2.18 +else
    2.19 +	libgl = -lGL -lGLU -lglut -lGLEW
    2.20 +endif
    2.21 +
    2.22 +$(bin): $(obj)
    2.23 +	$(CC) -o $@ $(obj) $(LDFLAGS)
    2.24 +
    2.25 +-include $(dep)
    2.26 +
    2.27 +%.d: %.c
    2.28 +	@$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@
    2.29 +
    2.30 +.PHONY: clean
    2.31 +clean:
    2.32 +	rm -f $(obj) $(bin)
    2.33 +
    2.34 +
    2.35 +.PHONY: cleandep
    2.36 +cleandep:
    2.37 +	rm -f $(dep)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/examples/volume/sdr/frag.glsl	Tue Oct 25 13:30:03 2011 +0300
     3.3 @@ -0,0 +1,19 @@
     3.4 +varying vec3 vpos, ldir, norm;
     3.5 +
     3.6 +void main()
     3.7 +{
     3.8 +	vec3 n = normalize(norm);
     3.9 +	vec3 l = normalize(ldir);
    3.10 +	vec3 v = -normalize(vpos);
    3.11 +	vec3 h = normalize(v + l);
    3.12 +
    3.13 +	const vec3 kd = vec3(0.87, 0.82, 0.74);
    3.14 +
    3.15 +	float diff = abs(dot(n, l));
    3.16 +	float spec = pow(abs(dot(n, h)), 60.0);
    3.17 +
    3.18 +	vec3 dcol = kd * diff;
    3.19 +	vec3 scol = vec3(0.8, 0.8, 0.8) * spec;
    3.20 +
    3.21 +	gl_FragColor = vec4(dcol + scol, 1.0);
    3.22 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/examples/volume/sdr/vert.glsl	Tue Oct 25 13:30:03 2011 +0300
     4.3 @@ -0,0 +1,10 @@
     4.4 +varying vec3 vpos, ldir, norm;
     4.5 +
     4.6 +void main()
     4.7 +{
     4.8 +	gl_Position = ftransform();
     4.9 +
    4.10 +	vpos = (gl_ModelViewMatrix * gl_Vertex).xyz;
    4.11 +	norm = gl_NormalMatrix * gl_Normal;
    4.12 +	ldir = gl_LightSource[0].position.xyz;
    4.13 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/examples/volume/src/cam.c	Tue Oct 25 13:30:03 2011 +0300
     5.3 @@ -0,0 +1,216 @@
     5.4 +#include <math.h>
     5.5 +#include "cam.h"
     5.6 +
     5.7 +#if defined(__APPLE__) && defined(__MACH__)
     5.8 +#include <OpenGL/gl.h>
     5.9 +#else
    5.10 +#include <GL/gl.h>
    5.11 +#endif
    5.12 +
    5.13 +#define DR				(M_PI / 180.0)
    5.14 +#define DEG_TO_RAD(x)	((x) * DR)
    5.15 +
    5.16 +typedef struct vec3 {
    5.17 +	float x, y, z;
    5.18 +} vec3_t;
    5.19 +
    5.20 +/* viewing parameters */
    5.21 +#define DEF_THETA	0
    5.22 +#define DEF_PHI		0
    5.23 +#define DEF_DIST	0
    5.24 +#define DEF_X		0
    5.25 +#define DEF_Y		0
    5.26 +#define DEF_Z		0
    5.27 +
    5.28 +static float cam_theta = DEF_THETA, cam_phi = DEF_PHI;
    5.29 +static float cam_dist = DEF_DIST;
    5.30 +static vec3_t cam_pos = {DEF_X, DEF_Y, DEF_Z};
    5.31 +
    5.32 +/* projection parameters */
    5.33 +#define DEF_VFOV	45.0
    5.34 +#define DEF_ASPECT	1.3333333
    5.35 +#define DEF_NEAR	1.0
    5.36 +#define DEF_FAR		1000.0
    5.37 +
    5.38 +static float vfov = DEF_VFOV;
    5.39 +static float aspect = DEF_ASPECT;
    5.40 +static float nearclip = DEF_NEAR, farclip = DEF_FAR;
    5.41 +
    5.42 +/* stereo parameters */
    5.43 +#define DEF_EYE_SEP		0.1
    5.44 +#define DEF_FOCUS_DIST	1.0
    5.45 +
    5.46 +static float eye_sep = DEF_EYE_SEP;
    5.47 +static float focus_dist = DEF_FOCUS_DIST;
    5.48 +
    5.49 +static float pan_speed = 0.001;
    5.50 +static float rot_speed = 0.5;
    5.51 +static float zoom_speed = 0.1;
    5.52 +
    5.53 +static float vmin_deg = -90.0, vmax_deg = 90.0;
    5.54 +
    5.55 +void cam_reset(void)
    5.56 +{
    5.57 +	cam_reset_view();
    5.58 +	cam_reset_proj();
    5.59 +	cam_reset_stereo();
    5.60 +}
    5.61 +
    5.62 +void cam_reset_view(void)
    5.63 +{
    5.64 +	cam_theta = DEF_THETA;
    5.65 +	cam_phi = DEF_PHI;
    5.66 +	cam_dist = DEF_DIST;
    5.67 +	cam_pos.x = DEF_X;
    5.68 +	cam_pos.y = DEF_Y;
    5.69 +	cam_pos.z = DEF_Z;
    5.70 +}
    5.71 +
    5.72 +void cam_reset_proj(void)
    5.73 +{
    5.74 +	vfov = DEF_VFOV;
    5.75 +	aspect = DEF_ASPECT;
    5.76 +	nearclip = DEF_NEAR;
    5.77 +	farclip = DEF_FAR;
    5.78 +}
    5.79 +
    5.80 +void cam_reset_stereo(void)
    5.81 +{
    5.82 +	eye_sep = DEF_EYE_SEP;
    5.83 +	focus_dist = DEF_FOCUS_DIST;
    5.84 +}
    5.85 +
    5.86 +void cam_set_vrange(float min_deg, float max_deg)
    5.87 +{
    5.88 +	vmin_deg = min_deg;
    5.89 +	vmax_deg = max_deg;
    5.90 +}
    5.91 +
    5.92 +void cam_move(float x, float y, float z)
    5.93 +{
    5.94 +	cam_pos.x += x;
    5.95 +	cam_pos.y += y;
    5.96 +	cam_pos.z += z;
    5.97 +}
    5.98 +
    5.99 +void cam_rotate(float theta, float phi)
   5.100 +{
   5.101 +	cam_phi += phi;
   5.102 +	cam_theta += theta;
   5.103 +}
   5.104 +
   5.105 +void cam_dolly(float dist)
   5.106 +{
   5.107 +	cam_dist += dist;
   5.108 +}
   5.109 +
   5.110 +void cam_inp_pan_speed(float speed)
   5.111 +{
   5.112 +	pan_speed = speed;
   5.113 +}
   5.114 +
   5.115 +void cam_inp_rotate_speed(float speed)
   5.116 +{
   5.117 +	rot_speed = speed;
   5.118 +}
   5.119 +
   5.120 +void cam_inp_zoom_speed(float speed)
   5.121 +{
   5.122 +	zoom_speed = speed;
   5.123 +}
   5.124 +
   5.125 +
   5.126 +void cam_inp_pan(int dx, int dy)
   5.127 +{
   5.128 +	float dxf = dx * pan_speed;
   5.129 +	float dyf = dy * pan_speed;
   5.130 +	float angle = -DEG_TO_RAD(cam_theta);
   5.131 +
   5.132 +	cam_pos.x += cos(angle) * dxf + sin(angle) * dyf;
   5.133 +	cam_pos.z += -sin(angle) * dxf + cos(angle) * dyf;
   5.134 +}
   5.135 +
   5.136 +void cam_inp_height(int dh)
   5.137 +{
   5.138 +	cam_pos.y += dh * pan_speed;
   5.139 +}
   5.140 +
   5.141 +void cam_inp_rotate(int dx, int dy)
   5.142 +{
   5.143 +	cam_theta += dx * rot_speed;
   5.144 +	cam_phi += dy * rot_speed;
   5.145 +
   5.146 +	if(cam_phi < vmin_deg) cam_phi = vmin_deg;
   5.147 +	if(cam_phi > vmax_deg) cam_phi = vmax_deg;
   5.148 +}
   5.149 +
   5.150 +void cam_inp_zoom(int dz)
   5.151 +{
   5.152 +	cam_dist += dz * zoom_speed;
   5.153 +	if(cam_dist < 0.001) {
   5.154 +		cam_dist = 0.001;
   5.155 +	}
   5.156 +}
   5.157 +
   5.158 +void cam_clip(float n, float f)
   5.159 +{
   5.160 +	nearclip = n;
   5.161 +	farclip = f;
   5.162 +}
   5.163 +
   5.164 +void cam_fov(float f)
   5.165 +{
   5.166 +	vfov = f;
   5.167 +}
   5.168 +
   5.169 +void cam_aspect(float a)
   5.170 +{
   5.171 +	aspect = a;
   5.172 +}
   5.173 +
   5.174 +void cam_separation(float s)
   5.175 +{
   5.176 +	eye_sep = s;
   5.177 +}
   5.178 +
   5.179 +void cam_focus_dist(float d)
   5.180 +{
   5.181 +	focus_dist = d;
   5.182 +
   5.183 +	cam_separation(d / 30.0);
   5.184 +}
   5.185 +
   5.186 +void cam_view_matrix(void)
   5.187 +{
   5.188 +	cam_stereo_view_matrix(CAM_CENTER);
   5.189 +}
   5.190 +
   5.191 +void cam_stereo_view_matrix(int eye)
   5.192 +{
   5.193 +	static const float offs_sign[] = {0.0f, 0.5f, -0.5f};	/* center, left, right */
   5.194 +	float offs = eye_sep * offs_sign[eye];
   5.195 +
   5.196 +	glTranslatef(offs, 0, 0);
   5.197 +
   5.198 +	glTranslatef(0, 0, -cam_dist);
   5.199 +	glRotatef(cam_phi, 1, 0, 0);
   5.200 +	glRotatef(cam_theta, 0, 1, 0);
   5.201 +	glTranslatef(-cam_pos.x, -cam_pos.y, -cam_pos.z);
   5.202 +}
   5.203 +
   5.204 +void cam_proj_matrix(void)
   5.205 +{
   5.206 +	cam_stereo_proj_matrix(CAM_CENTER);
   5.207 +}
   5.208 +
   5.209 +void cam_stereo_proj_matrix(int eye)
   5.210 +{
   5.211 +	float vfov_rad = M_PI * vfov / 180.0;
   5.212 +	float top = nearclip * tan(vfov_rad * 0.5);
   5.213 +	float right = top * aspect;
   5.214 +
   5.215 +	static const float offs_sign[] = {0.0f, 1.0, -1.0};	/* center, left, right */
   5.216 +	float frust_shift = offs_sign[eye] * (eye_sep * 0.5 * nearclip / focus_dist);
   5.217 +
   5.218 +	glFrustum(-right + frust_shift, right + frust_shift, -top, top, nearclip, farclip);
   5.219 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/examples/volume/src/cam.h	Tue Oct 25 13:30:03 2011 +0300
     6.3 @@ -0,0 +1,54 @@
     6.4 +#ifndef CAM_H_
     6.5 +#define CAM_H_
     6.6 +
     6.7 +enum {
     6.8 +	CAM_CENTER,
     6.9 +	CAM_LEFT,
    6.10 +	CAM_RIGHT
    6.11 +};
    6.12 +
    6.13 +/* reset to the initial state */
    6.14 +void cam_reset(void);			/* all */
    6.15 +void cam_reset_view(void);		/* view parameters */
    6.16 +void cam_reset_proj(void);		/* projection parameters */
    6.17 +void cam_reset_stereo(void);	/* stereo parameters */
    6.18 +
    6.19 +void cam_set_vrange(float min_deg, float max_deg);
    6.20 +
    6.21 +void cam_move(float x, float y, float z);
    6.22 +void cam_rotate(float theta, float phi);
    6.23 +void cam_dolly(float dist);
    6.24 +
    6.25 +/* camera input handling */
    6.26 +void cam_inp_pan_speed(float speed);
    6.27 +void cam_inp_rotate_speed(float speed);
    6.28 +void cam_inp_zoom_speed(float speed);
    6.29 +
    6.30 +void cam_inp_pan(int dx, int dy);		/* pan across X/Z plane */
    6.31 +void cam_inp_height(int dh);			/* move verticaly */
    6.32 +void cam_inp_rotate(int dx, int dy);	/* rotate around local Y and X axis */
    6.33 +void cam_inp_zoom(int dz);				/* dolly the camera fwd/back */
    6.34 +
    6.35 +/* camera projection parameters */
    6.36 +void cam_clip(float n, float f);	/* set clipping planes */
    6.37 +void cam_fov(float f);				/* vertical field of view in degrees */
    6.38 +void cam_aspect(float a);			/* aspect ratio (width / height) */
    6.39 +
    6.40 +/* stereo parameters */
    6.41 +void cam_separation(float s);
    6.42 +void cam_focus_dist(float d);
    6.43 +
    6.44 +
    6.45 +/* multiply the camera view matrix on top of the current matrix stack
    6.46 + * (which should be GL_MODELVIEW)
    6.47 + */
    6.48 +void cam_view_matrix(void);
    6.49 +void cam_stereo_view_matrix(int eye);
    6.50 +
    6.51 +/* multiply the camera projection matrix on top of the current matrix stack
    6.52 + * (which should be GL_PROJECTION)
    6.53 + */
    6.54 +void cam_proj_matrix(void);
    6.55 +void cam_stereo_proj_matrix(int eye);
    6.56 +
    6.57 +#endif	/* CAM_H_ */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/examples/volume/src/sdr.c	Tue Oct 25 13:30:03 2011 +0300
     7.3 @@ -0,0 +1,333 @@
     7.4 +#ifndef NO_SHADERS
     7.5 +
     7.6 +#include <stdio.h>
     7.7 +#include <stdlib.h>
     7.8 +#include <string.h>
     7.9 +#include <errno.h>
    7.10 +#include <assert.h>
    7.11 +#include <GL/glew.h>
    7.12 +
    7.13 +#if defined(unix) || defined(__unix__)
    7.14 +#include <unistd.h>
    7.15 +#include <sys/stat.h>
    7.16 +#endif	/* unix */
    7.17 +
    7.18 +#include "sdr.h"
    7.19 +
    7.20 +unsigned int create_vertex_shader(const char *src)
    7.21 +{
    7.22 +	return create_shader(src, GL_VERTEX_SHADER);
    7.23 +}
    7.24 +
    7.25 +unsigned int create_pixel_shader(const char *src)
    7.26 +{
    7.27 +	return create_shader(src, GL_FRAGMENT_SHADER);
    7.28 +}
    7.29 +
    7.30 +unsigned int create_shader(const char *src, unsigned int sdr_type)
    7.31 +{
    7.32 +	unsigned int sdr;
    7.33 +	int success, info_len;
    7.34 +	char *info_str = 0;
    7.35 +	GLenum err;
    7.36 +
    7.37 +	sdr = glCreateShader(sdr_type);
    7.38 +	assert(glGetError() == GL_NO_ERROR);
    7.39 +	glShaderSource(sdr, 1, &src, 0);
    7.40 +	err = glGetError();
    7.41 +	assert(err == GL_NO_ERROR);
    7.42 +	glCompileShader(sdr);
    7.43 +	assert(glGetError() == GL_NO_ERROR);
    7.44 +
    7.45 +	glGetShaderiv(sdr, GL_COMPILE_STATUS, &success);
    7.46 +	assert(glGetError() == GL_NO_ERROR);
    7.47 +	glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len);
    7.48 +	assert(glGetError() == GL_NO_ERROR);
    7.49 +
    7.50 +	if(info_len) {
    7.51 +		if((info_str = malloc(info_len + 1))) {
    7.52 +			glGetShaderInfoLog(sdr, info_len, 0, info_str);
    7.53 +			assert(glGetError() == GL_NO_ERROR);
    7.54 +		}
    7.55 +	}
    7.56 +
    7.57 +	if(success) {
    7.58 +		fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str);
    7.59 +	} else {
    7.60 +		fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str);
    7.61 +		glDeleteShader(sdr);
    7.62 +		sdr = 0;
    7.63 +	}
    7.64 +
    7.65 +	free(info_str);
    7.66 +	return sdr;
    7.67 +}
    7.68 +
    7.69 +void free_shader(unsigned int sdr)
    7.70 +{
    7.71 +	glDeleteShader(sdr);
    7.72 +}
    7.73 +
    7.74 +unsigned int load_vertex_shader(const char *fname)
    7.75 +{
    7.76 +	return load_shader(fname, GL_VERTEX_SHADER);
    7.77 +}
    7.78 +
    7.79 +unsigned int load_pixel_shader(const char *fname)
    7.80 +{
    7.81 +	return load_shader(fname, GL_FRAGMENT_SHADER);
    7.82 +}
    7.83 +
    7.84 +unsigned int load_shader(const char *fname, unsigned int sdr_type)
    7.85 +{
    7.86 +#if defined(unix) || defined(__unix__)
    7.87 +	struct stat st;
    7.88 +#endif
    7.89 +	unsigned int sdr;
    7.90 +	size_t filesize;
    7.91 +	FILE *fp;
    7.92 +	char *src;
    7.93 +
    7.94 +	if(!(fp = fopen(fname, "r"))) {
    7.95 +		fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno));
    7.96 +		return 0;
    7.97 +	}
    7.98 +
    7.99 +#if defined(unix) || defined(__unix__)
   7.100 +	fstat(fileno(fp), &st);
   7.101 +	filesize = st.st_size;
   7.102 +#else
   7.103 +	fseek(fp, 0, SEEK_END);
   7.104 +	filesize = ftell(fp);
   7.105 +	fseek(fp, 0, SEEK_SET);
   7.106 +#endif	/* unix */
   7.107 +
   7.108 +	if(!(src = malloc(filesize + 1))) {
   7.109 +		fclose(fp);
   7.110 +		return 0;
   7.111 +	}
   7.112 +	fread(src, 1, filesize, fp);
   7.113 +	src[filesize] = 0;
   7.114 +	fclose(fp);
   7.115 +
   7.116 +	fprintf(stderr, "compiling %s shader: %s... ", (sdr_type == GL_VERTEX_SHADER ? "vertex" : "pixel"), fname);
   7.117 +	sdr = create_shader(src, sdr_type);
   7.118 +
   7.119 +	free(src);
   7.120 +	return sdr;
   7.121 +}
   7.122 +
   7.123 +
   7.124 +unsigned int get_vertex_shader(const char *fname)
   7.125 +{
   7.126 +	return get_shader(fname, GL_VERTEX_SHADER);
   7.127 +}
   7.128 +
   7.129 +unsigned int get_pixel_shader(const char *fname)
   7.130 +{
   7.131 +	return get_shader(fname, GL_FRAGMENT_SHADER);
   7.132 +}
   7.133 +
   7.134 +unsigned int get_shader(const char *fname, unsigned int sdr_type)
   7.135 +{
   7.136 +	unsigned int sdr;
   7.137 +
   7.138 +	if(!(sdr = load_shader(fname, sdr_type))) {
   7.139 +		return 0;
   7.140 +	}
   7.141 +	return sdr;
   7.142 +}
   7.143 +
   7.144 +
   7.145 +/* ---- gpu programs ---- */
   7.146 +
   7.147 +unsigned int create_program(void)
   7.148 +{
   7.149 +	unsigned int prog = glCreateProgram();
   7.150 +	assert(glGetError() == GL_NO_ERROR);
   7.151 +	return prog;
   7.152 +}
   7.153 +
   7.154 +unsigned int create_program_link(unsigned int vs, unsigned int ps)
   7.155 +{
   7.156 +	unsigned int prog;
   7.157 +
   7.158 +	if(!(prog = create_program())) {
   7.159 +		return 0;
   7.160 +	}
   7.161 +
   7.162 +	if(vs) {
   7.163 +		attach_shader(prog, vs);
   7.164 +		assert(glGetError() == GL_NO_ERROR);
   7.165 +	}
   7.166 +	if(ps) {
   7.167 +		attach_shader(prog, ps);
   7.168 +		assert(glGetError() == GL_NO_ERROR);
   7.169 +	}
   7.170 +
   7.171 +	if(link_program(prog) == -1) {
   7.172 +		free_program(prog);
   7.173 +		return 0;
   7.174 +	}
   7.175 +	return prog;
   7.176 +}
   7.177 +
   7.178 +unsigned int create_program_load(const char *vfile, const char *pfile)
   7.179 +{
   7.180 +	unsigned int vs = 0, ps = 0;
   7.181 +
   7.182 +	if(vfile && !(vs = get_vertex_shader(vfile))) {
   7.183 +		return 0;
   7.184 +	}
   7.185 +	if(pfile && !(ps = get_pixel_shader(pfile))) {
   7.186 +		return 0;
   7.187 +	}
   7.188 +	return create_program_link(vs, ps);
   7.189 +}
   7.190 +
   7.191 +void free_program(unsigned int sdr)
   7.192 +{
   7.193 +	glDeleteProgram(sdr);
   7.194 +}
   7.195 +
   7.196 +void attach_shader(unsigned int prog, unsigned int sdr)
   7.197 +{
   7.198 +	glAttachShader(prog, sdr);
   7.199 +	assert(glGetError() == GL_NO_ERROR);
   7.200 +}
   7.201 +
   7.202 +int link_program(unsigned int prog)
   7.203 +{
   7.204 +	int linked, info_len, retval = 0;
   7.205 +	char *info_str = 0;
   7.206 +
   7.207 +	glLinkProgram(prog);
   7.208 +	assert(glGetError() == GL_NO_ERROR);
   7.209 +	glGetProgramiv(prog, GL_LINK_STATUS, &linked);
   7.210 +	assert(glGetError() == GL_NO_ERROR);
   7.211 +	glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len);
   7.212 +	assert(glGetError() == GL_NO_ERROR);
   7.213 +
   7.214 +	if(info_len) {
   7.215 +		if((info_str = malloc(info_len + 1))) {
   7.216 +			glGetProgramInfoLog(prog, info_len, 0, info_str);
   7.217 +			assert(glGetError() == GL_NO_ERROR);
   7.218 +		}
   7.219 +	}
   7.220 +
   7.221 +	if(linked) {
   7.222 +		fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str);
   7.223 +	} else {
   7.224 +		fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str);
   7.225 +		retval = -1;
   7.226 +	}
   7.227 +
   7.228 +	free(info_str);
   7.229 +	return retval;
   7.230 +}
   7.231 +
   7.232 +int bind_program(unsigned int prog)
   7.233 +{
   7.234 +	GLenum err;
   7.235 +
   7.236 +	glUseProgram(prog);
   7.237 +	if(prog && (err = glGetError()) != GL_NO_ERROR) {
   7.238 +		/* maybe the program is not linked, try linking first */
   7.239 +		if(err == GL_INVALID_OPERATION) {
   7.240 +			if(link_program(prog) == -1) {
   7.241 +				return -1;
   7.242 +			}
   7.243 +			glUseProgram(prog);
   7.244 +			return glGetError() == GL_NO_ERROR ? 0 : -1;
   7.245 +		}
   7.246 +		return -1;
   7.247 +	}
   7.248 +	return 0;
   7.249 +}
   7.250 +
   7.251 +/* ugly but I'm not going to write the same bloody code over and over */
   7.252 +#define BEGIN_UNIFORM_CODE \
   7.253 +	int loc, curr_prog; \
   7.254 +	glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \
   7.255 +	if(curr_prog != prog && bind_program(prog) == -1) { \
   7.256 +		return -1; \
   7.257 +	} \
   7.258 +	if((loc = glGetUniformLocation(prog, name)) != -1)
   7.259 +
   7.260 +#define END_UNIFORM_CODE \
   7.261 +	if(curr_prog != prog) { \
   7.262 +		bind_program(curr_prog); \
   7.263 +	} \
   7.264 +	return loc == -1 ? -1 : 0
   7.265 +
   7.266 +int set_uniform_int(unsigned int prog, const char *name, int val)
   7.267 +{
   7.268 +	BEGIN_UNIFORM_CODE {
   7.269 +		glUniform1i(loc, val);
   7.270 +	}
   7.271 +	END_UNIFORM_CODE;
   7.272 +}
   7.273 +
   7.274 +int set_uniform_float(unsigned int prog, const char *name, float val)
   7.275 +{
   7.276 +	BEGIN_UNIFORM_CODE {
   7.277 +		glUniform1f(loc, val);
   7.278 +	}
   7.279 +	END_UNIFORM_CODE;
   7.280 +}
   7.281 +
   7.282 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z)
   7.283 +{
   7.284 +	BEGIN_UNIFORM_CODE {
   7.285 +		glUniform3f(loc, x, y, z);
   7.286 +	}
   7.287 +	END_UNIFORM_CODE;
   7.288 +}
   7.289 +
   7.290 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w)
   7.291 +{
   7.292 +	BEGIN_UNIFORM_CODE {
   7.293 +		glUniform4f(loc, x, y, z, w);
   7.294 +	}
   7.295 +	END_UNIFORM_CODE;
   7.296 +}
   7.297 +
   7.298 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat)
   7.299 +{
   7.300 +	BEGIN_UNIFORM_CODE {
   7.301 +		glUniformMatrix4fv(loc, 1, GL_FALSE, mat);
   7.302 +	}
   7.303 +	END_UNIFORM_CODE;
   7.304 +}
   7.305 +
   7.306 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat)
   7.307 +{
   7.308 +	BEGIN_UNIFORM_CODE {
   7.309 +		glUniformMatrix4fv(loc, 1, GL_TRUE, mat);
   7.310 +	}
   7.311 +	END_UNIFORM_CODE;
   7.312 +}
   7.313 +
   7.314 +int get_attrib_loc(unsigned int prog, const char *name)
   7.315 +{
   7.316 +	int loc, curr_prog;
   7.317 +
   7.318 +	glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog);
   7.319 +	if(curr_prog != prog && bind_program(prog) == -1) {
   7.320 +		return -1;
   7.321 +	}
   7.322 +
   7.323 +	loc = glGetAttribLocation(prog, (char*)name);
   7.324 +
   7.325 +	if(curr_prog != prog) {
   7.326 +		bind_program(curr_prog);
   7.327 +	}
   7.328 +	return loc;
   7.329 +}
   7.330 +
   7.331 +void set_attrib_float3(int attr_loc, float x, float y, float z)
   7.332 +{
   7.333 +	glVertexAttrib3f(attr_loc, x, y, z);
   7.334 +}
   7.335 +
   7.336 +#endif	/* !NO_SHADERS */
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/examples/volume/src/sdr.h	Tue Oct 25 13:30:03 2011 +0300
     8.3 @@ -0,0 +1,49 @@
     8.4 +#ifndef SDR_H_
     8.5 +#define SDR_H_
     8.6 +
     8.7 +#ifdef __cplusplus
     8.8 +extern "C" {
     8.9 +#endif	/* __cplusplus */
    8.10 +
    8.11 +/* ---- shaders ---- */
    8.12 +unsigned int create_vertex_shader(const char *src);
    8.13 +unsigned int create_pixel_shader(const char *src);
    8.14 +unsigned int create_shader(const char *src, unsigned int sdr_type);
    8.15 +void free_shader(unsigned int sdr);
    8.16 +
    8.17 +unsigned int load_vertex_shader(const char *fname);
    8.18 +unsigned int load_pixel_shader(const char *fname);
    8.19 +unsigned int load_shader(const char *src, unsigned int sdr_type);
    8.20 +
    8.21 +unsigned int get_vertex_shader(const char *fname);
    8.22 +unsigned int get_pixel_shader(const char *fname);
    8.23 +unsigned int get_shader(const char *fname, unsigned int sdr_type);
    8.24 +
    8.25 +int add_shader(const char *fname, unsigned int sdr);
    8.26 +int remove_shader(const char *fname);
    8.27 +
    8.28 +/* ---- gpu programs ---- */
    8.29 +unsigned int create_program(void);
    8.30 +unsigned int create_program_link(unsigned int vs, unsigned int ps);
    8.31 +unsigned int create_program_load(const char *vfile, const char *pfile);
    8.32 +void free_program(unsigned int sdr);
    8.33 +
    8.34 +void attach_shader(unsigned int prog, unsigned int sdr);
    8.35 +int link_program(unsigned int prog);
    8.36 +int bind_program(unsigned int prog);
    8.37 +
    8.38 +int set_uniform_int(unsigned int prog, const char *name, int val);
    8.39 +int set_uniform_float(unsigned int prog, const char *name, float val);
    8.40 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z);
    8.41 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w);
    8.42 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat);
    8.43 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat);
    8.44 +
    8.45 +int get_attrib_loc(unsigned int prog, const char *name);
    8.46 +void set_attrib_float3(int attr_loc, float x, float y, float z);
    8.47 +
    8.48 +#ifdef __cplusplus
    8.49 +}
    8.50 +#endif	/* __cplusplus */
    8.51 +
    8.52 +#endif	/* SDR_H_ */
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/examples/volume/src/volume.c	Tue Oct 25 13:30:03 2011 +0300
     9.3 @@ -0,0 +1,391 @@
     9.4 +#include <stdio.h>
     9.5 +#include <stdlib.h>
     9.6 +#include <math.h>
     9.7 +#include <assert.h>
     9.8 +
     9.9 +#ifndef NO_SHADERS
    9.10 +#include <GL/glew.h>
    9.11 +#include "sdr.h"
    9.12 +#endif
    9.13 +
    9.14 +#ifndef __APPLE__
    9.15 +#include <GL/glut.h>
    9.16 +#else
    9.17 +#include <GLUT/glut.h>
    9.18 +#endif
    9.19 +
    9.20 +#include <imago2.h>
    9.21 +
    9.22 +#include "cam.h"
    9.23 +#include "metasurf.h"
    9.24 +
    9.25 +float eval(float x, float y, float z);
    9.26 +void vertex(float x, float y, float z);
    9.27 +void render(void);
    9.28 +void disp(void);
    9.29 +void reshape(int x, int y);
    9.30 +void keyb(unsigned char key, int x, int y);
    9.31 +void mouse(int bn, int state, int x, int y);
    9.32 +void motion(int x, int y);
    9.33 +int parse_args(int argc, char **argv);
    9.34 +
    9.35 +int stereo, fullscreen;
    9.36 +int orig_xsz, orig_ysz;
    9.37 +
    9.38 +struct metasurface *msurf;
    9.39 +float threshold = 0.5;
    9.40 +#ifndef NO_SHADERS
    9.41 +unsigned int sdr;
    9.42 +#endif
    9.43 +
    9.44 +struct img_pixmap *volume;
    9.45 +int xres, yres, num_slices;
    9.46 +
    9.47 +int dlist, need_update = 1;
    9.48 +
    9.49 +int main(int argc, char **argv)
    9.50 +{
    9.51 +	float amb[] = {0, 0, 0, 0};
    9.52 +	float lpos[] = {-0.2, 0.2, 1, 0};
    9.53 +
    9.54 +	glutInitWindowSize(1280, 720);
    9.55 +	glutInit(&argc, argv);
    9.56 +
    9.57 +	if(parse_args(argc, argv) == -1) {
    9.58 +		return 1;
    9.59 +	}
    9.60 +	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | (stereo ? GLUT_STEREO : 0));
    9.61 +	glutCreateWindow("metasurf - volume rendering");
    9.62 +
    9.63 +	orig_xsz = glutGet(GLUT_WINDOW_WIDTH);
    9.64 +	orig_ysz = glutGet(GLUT_WINDOW_HEIGHT);
    9.65 +
    9.66 +	if(fullscreen) {
    9.67 +		glutFullScreen();
    9.68 +	}
    9.69 +
    9.70 +	glutDisplayFunc(disp);
    9.71 +	glutReshapeFunc(reshape);
    9.72 +	glutKeyboardFunc(keyb);
    9.73 +	glutMouseFunc(mouse);
    9.74 +	glutMotionFunc(motion);
    9.75 +
    9.76 +#ifndef NO_SHADERS
    9.77 +	glewInit();
    9.78 +	if(!(sdr = create_program_load("sdr/vert.glsl", "sdr/frag.glsl"))) {
    9.79 +		return 1;
    9.80 +	}
    9.81 +#endif
    9.82 +
    9.83 +	glEnable(GL_CULL_FACE);
    9.84 +	glEnable(GL_DEPTH_TEST);
    9.85 +
    9.86 +	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
    9.87 +
    9.88 +	glEnable(GL_LIGHTING);
    9.89 +	glEnable(GL_LIGHT0);
    9.90 +	glLightfv(GL_LIGHT0, GL_POSITION, lpos);
    9.91 +
    9.92 +	glEnable(GL_NORMALIZE);
    9.93 +
    9.94 +	cam_focus_dist(3.0);
    9.95 +	cam_clip(0.1, 200.0);
    9.96 +	cam_rotate(0, 0);
    9.97 +	cam_dolly(2);
    9.98 +
    9.99 +	msurf = msurf_create();
   9.100 +	msurf_eval_func(msurf, eval);
   9.101 +	msurf_vertex_func(msurf, vertex);
   9.102 +	msurf_threshold(msurf, threshold);
   9.103 +	msurf_resolution(msurf, xres, yres, num_slices);
   9.104 +	msurf_bounds(msurf, -1, -1, -1, 1, 1, 1);
   9.105 +
   9.106 +	glClearColor(0.6, 0.6, 0.6, 1.0);
   9.107 +
   9.108 +	dlist = glGenLists(1);
   9.109 +
   9.110 +	glutMainLoop();
   9.111 +	return 0;
   9.112 +}
   9.113 +
   9.114 +float eval(float x, float y, float z)
   9.115 +{
   9.116 +	int px, py, slice;
   9.117 +	struct img_pixmap *img;
   9.118 +
   9.119 +	px = round((x * 0.5 + 0.5) * xres);
   9.120 +	py = round((y * 0.5 + 0.5) * yres);
   9.121 +	slice = round((z * 0.5 + 0.5) * num_slices);
   9.122 +
   9.123 +	if(px < 0) px = 0;
   9.124 +	if(px >= xres) px = xres - 1;
   9.125 +
   9.126 +	if(py < 0) py = 0;
   9.127 +	if(py >= yres) py = yres - 1;
   9.128 +
   9.129 +	if(slice < 0) slice = 0;
   9.130 +	if(slice >= num_slices) slice = num_slices - 1;
   9.131 +
   9.132 +	img = volume + slice;
   9.133 +	return *((unsigned char*)img->pixels + py * img->width + px) / 255.0;
   9.134 +}
   9.135 +
   9.136 +void vertex(float x, float y, float z)
   9.137 +{
   9.138 +	float dx = 1.0 / xres;
   9.139 +	float dy = 1.0 / yres;
   9.140 +	float dz = 1.0 / num_slices;
   9.141 +	float dfdx = eval(x - dx, y, z) - eval(x + dx, y, z);
   9.142 +	float dfdy = eval(x, y - dy, z) - eval(x, y + dy, z);
   9.143 +	float dfdz = eval(x, y, z - dz) - eval(x, y, z + dz);
   9.144 +
   9.145 +	glNormal3f(dfdx, dfdy, dfdz);
   9.146 +	glVertex3f(x, y, z);
   9.147 +}
   9.148 +
   9.149 +void render(void)
   9.150 +{
   9.151 +	float kd[] = {0.87, 0.82, 0.74, 1.0};
   9.152 +	float ks[] = {0.9, 0.9, 0.9, 1.0};
   9.153 +
   9.154 +	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, kd);
   9.155 +	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, ks);
   9.156 +	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 60.0);
   9.157 +
   9.158 +#ifndef NO_SHADERS
   9.159 +	bind_program(sdr);
   9.160 +#endif
   9.161 +
   9.162 +	glMatrixMode(GL_MODELVIEW);
   9.163 +	glPushMatrix();
   9.164 +	glRotatef(90, 1, 0, 0);
   9.165 +
   9.166 +	if(need_update) {
   9.167 +		glNewList(dlist, GL_COMPILE);
   9.168 +		glBegin(GL_TRIANGLES);
   9.169 +		printf("generating mesh... ");
   9.170 +		fflush(stdout);
   9.171 +		msurf_polygonize(msurf);
   9.172 +		glEnd();
   9.173 +		glEndList();
   9.174 +		need_update = 0;
   9.175 +		printf("done\n");
   9.176 +	}
   9.177 +	glCallList(dlist);
   9.178 +
   9.179 +	glPopMatrix();
   9.180 +
   9.181 +	assert(glGetError() == GL_NO_ERROR);
   9.182 +}
   9.183 +
   9.184 +void disp(void)
   9.185 +{
   9.186 +	if(stereo) {
   9.187 +		glDrawBuffer(GL_BACK_LEFT);
   9.188 +	}
   9.189 +
   9.190 +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   9.191 +
   9.192 +	glMatrixMode(GL_PROJECTION);
   9.193 +	glLoadIdentity();
   9.194 +	cam_stereo_proj_matrix(stereo ? CAM_LEFT : CAM_CENTER);
   9.195 +
   9.196 +	glMatrixMode(GL_MODELVIEW);
   9.197 +	glLoadIdentity();
   9.198 +	cam_stereo_view_matrix(stereo ? CAM_LEFT : CAM_CENTER);
   9.199 +
   9.200 +	render();
   9.201 +
   9.202 +	if(stereo) {
   9.203 +		glDrawBuffer(GL_BACK_RIGHT);
   9.204 +		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   9.205 +
   9.206 +		glMatrixMode(GL_PROJECTION);
   9.207 +		glLoadIdentity();
   9.208 +		cam_stereo_proj_matrix(CAM_RIGHT);
   9.209 +
   9.210 +		glMatrixMode(GL_MODELVIEW);
   9.211 +		glLoadIdentity();
   9.212 +		cam_stereo_view_matrix(CAM_RIGHT);
   9.213 +
   9.214 +		render();
   9.215 +	}
   9.216 +	glutSwapBuffers();
   9.217 +}
   9.218 +
   9.219 +void reshape(int x, int y)
   9.220 +{
   9.221 +	glViewport(0, 0, x, y);
   9.222 +	cam_aspect((float)x / (float)y);
   9.223 +}
   9.224 +
   9.225 +void keyb(unsigned char key, int x, int y)
   9.226 +{
   9.227 +	static int wire;
   9.228 +
   9.229 +	switch(key) {
   9.230 +	case 27:
   9.231 +		exit(0);
   9.232 +
   9.233 +	case 'f':
   9.234 +		fullscreen = !fullscreen;
   9.235 +		if(fullscreen) {
   9.236 +			glutFullScreen();
   9.237 +		} else {
   9.238 +			glutReshapeWindow(orig_xsz, orig_ysz);
   9.239 +		}
   9.240 +		break;
   9.241 +
   9.242 +	case 's':
   9.243 +		stereo = !stereo;
   9.244 +		glutPostRedisplay();
   9.245 +		break;
   9.246 +
   9.247 +	case 'w':
   9.248 +		wire = !wire;
   9.249 +		glPolygonMode(GL_FRONT_AND_BACK, wire ? GL_LINE : GL_FILL);
   9.250 +		glutPostRedisplay();
   9.251 +		break;
   9.252 +
   9.253 +	case '=':
   9.254 +		threshold += 0.05;
   9.255 +		msurf_threshold(msurf, threshold);
   9.256 +		printf("threshold: %f\n", threshold);
   9.257 +		glutPostRedisplay();
   9.258 +		need_update = 1;
   9.259 +		break;
   9.260 +
   9.261 +	case '-':
   9.262 +		threshold -= 0.05;
   9.263 +		msurf_threshold(msurf, threshold);
   9.264 +		printf("threshold: %f\n", threshold);
   9.265 +		glutPostRedisplay();
   9.266 +		need_update = 1;
   9.267 +		break;
   9.268 +
   9.269 +	default:
   9.270 +		break;
   9.271 +	}
   9.272 +}
   9.273 +
   9.274 +int bnstate[32];
   9.275 +int prev_x, prev_y;
   9.276 +
   9.277 +void mouse(int bn, int state, int x, int y)
   9.278 +{
   9.279 +	bnstate[bn] = state == GLUT_DOWN;
   9.280 +	prev_x = x;
   9.281 +	prev_y = y;
   9.282 +}
   9.283 +
   9.284 +void motion(int x, int y)
   9.285 +{
   9.286 +	int dx, dy;
   9.287 +
   9.288 +	dx = x - prev_x;
   9.289 +	dy = y - prev_y;
   9.290 +	prev_x = x;
   9.291 +	prev_y = y;
   9.292 +
   9.293 +	if(bnstate[GLUT_LEFT_BUTTON]) {
   9.294 +		cam_inp_rotate(dx, dy);
   9.295 +	}
   9.296 +	if(bnstate[GLUT_RIGHT_BUTTON]) {
   9.297 +		cam_inp_zoom(dy);
   9.298 +	}
   9.299 +	glutPostRedisplay();
   9.300 +}
   9.301 +
   9.302 +struct list_node {
   9.303 +	struct img_pixmap img;
   9.304 +	struct list_node *next;
   9.305 +};
   9.306 +
   9.307 +int parse_args(int argc, char **argv)
   9.308 +{
   9.309 +	int i;
   9.310 +	struct list_node *head = 0, *tail = 0;
   9.311 +
   9.312 +	for(i=1; i<argc; i++) {
   9.313 +		if(argv[i][0] == '-' && argv[i][2] == 0) {
   9.314 +			switch(argv[i][1]) {
   9.315 +			case 'f':
   9.316 +				fullscreen = !fullscreen;
   9.317 +				break;
   9.318 +
   9.319 +			case 's':
   9.320 +				stereo = !stereo;
   9.321 +				break;
   9.322 +
   9.323 +			case 'h':
   9.324 +				printf("usage: %s [opt]\n", argv[0]);
   9.325 +				printf("options:\n");
   9.326 +				printf("  -f    start in fullscreen\n");
   9.327 +				printf("  -s    enable stereoscopic rendering\n");
   9.328 +				printf("  -h    print usage and exit\n");
   9.329 +				exit(0);
   9.330 +
   9.331 +			default:
   9.332 +				fprintf(stderr, "unrecognized option: %s\n", argv[i]);
   9.333 +				return -1;
   9.334 +			}
   9.335 +		} else {
   9.336 +			struct list_node *slice;
   9.337 +
   9.338 +			if(!(slice = malloc(sizeof *slice))) {
   9.339 +				fprintf(stderr, "failed to allocate volume slice: %d\n", num_slices);
   9.340 +				return -1;
   9.341 +			}
   9.342 +			slice->next = 0;
   9.343 +
   9.344 +			img_init(&slice->img);
   9.345 +			if(img_load(&slice->img, argv[i]) == -1) {
   9.346 +				fprintf(stderr, "failed to load volume slice %d: %s\n", num_slices, argv[i]);
   9.347 +				free(slice);
   9.348 +				return -1;
   9.349 +			}
   9.350 +			img_convert(&slice->img, IMG_FMT_GREY8);
   9.351 +
   9.352 +			if(num_slices > 0 && (xres != slice->img.width || yres != slice->img.height)) {
   9.353 +				fprintf(stderr, "error: slice %d (%s) is %dx%d, up to now we had %dx%d images\n", num_slices, argv[i],
   9.354 +						slice->img.width, slice->img.height, xres, yres);
   9.355 +				img_destroy(&slice->img);
   9.356 +				free(slice);
   9.357 +				return -1;
   9.358 +			}
   9.359 +			xres = slice->img.width;
   9.360 +			yres = slice->img.height;
   9.361 +
   9.362 +			if(head) {
   9.363 +				tail->next = slice;
   9.364 +				tail = slice;
   9.365 +			} else {
   9.366 +				head = tail = slice;
   9.367 +			}
   9.368 +			printf("loaded volume slice %d: %s\n", num_slices++, argv[i]);
   9.369 +		}
   9.370 +	}
   9.371 +
   9.372 +	if(!head) {
   9.373 +		fprintf(stderr, "you must specify a list of images for the volume data slices\n");
   9.374 +		return -1;
   9.375 +	}
   9.376 +
   9.377 +	if(!(volume = malloc(num_slices * sizeof *volume))) {
   9.378 +		fprintf(stderr, "failed to allocate volume data (%d slices)\n", num_slices);
   9.379 +		return -1;
   9.380 +	}
   9.381 +
   9.382 +	for(i=0; i<num_slices; i++) {
   9.383 +		void *tmp;
   9.384 +
   9.385 +		assert(head);
   9.386 +		volume[i] = head->img;
   9.387 +
   9.388 +		tmp = head;
   9.389 +		head = head->next;
   9.390 +		free(tmp);
   9.391 +	}
   9.392 +
   9.393 +	return 0;
   9.394 +}