metasurf

changeset 1:dc0e882ec3f9

renamed example source file test.c -> metaballs.c
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 25 Oct 2011 07:57:07 +0300
parents 7aa4627e492b
children 9ab057fba0c5
files README examples/metaballs/Makefile examples/metaballs/src/metaballs.c examples/metaballs/src/test.c
diffstat 4 files changed, 359 insertions(+), 310 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/README	Tue Oct 25 07:57:07 2011 +0300
     1.3 @@ -0,0 +1,49 @@
     1.4 +metasurf - a library for implicit surface polygonization
     1.5 +
     1.6 +1. Overview
     1.7 +-----------
     1.8 +
     1.9 +Metasurf is a library for implict surface polygonization. You only need to
    1.10 +set a callback that returns the scalar field value at any given point in
    1.11 +3-space, and another callback to accept isosurface vertices. Then at any point
    1.12 +just call msurf_polygonize, and the library handles everything else for you.
    1.13 +
    1.14 +2. Usage
    1.15 +--------
    1.16 +The following snippet is sufficient to draw the surface of an implict sphere.
    1.17 +
    1.18 +     struct metasurface *ms;
    1.19 +     
    1.20 +     /* initialization */
    1.21 +     ms = msurf_create();
    1.22 +     msurf_eval_func(ms, eval);
    1.23 +     msurf_vertex_func(ms, glVertex3f);
    1.24 +     
    1.25 +     /* drawing */
    1.26 +     glBegin(GL_TRIANGLES);
    1.27 +     msurf_polygonize(ms);
    1.28 +     glEnd();
    1.29 +     
    1.30 +     /* evaluator */
    1.31 +     float eval(float x, float y, float z)
    1.32 +     {
    1.33 +         return x * x + y * y + z * z;
    1.34 +     }
    1.35 +
    1.36 +See the examples subdirectory for more examples.
    1.37 +
    1.38 +3. License
    1.39 +----------
    1.40 +Copyright: John Tsiombikas <nuclear@member.fsf.org>
    1.41 +
    1.42 +Metasurf is free software, you may use, modify, and redistribute it freely under
    1.43 +the terms of the GNU Lesser General Public License (LGPL) v3 (or at your option,
    1.44 +any later version published by the Free Software Foundation). See COPYING and
    1.45 +COPYING.LESSER for more details.
    1.46 +
    1.47 +
    1.48 +4. Contributions
    1.49 +----------------
    1.50 +If you'd like to fix the marching tetrahedra implementation or have any other
    1.51 +ideas for improving this library drop me an email at: nuclear@member.fsf.org.
    1.52 +Also feel free to submit patches for bugfixes.
     2.1 --- a/examples/metaballs/Makefile	Tue Oct 25 07:34:31 2011 +0300
     2.2 +++ b/examples/metaballs/Makefile	Tue Oct 25 07:57:07 2011 +0300
     2.3 @@ -1,11 +1,11 @@
     2.4  src = $(wildcard src/*.c)
     2.5  obj = $(src:.c=.o)
     2.6  dep = $(obj:.o=.d)
     2.7 -bin = metasurf
     2.8 +bin = metaballs
     2.9  
    2.10  CC = gcc
    2.11 -CFLAGS = -pedantic -Wall -g -O3
    2.12 -LDFLAGS = $(libgl)
    2.13 +CFLAGS = -pedantic -Wall -g -I../../src
    2.14 +LDFLAGS = -L../.. -lmetasurf $(libgl)
    2.15  
    2.16  ifeq ($(shell uname -s), Darwin)
    2.17  	libgl = -framework OpenGL -framework GLUT -lGLEW
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/examples/metaballs/src/metaballs.c	Tue Oct 25 07:57:07 2011 +0300
     3.3 @@ -0,0 +1,307 @@
     3.4 +#include <stdio.h>
     3.5 +#include <stdlib.h>
     3.6 +#include <math.h>
     3.7 +#include <assert.h>
     3.8 +
     3.9 +#include <GL/glew.h>
    3.10 +#ifndef __APPLE__
    3.11 +#include <GL/glut.h>
    3.12 +#else
    3.13 +#include <GLUT/glut.h>
    3.14 +#endif
    3.15 +
    3.16 +#include "cam.h"
    3.17 +#include "sdr.h"
    3.18 +#include "metasurf.h"
    3.19 +
    3.20 +#define RES		38
    3.21 +
    3.22 +struct metaball {
    3.23 +	float energy;
    3.24 +	float x, y, z;
    3.25 +} mball[] = {
    3.26 +	{1.0, 0, 0, 0},
    3.27 +	{0.25, 0.45, 0, 0.25},
    3.28 +	{0.15, -0.3, 0.2, 0.1}
    3.29 +};
    3.30 +
    3.31 +int num_mballs = sizeof mball / sizeof *mball;
    3.32 +
    3.33 +float eval(float x, float y, float z);
    3.34 +float eval_cached(float x, float y, float z);
    3.35 +void vertex(float x, float y, float z);
    3.36 +void render(void);
    3.37 +void disp(void);
    3.38 +void reshape(int x, int y);
    3.39 +void keyb(unsigned char key, int x, int y);
    3.40 +void mouse(int bn, int state, int x, int y);
    3.41 +void motion(int x, int y);
    3.42 +void sball_button(int bn, int state);
    3.43 +void sball_motion(int x, int y, int z);
    3.44 +int parse_args(int argc, char **argv);
    3.45 +
    3.46 +int stereo;
    3.47 +struct metasurface *msurf;
    3.48 +float threshold = 12;
    3.49 +unsigned int sdr;
    3.50 +int bidx = 1;
    3.51 +
    3.52 +int main(int argc, char **argv)
    3.53 +{
    3.54 +	float amb[] = {0, 0, 0, 0};
    3.55 +	float lpos[] = {-0.2, 0.2, 1, 0};
    3.56 +
    3.57 +	glutInitWindowSize(1280, 720);
    3.58 +	glutInit(&argc, argv);
    3.59 +
    3.60 +	if(parse_args(argc, argv) == -1) {
    3.61 +		return 1;
    3.62 +	}
    3.63 +	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | (stereo ? GLUT_STEREO : 0));
    3.64 +	glutCreateWindow("metasurf");
    3.65 +
    3.66 +	glutDisplayFunc(disp);
    3.67 +	glutReshapeFunc(reshape);
    3.68 +	glutKeyboardFunc(keyb);
    3.69 +	glutMouseFunc(mouse);
    3.70 +	glutMotionFunc(motion);
    3.71 +	glutSpaceballButtonFunc(sball_button);
    3.72 +	glutSpaceballMotionFunc(sball_motion);
    3.73 +
    3.74 +	glewInit();
    3.75 +
    3.76 +	glEnable(GL_CULL_FACE);
    3.77 +	glEnable(GL_DEPTH_TEST);
    3.78 +
    3.79 +	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
    3.80 +
    3.81 +	glEnable(GL_LIGHTING);
    3.82 +	glEnable(GL_LIGHT0);
    3.83 +	glLightfv(GL_LIGHT0, GL_POSITION, lpos);
    3.84 +
    3.85 +	glEnable(GL_NORMALIZE);
    3.86 +
    3.87 +	cam_focus_dist(2.0);
    3.88 +	cam_clip(0.1, 200.0);
    3.89 +	cam_rotate(0, 0);
    3.90 +	cam_dolly(2);
    3.91 +
    3.92 +	msurf = msurf_create();
    3.93 +	msurf_eval_func(msurf, eval);
    3.94 +	msurf_vertex_func(msurf, vertex);
    3.95 +	msurf_threshold(msurf, threshold);
    3.96 +	msurf_resolution(msurf, RES, RES, RES);
    3.97 +	msurf_bounds(msurf, -1, -1, -1, 1, 1, 1);
    3.98 +
    3.99 +	glClearColor(0.8, 0.8, 0.8, 1.0);
   3.100 +
   3.101 +	if(!(sdr = create_program_load("sdr/vert.glsl", "sdr/frag.glsl"))) {
   3.102 +		return 1;
   3.103 +	}
   3.104 +
   3.105 +	glutMainLoop();
   3.106 +	return 0;
   3.107 +}
   3.108 +
   3.109 +float eval(float x, float y, float z)
   3.110 +{
   3.111 +	int i;
   3.112 +	float val = 0.0f;
   3.113 +
   3.114 +	for(i=0; i<num_mballs; i++) {
   3.115 +		float dx = mball[i].x - x;
   3.116 +		float dy = mball[i].y - y;
   3.117 +		float dz = mball[i].z - z;
   3.118 +		float dist_sq = dx * dx + dy * dy + dz * dz;
   3.119 +
   3.120 +		if(dist_sq < 1e-6) {
   3.121 +			val += 100.0;
   3.122 +		} else {
   3.123 +			val += mball[i].energy / dist_sq;
   3.124 +		}
   3.125 +	}
   3.126 +	return val;
   3.127 +}
   3.128 +
   3.129 +void vertex(float x, float y, float z)
   3.130 +{
   3.131 +	const float dt = 0.001;
   3.132 +	float dfdx = eval(x - dt, y, z) - eval(x + dt, y, z);
   3.133 +	float dfdy = eval(x, y - dt, z) - eval(x, y + dt, z);
   3.134 +	float dfdz = eval(x, y, z - dt) - eval(x, y, z + dt);
   3.135 +
   3.136 +	glNormal3f(dfdx, dfdy, dfdz);
   3.137 +	glVertex3f(x, y, z);
   3.138 +}
   3.139 +
   3.140 +void render(void)
   3.141 +{
   3.142 +	float kd[] = {0.7, 0.28, 0.2, 1.0};
   3.143 +	float ks[] = {0.9, 0.9, 0.9, 1.0};
   3.144 +
   3.145 +	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, kd);
   3.146 +	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, ks);
   3.147 +	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 60.0);
   3.148 +
   3.149 +	bind_program(sdr);
   3.150 +
   3.151 +	glBegin(GL_TRIANGLES);
   3.152 +	msurf_polygonize(msurf);
   3.153 +	glEnd();
   3.154 +
   3.155 +	assert(glGetError() == GL_NO_ERROR);
   3.156 +}
   3.157 +
   3.158 +void disp(void)
   3.159 +{
   3.160 +	if(stereo) {
   3.161 +		glDrawBuffer(GL_BACK_LEFT);
   3.162 +	}
   3.163 +
   3.164 +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   3.165 +
   3.166 +	glMatrixMode(GL_PROJECTION);
   3.167 +	glLoadIdentity();
   3.168 +	cam_stereo_proj_matrix(stereo ? CAM_LEFT : CAM_CENTER);
   3.169 +
   3.170 +	glMatrixMode(GL_MODELVIEW);
   3.171 +	glLoadIdentity();
   3.172 +	cam_stereo_view_matrix(stereo ? CAM_LEFT : CAM_CENTER);
   3.173 +
   3.174 +	render();
   3.175 +
   3.176 +	if(stereo) {
   3.177 +		glDrawBuffer(GL_BACK_RIGHT);
   3.178 +		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   3.179 +
   3.180 +		glMatrixMode(GL_PROJECTION);
   3.181 +		glLoadIdentity();
   3.182 +		cam_stereo_proj_matrix(CAM_RIGHT);
   3.183 +
   3.184 +		glMatrixMode(GL_MODELVIEW);
   3.185 +		glLoadIdentity();
   3.186 +		cam_stereo_view_matrix(CAM_RIGHT);
   3.187 +
   3.188 +		render();
   3.189 +	}
   3.190 +	glutSwapBuffers();
   3.191 +}
   3.192 +
   3.193 +void reshape(int x, int y)
   3.194 +{
   3.195 +	glViewport(0, 0, x, y);
   3.196 +	cam_aspect((float)x / (float)y);
   3.197 +}
   3.198 +
   3.199 +void keyb(unsigned char key, int x, int y)
   3.200 +{
   3.201 +	static int wire;
   3.202 +
   3.203 +	switch(key) {
   3.204 +	case 27:
   3.205 +		exit(0);
   3.206 +
   3.207 +	case 's':
   3.208 +		stereo = !stereo;
   3.209 +		glutPostRedisplay();
   3.210 +		break;
   3.211 +
   3.212 +	case 'w':
   3.213 +		wire = !wire;
   3.214 +		glPolygonMode(GL_FRONT_AND_BACK, wire ? GL_LINE : GL_FILL);
   3.215 +		glutPostRedisplay();
   3.216 +		break;
   3.217 +
   3.218 +	case '=':
   3.219 +		threshold += 0.05;
   3.220 +		msurf_threshold(msurf, threshold);
   3.221 +		printf("threshold: %f\n", threshold);
   3.222 +		glutPostRedisplay();
   3.223 +		break;
   3.224 +
   3.225 +	case '-':
   3.226 +		threshold -= 0.05;
   3.227 +		msurf_threshold(msurf, threshold);
   3.228 +		printf("threshold: %f\n", threshold);
   3.229 +		glutPostRedisplay();
   3.230 +		break;
   3.231 +
   3.232 +	case ' ':
   3.233 +		bidx = (bidx + 1) % num_mballs;
   3.234 +		break;
   3.235 +
   3.236 +	default:
   3.237 +		break;
   3.238 +	}
   3.239 +}
   3.240 +
   3.241 +int bnstate[32];
   3.242 +int prev_x, prev_y;
   3.243 +
   3.244 +void mouse(int bn, int state, int x, int y)
   3.245 +{
   3.246 +	bnstate[bn] = state == GLUT_DOWN;
   3.247 +	prev_x = x;
   3.248 +	prev_y = y;
   3.249 +}
   3.250 +
   3.251 +void motion(int x, int y)
   3.252 +{
   3.253 +	int dx, dy;
   3.254 +
   3.255 +	dx = x - prev_x;
   3.256 +	dy = y - prev_y;
   3.257 +	prev_x = x;
   3.258 +	prev_y = y;
   3.259 +
   3.260 +	if(bnstate[GLUT_LEFT_BUTTON]) {
   3.261 +		cam_inp_rotate(dx, dy);
   3.262 +		glutPostRedisplay();
   3.263 +	}
   3.264 +	if(bnstate[GLUT_RIGHT_BUTTON]) {
   3.265 +		cam_inp_zoom(dy);
   3.266 +		glutPostRedisplay();
   3.267 +	}
   3.268 +}
   3.269 +
   3.270 +void sball_button(int bn, int state)
   3.271 +{
   3.272 +	if(state) return;
   3.273 +
   3.274 +	if(bn < num_mballs) {
   3.275 +		bidx = bn;
   3.276 +	} else {
   3.277 +		bidx = (bidx + 1) % num_mballs;
   3.278 +	}
   3.279 +}
   3.280 +
   3.281 +void sball_motion(int x, int y, int z)
   3.282 +{
   3.283 +	mball[bidx].x += (float)x / 32768.0;
   3.284 +	mball[bidx].y += (float)y / 32768.0;
   3.285 +	mball[bidx].z -= (float)z / 32768.0;
   3.286 +	glutPostRedisplay();
   3.287 +}
   3.288 +
   3.289 +int parse_args(int argc, char **argv)
   3.290 +{
   3.291 +	int i;
   3.292 +
   3.293 +	for(i=1; i<argc; i++) {
   3.294 +		if(argv[i][0] == '-' && argv[i][2] == 0) {
   3.295 +			switch(argv[i][1]) {
   3.296 +			case 's':
   3.297 +				stereo = !stereo;
   3.298 +				break;
   3.299 +
   3.300 +			default:
   3.301 +				fprintf(stderr, "unrecognized option: %s\n", argv[i]);
   3.302 +				return -1;
   3.303 +			}
   3.304 +		} else {
   3.305 +			fprintf(stderr, "unexpected argument: %s\n", argv[i]);
   3.306 +			return -1;
   3.307 +		}
   3.308 +	}
   3.309 +	return 0;
   3.310 +}
     4.1 --- a/examples/metaballs/src/test.c	Tue Oct 25 07:34:31 2011 +0300
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,307 +0,0 @@
     4.4 -#include <stdio.h>
     4.5 -#include <stdlib.h>
     4.6 -#include <math.h>
     4.7 -#include <assert.h>
     4.8 -
     4.9 -#include <GL/glew.h>
    4.10 -#ifndef __APPLE__
    4.11 -#include <GL/glut.h>
    4.12 -#else
    4.13 -#include <GLUT/glut.h>
    4.14 -#endif
    4.15 -
    4.16 -#include "cam.h"
    4.17 -#include "sdr.h"
    4.18 -#include "metasurf.h"
    4.19 -
    4.20 -#define RES		38
    4.21 -
    4.22 -struct metaball {
    4.23 -	float energy;
    4.24 -	float x, y, z;
    4.25 -} mball[] = {
    4.26 -	{1.0, 0, 0, 0},
    4.27 -	{0.25, 0.45, 0, 0.25},
    4.28 -	{0.15, -0.3, 0.2, 0.1}
    4.29 -};
    4.30 -
    4.31 -int num_mballs = sizeof mball / sizeof *mball;
    4.32 -
    4.33 -float eval(float x, float y, float z);
    4.34 -float eval_cached(float x, float y, float z);
    4.35 -void vertex(float x, float y, float z);
    4.36 -void render(void);
    4.37 -void disp(void);
    4.38 -void reshape(int x, int y);
    4.39 -void keyb(unsigned char key, int x, int y);
    4.40 -void mouse(int bn, int state, int x, int y);
    4.41 -void motion(int x, int y);
    4.42 -void sball_button(int bn, int state);
    4.43 -void sball_motion(int x, int y, int z);
    4.44 -int parse_args(int argc, char **argv);
    4.45 -
    4.46 -int stereo;
    4.47 -struct metasurface *msurf;
    4.48 -float threshold = 12;
    4.49 -unsigned int sdr;
    4.50 -int bidx = 1;
    4.51 -
    4.52 -int main(int argc, char **argv)
    4.53 -{
    4.54 -	float amb[] = {0, 0, 0, 0};
    4.55 -	float lpos[] = {-0.2, 0.2, 1, 0};
    4.56 -
    4.57 -	glutInitWindowSize(1280, 720);
    4.58 -	glutInit(&argc, argv);
    4.59 -
    4.60 -	if(parse_args(argc, argv) == -1) {
    4.61 -		return 1;
    4.62 -	}
    4.63 -	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | (stereo ? GLUT_STEREO : 0));
    4.64 -	glutCreateWindow("metasurf");
    4.65 -
    4.66 -	glutDisplayFunc(disp);
    4.67 -	glutReshapeFunc(reshape);
    4.68 -	glutKeyboardFunc(keyb);
    4.69 -	glutMouseFunc(mouse);
    4.70 -	glutMotionFunc(motion);
    4.71 -	glutSpaceballButtonFunc(sball_button);
    4.72 -	glutSpaceballMotionFunc(sball_motion);
    4.73 -
    4.74 -	glewInit();
    4.75 -
    4.76 -	glEnable(GL_CULL_FACE);
    4.77 -	glEnable(GL_DEPTH_TEST);
    4.78 -
    4.79 -	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
    4.80 -
    4.81 -	glEnable(GL_LIGHTING);
    4.82 -	glEnable(GL_LIGHT0);
    4.83 -	glLightfv(GL_LIGHT0, GL_POSITION, lpos);
    4.84 -
    4.85 -	glEnable(GL_NORMALIZE);
    4.86 -
    4.87 -	cam_focus_dist(2.0);
    4.88 -	cam_clip(0.1, 200.0);
    4.89 -	cam_rotate(0, 0);
    4.90 -	cam_dolly(2);
    4.91 -
    4.92 -	msurf = msurf_create();
    4.93 -	msurf_eval_func(msurf, eval);
    4.94 -	msurf_vertex_func(msurf, vertex);
    4.95 -	msurf_threshold(msurf, threshold);
    4.96 -	msurf_resolution(msurf, RES, RES, RES);
    4.97 -	msurf_bounds(msurf, -1, -1, -1, 1, 1, 1);
    4.98 -
    4.99 -	glClearColor(0.8, 0.8, 0.8, 1.0);
   4.100 -
   4.101 -	if(!(sdr = create_program_load("sdr/vert.glsl", "sdr/frag.glsl"))) {
   4.102 -		return 1;
   4.103 -	}
   4.104 -
   4.105 -	glutMainLoop();
   4.106 -	return 0;
   4.107 -}
   4.108 -
   4.109 -float eval(float x, float y, float z)
   4.110 -{
   4.111 -	int i;
   4.112 -	float val = 0.0f;
   4.113 -
   4.114 -	for(i=0; i<num_mballs; i++) {
   4.115 -		float dx = mball[i].x - x;
   4.116 -		float dy = mball[i].y - y;
   4.117 -		float dz = mball[i].z - z;
   4.118 -		float dist_sq = dx * dx + dy * dy + dz * dz;
   4.119 -
   4.120 -		if(dist_sq < 1e-6) {
   4.121 -			val += 100.0;
   4.122 -		} else {
   4.123 -			val += mball[i].energy / dist_sq;
   4.124 -		}
   4.125 -	}
   4.126 -	return val;
   4.127 -}
   4.128 -
   4.129 -void vertex(float x, float y, float z)
   4.130 -{
   4.131 -	const float dt = 0.001;
   4.132 -	float dfdx = eval(x - dt, y, z) - eval(x + dt, y, z);
   4.133 -	float dfdy = eval(x, y - dt, z) - eval(x, y + dt, z);
   4.134 -	float dfdz = eval(x, y, z - dt) - eval(x, y, z + dt);
   4.135 -
   4.136 -	glNormal3f(dfdx, dfdy, dfdz);
   4.137 -	glVertex3f(x, y, z);
   4.138 -}
   4.139 -
   4.140 -void render(void)
   4.141 -{
   4.142 -	float kd[] = {0.7, 0.28, 0.2, 1.0};
   4.143 -	float ks[] = {0.9, 0.9, 0.9, 1.0};
   4.144 -
   4.145 -	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, kd);
   4.146 -	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, ks);
   4.147 -	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 60.0);
   4.148 -
   4.149 -	bind_program(sdr);
   4.150 -
   4.151 -	glBegin(GL_TRIANGLES);
   4.152 -	msurf_polygonize(msurf);
   4.153 -	glEnd();
   4.154 -
   4.155 -	assert(glGetError() == GL_NO_ERROR);
   4.156 -}
   4.157 -
   4.158 -void disp(void)
   4.159 -{
   4.160 -	if(stereo) {
   4.161 -		glDrawBuffer(GL_BACK_LEFT);
   4.162 -	}
   4.163 -
   4.164 -	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   4.165 -
   4.166 -	glMatrixMode(GL_PROJECTION);
   4.167 -	glLoadIdentity();
   4.168 -	cam_stereo_proj_matrix(stereo ? CAM_LEFT : CAM_CENTER);
   4.169 -
   4.170 -	glMatrixMode(GL_MODELVIEW);
   4.171 -	glLoadIdentity();
   4.172 -	cam_stereo_view_matrix(stereo ? CAM_LEFT : CAM_CENTER);
   4.173 -
   4.174 -	render();
   4.175 -
   4.176 -	if(stereo) {
   4.177 -		glDrawBuffer(GL_BACK_RIGHT);
   4.178 -		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   4.179 -
   4.180 -		glMatrixMode(GL_PROJECTION);
   4.181 -		glLoadIdentity();
   4.182 -		cam_stereo_proj_matrix(CAM_RIGHT);
   4.183 -
   4.184 -		glMatrixMode(GL_MODELVIEW);
   4.185 -		glLoadIdentity();
   4.186 -		cam_stereo_view_matrix(CAM_RIGHT);
   4.187 -
   4.188 -		render();
   4.189 -	}
   4.190 -	glutSwapBuffers();
   4.191 -}
   4.192 -
   4.193 -void reshape(int x, int y)
   4.194 -{
   4.195 -	glViewport(0, 0, x, y);
   4.196 -	cam_aspect((float)x / (float)y);
   4.197 -}
   4.198 -
   4.199 -void keyb(unsigned char key, int x, int y)
   4.200 -{
   4.201 -	static int wire;
   4.202 -
   4.203 -	switch(key) {
   4.204 -	case 27:
   4.205 -		exit(0);
   4.206 -
   4.207 -	case 's':
   4.208 -		stereo = !stereo;
   4.209 -		glutPostRedisplay();
   4.210 -		break;
   4.211 -
   4.212 -	case 'w':
   4.213 -		wire = !wire;
   4.214 -		glPolygonMode(GL_FRONT_AND_BACK, wire ? GL_LINE : GL_FILL);
   4.215 -		glutPostRedisplay();
   4.216 -		break;
   4.217 -
   4.218 -	case '=':
   4.219 -		threshold += 0.05;
   4.220 -		msurf_threshold(msurf, threshold);
   4.221 -		printf("threshold: %f\n", threshold);
   4.222 -		glutPostRedisplay();
   4.223 -		break;
   4.224 -
   4.225 -	case '-':
   4.226 -		threshold -= 0.05;
   4.227 -		msurf_threshold(msurf, threshold);
   4.228 -		printf("threshold: %f\n", threshold);
   4.229 -		glutPostRedisplay();
   4.230 -		break;
   4.231 -
   4.232 -	case ' ':
   4.233 -		bidx = (bidx + 1) % num_mballs;
   4.234 -		break;
   4.235 -
   4.236 -	default:
   4.237 -		break;
   4.238 -	}
   4.239 -}
   4.240 -
   4.241 -int bnstate[32];
   4.242 -int prev_x, prev_y;
   4.243 -
   4.244 -void mouse(int bn, int state, int x, int y)
   4.245 -{
   4.246 -	bnstate[bn] = state == GLUT_DOWN;
   4.247 -	prev_x = x;
   4.248 -	prev_y = y;
   4.249 -}
   4.250 -
   4.251 -void motion(int x, int y)
   4.252 -{
   4.253 -	int dx, dy;
   4.254 -
   4.255 -	dx = x - prev_x;
   4.256 -	dy = y - prev_y;
   4.257 -	prev_x = x;
   4.258 -	prev_y = y;
   4.259 -
   4.260 -	if(bnstate[GLUT_LEFT_BUTTON]) {
   4.261 -		cam_inp_rotate(dx, dy);
   4.262 -		glutPostRedisplay();
   4.263 -	}
   4.264 -	if(bnstate[GLUT_RIGHT_BUTTON]) {
   4.265 -		cam_inp_zoom(dy);
   4.266 -		glutPostRedisplay();
   4.267 -	}
   4.268 -}
   4.269 -
   4.270 -void sball_button(int bn, int state)
   4.271 -{
   4.272 -	if(state) return;
   4.273 -
   4.274 -	if(bn < num_mballs) {
   4.275 -		bidx = bn;
   4.276 -	} else {
   4.277 -		bidx = (bidx + 1) % num_mballs;
   4.278 -	}
   4.279 -}
   4.280 -
   4.281 -void sball_motion(int x, int y, int z)
   4.282 -{
   4.283 -	mball[bidx].x += (float)x / 32768.0;
   4.284 -	mball[bidx].y += (float)y / 32768.0;
   4.285 -	mball[bidx].z -= (float)z / 32768.0;
   4.286 -	glutPostRedisplay();
   4.287 -}
   4.288 -
   4.289 -int parse_args(int argc, char **argv)
   4.290 -{
   4.291 -	int i;
   4.292 -
   4.293 -	for(i=1; i<argc; i++) {
   4.294 -		if(argv[i][0] == '-' && argv[i][2] == 0) {
   4.295 -			switch(argv[i][1]) {
   4.296 -			case 's':
   4.297 -				stereo = !stereo;
   4.298 -				break;
   4.299 -
   4.300 -			default:
   4.301 -				fprintf(stderr, "unrecognized option: %s\n", argv[i]);
   4.302 -				return -1;
   4.303 -			}
   4.304 -		} else {
   4.305 -			fprintf(stderr, "unexpected argument: %s\n", argv[i]);
   4.306 -			return -1;
   4.307 -		}
   4.308 -	}
   4.309 -	return 0;
   4.310 -}