Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!usc!apple!rutgers!njin!princeton!phoenix!dmlaur From: dmlaur@phoenix.Princeton.EDU (David M. Laur) Newsgroups: comp.sys.sgi Subject: Re: spaceball Message-ID: <1478@idunno.Princeton.EDU> Date: 27 Jul 90 16:00:17 GMT References: <23385@dartvax.Dartmouth.EDU> Sender: news@idunno.Princeton.EDU Organization: Princeton University, Princeton, New Jersey Lines: 405 In article <23385@dartvax.Dartmouth.EDU> emma@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@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@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 #include #include /* ---- 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; } } /* -------------------------------------------------------------------- */