spaceball

David M. Laur dmlaur at phoenix.Princeton.EDU
Sat Jul 28 02:00:17 AEST 1990


In article <23385 at dartvax.Dartmouth.EDU> emma at northstar27.dartmouth.edu (Emma Lan) writes:
>
>  We had a 4D/80 IRIS two years ago, we did a lot things which need dials and 
>buttons to rotate and translate objects on it.  So most of our programs have
>been written accordingly.  Now we got another 4D/210 IRIS, and we are thinking
>of transfering some of our programs to this new machine, but this new machine
>has an innovative device called "spaceball", instead of the "dial and button
>box".
>  Could someone please send me a sample program using this new "spaceball" 
>device or point it out how to convert "the dial and button box" to "spaceball
>device".
>  Please reply me to emma at northstar.dartmouth.edu.
>  Thanks a lot in advance!

try this ...

-------------------- cut here ------------------------------
/*
 *  - test spaceball to rotate and position an object
 *  - use triangle-mesh drawing routines
 *  - use RGB color scheme
 *
 * compile using:
 *
 *   cc -o sbtest sbtest.c -O -lspaceball -lgl_s -lc_s -lm -s
 *
 *
 *  David Laur, Princeton ICGL, Oct 89
 *  dmlaur at manray.princeton.edu
 *  609-258-4609
 *
 *
 * note: the Gouraud shading option on the menu isn't meaningful on some
 *       SGI systems ... the drawing scheme used 'forces' smooth shading
 *       on 4D/GT machines.
 */


#include <gl/gl.h>
#include <gl/device.h>
#include <math.h>

/* ---- function declarations / prototypes ---- */
void setup(void);
void do_events(void);
void figure(void);
void draw_cube(void);
void draw_axes(void);
void do_menu(void);
void newView(void);
void newSb (short *sbvals, Matrix sbmat);

long Zmax, menu, Wid, MouseIn=0;
char sbstatus[128];
Matrix Rmat;			/* global rotation matrix */
float sbscale = 0.0002, trns[3];
Boolean flat, dominant=FALSE;

char *sbsingle[] = {"Tx","Ty","Tz","Rx","Ry","Rz"};

Matrix Id_mat = {
		{ 1.0, 0.0, 0.0, 0.0 },
		{ 0.0, 1.0, 0.0, 0.0 },
		{ 0.0, 0.0, 1.0, 0.0 },
		{ 0.0, 0.0, 0.0, 1.0 } };


int Cv[][3] =	{	0, 0, 0,
			1, 0, 0,
			1, 1, 0,
			0, 1, 0,
			0, 0, 1,
			1, 0, 1,
			1, 1, 1,
			0, 1, 1,
		};

int Crgb[][3] =	{	30, 30, 30,
			100, 30, 30,
			30, 100, 30,
			30, 30, 100,
			100, 100, 100,
			255, 100, 100,
			100, 255, 100,
			100, 100, 255,
		};

/* -------------------------------------------------------------------- */

main (argc,argv)
	int argc;
	char **argv;
{
	if (!sbexists()) {
		puts("no spaceball on this machine!");
		exit(-1);
	}

	setup();		/* do initial window stuff */

	sbspaceball();		/* initialize the spaceball */
	sbrezero();		/* re-zero */
	sbdataperiod(0, -1);	/* only way I found to reset this */
	sbdataperiod(1000, 0);	/* seems to give reasonable performance on our GT */
	sbprompt();		/* make sure first SB events aren't delayed */
	
	do_events();		/* handle events 'forever' */

}	/* end of main routine */

/* -------------------------------------------------------------------- */

void
setup ()	/***** setup the window *****/
{
	Wid = winopen("sample");

	Zmax = getgdesc(GD_ZMAX); /* save max available z-depth */

	zbuffer(TRUE);
	doublebuffer();
	RGBmode();
	gconfig();

	qdevice(RIGHTMOUSE);	/* trap right mouse button events */
	qdevice(REDRAW);	/* trap window manager `redraw' messages */
	qdevice(INPUTCHANGE);	/* trap changes in input focus */

	qdevice(SBBUT1);	/* SpaceBall Button 1 */
	qdevice(SBBUT2);
	qdevice(SBBUT3);
	qdevice(SBBUT4);
	qdevice(SBTX);		/* SpaceBall Translate in X */
	qdevice(SBTY);
	qdevice(SBTZ);
	qdevice(SBRX);		/* SpaceBall Rotate about X */
	qdevice(SBRY);
	qdevice(SBRZ);
	qdevice(SBPERIOD);	/* SpaceBall time delta */

	qenter(REDRAW,Wid);	/* make sure we do initial redraw */

	menu = defpup("Some Choices%t|Reset Position%x10");
	addtopup(menu,"Use Flat Shading%x20|Use Gouraud Shading%x20");
	addtopup(menu,"Exit%x999");

	shademodel( (flat=TRUE) ? FLAT : GOURAUD );
	setpup(menu, ((flat) ? 2 : 3), PUP_GREY);	/* grey-out inappropriate menu entry */

	strcpy(sbstatus, "Spaceball may require Inputchange event");
}

