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