/* -------------------------------------------------------------------- */

void
do_events ()	/***** event handler loop *****/
{
	long device;
	short value;
	long wx, wy;
	int mx, my;
	short sbvals[7];

	for (mx=0; mx<7; mx++) sbvals[mx] = 0;
	bcopy(Id_mat, Rmat, sizeof(float)*4*4);	/* initialize to no rotations */
	trns[0] = trns[1] = 0.0;  trns[2] = -500.0;

	while (1)	/* until killed from menu ... */
	{
	device = qread(&value);		/* read next event */

	switch (device)
	{
		case (RIGHTMOUSE):
			if (1 != value) break;
			do_menu();
			newView();
			break;

		case (SBPERIOD):
		case (SBTX):
		case (SBTY):
		case (SBTZ):
		case (SBRX):
		case (SBRY):
		case (SBRZ):
			sbvals[device-SBTX] = value;
			if (device == SBRZ) {	/* now have complete sb event */
				sbprompt();	/* ensure next sb is sent without delay */
				newSb( sbvals, Rmat);
				newView();
			}
			break;

		case SBBUT1:
			if (value != 1) break;
			bcopy(Id_mat, Rmat, sizeof(float)*4*4);
			trns[0] = trns[1] = 0.0;  trns[2] = -500.0;
			newView();
			break;

		case SBBUT2:
			if (value == 1) dominant = !dominant;
			break;

		case SBBUT3:
		case SBBUT4:
			if (value != 1) break;
			sbscale *= ((device == SBBUT3)? 0.5 : 2.0);
			break;

		case (REDRAW):
			reshapeviewport();		/* re-map new window position */
			getsize(&wx, &wy);		/* get window size */
			perspective(650, wx / (float)wy, 1.0, 1500.0);
			newView();
			break;

		case (INPUTCHANGE):
			if (value != Wid) break;
			if (++MouseIn == 2) {
				strcpy(sbstatus,"ok");
				newView();
			}
			break;

		} /* end switch */

	} /* end while */
	/*NOTREACHED*/
}

/* -------------------------------------------------------------------- */

void
newSb (short *sbvals, Matrix sbmat)
{
	Matrix sbtmp;
	static int oldn=0, maxn, run=0;
	register int n, v,w;
	float trv[6];
	
	sprintf(sbstatus,"%3s   T(%-5hd%-5hd%-5hd)    R(%-5hd%-5hd%-5hd)", 
		((dominant)?sbsingle[maxn]:"all"),
	sbvals[0],sbvals[1],sbvals[2],sbvals[3],sbvals[4],sbvals[5]);

	if (dominant) {
		for (n=0; n<6; n++) if (5 < abs(sbvals[n])) break;
		if (n == 6) {	/* all zeros, end of sb events */
		run = 0;
		strcpy(sbstatus,"Stop  T(0    0    0    )    R(0    0    0    )");
		return;
	}
	if (run < 2) {	/* find dominant mode */
		for (maxn=n=v=0; n<6; n++) if (v < (w = abs(sbvals[n]))) { maxn = n; v = w; }
		if (oldn == maxn) run++;
		else { run=0; oldn = maxn; }
		if (run < 2) return;
		else for (n=0; n<6; n++) trv[n] = 0.0;
	}
	trv[maxn] = (float) (sbvals[maxn]);
	}
	else for (n=run=0; n<6; n++) trv[n] = (float) (sbvals[n]);

	if ( ((!dominant) || (maxn < 3)) && (trv[0] || trv[1] || trv[2])) {
		trv[2] *= -1.0;
		for (n=0; n<3; n++) trns[n] += (25.0 * sbscale * trv[n]);
	}

	if ( ((!dominant) || (maxn > 2)) && (trv[3] || trv[4] || trv[5]) && (!getbutton(SBPICK))) {
		trv[3] *= -1.0;
		trv[4] *= -1.0;

		rotarbaxis(sbscale, trv[3], trv[4], trv[5], sbtmp);	/* convert SB to matrix */

		pushmatrix();
		loadmatrix(sbtmp);
		multmatrix(sbmat);	/* use GL to do post-multiply */
		getmatrix(sbmat);	/* ... there's probably a better way */
		popmatrix();
	}
}

/* -------------------------------------------------------------------- */

void
newView ( void )	/***** draw scene *****/
{
	czclear(0, Zmax);
	pushmatrix();			/* store perspective */

	translate( trns[0], trns[1], trns[2] );
	multmatrix(Rmat);
	draw_axes();
	figure();

	ortho2(0.0, 500.0, 0.0, 500.0);
	RGBcolor(255,255,0);
	cmov2i(10,5);
	charstr(sbstatus);
	cmov2i(10,20);
	charstr("1: Reset   2: All/One Axis   3: Slower   4: Faster");

	popmatrix();
	swapbuffers();
}

/* -------------------------------------------------------------------- */

void
figure ()	/***** geometry drawing subroutine *****/
{
	pushmatrix();	/* cube centered at origin, scaled */
	scale(100.0, 100.0, 100.0);
	draw_cube();
	popmatrix();

	pushmatrix();	/* cube translated, scaled, intersects first */
	translate(100.0, 100.0, 100.0);
	scale(50.0, 50.0, 50.0);
	rotate(900, 'y');
	rotate(900, 'z');
	translate(-.5, -.5, -.5);
	draw_cube();
	popmatrix();

	pushmatrix();	/* another cube, distorted */
	translate(-50.0, -150.0, -70.0);
	scale(30.0, 20.0, 50.0);
	rotate(300, 'x');
	draw_cube();
	popmatrix();
}

/* -------------------------------------------------------------------- */

void
draw_cube ()	/* draw a unit cube: 8 corners, 6 faces (right-handed) */
{
	bgntmesh();
	c3i(Crgb[0]);	v3i(Cv[0]);
	c3i(Crgb[3]);	v3i(Cv[3]);
	c3i(Crgb[1]);	v3i(Cv[1]);
	c3i(Crgb[2]);	v3i(Cv[2]);
	c3i(Crgb[5]);	v3i(Cv[5]);
	c3i(Crgb[6]);	v3i(Cv[6]);
	c3i(Crgb[4]);	v3i(Cv[4]);
	c3i(Crgb[7]);	v3i(Cv[7]);
	endtmesh();

	bgntmesh();
	c3i(Crgb[1]);	v3i(Cv[1]);
	c3i(Crgb[5]);	v3i(Cv[5]);
	c3i(Crgb[0]);	v3i(Cv[0]);
	c3i(Crgb[4]);	v3i(Cv[4]);
	c3i(Crgb[3]);	v3i(Cv[3]);
	c3i(Crgb[7]);	v3i(Cv[7]);
	c3i(Crgb[2]);	v3i(Cv[2]);
	c3i(Crgb[6]);	v3i(Cv[6]);
	endtmesh();
}

/* -------------------------------------------------------------------- */

void
draw_axes ()
{
	RGBcolor(255,0,0); movei(0,0,0); drawi(150,0,0); cmovi(150,0,0); charstr("x");
	RGBcolor(0,255,0); movei(0,0,0); drawi(0,150,0); cmovi(0,150,0); charstr("y");
	RGBcolor(0,0,255); movei(0,0,0); drawi(0,0,150); cmovi(0,0,150); charstr("z");
}

/* -------------------------------------------------------------------- */

void
do_menu ()	/***** pop-up menu stuff *****/
{
	int v;

	v = dopup(menu);
	if (v < 1) return;		/* nothing selected */

	switch( v )
	{
	case 10:	/* reset position */
		bcopy(Id_mat, Rmat, sizeof(float)*4*4);
		trns[0] = trns[1] = 0.0;  trns[2] = -500.0;
		newView();
		break;
	case 20:
		flat = !flat;
		shademodel( (flat) ? FLAT : GOURAUD );
		setpup(menu, ((flat) ? 2 : 3), PUP_GREY);	/* grey-out inappropriate menu entry */
		setpup(menu, ((flat) ? 3 : 2), PUP_NONE);	/* allow other menu selection */
		break;
	case 999:
		gexit();
		exit(0);
		break;
	default:
		break;
	}
}

/* -------------------------------------------------------------------- */



More information about the Comp.sys.sgi mailing list