/* navigate1.c /* An example of navigating in a CAVE environment. The world is that /* of bounce.c. The user navigates using the wand joystick - JOYSTICK_Y /* controls the forward/back motion; JOYSTICK_X controls turning. */ #include #include /* The data that will be shared between processes */ struct _balldata { float y; }; void init_gl(void),draw_balls(struct _balldata *); struct _balldata *init_shmem(void); void compute(struct _balldata *); void navigate(void); main(int argc,char **argv) { struct _balldata *ball; CAVEConfigure(&argc,argv,NULL); ball = init_shmem(); CAVEInit(); CAVEInitApplication(init_gl,0); CAVEDisplay(draw_balls,1,ball); while (!CAVEgetbutton(CAVE_ESCKEY)) { navigate(); compute(ball); sginap(1); } CAVEExit(); } #define SPEED 5.0f /* Max navigation speed in feet per second */ /* navigate - perform the navigation calculations. This checks the joystick state and uses that to move and rotate. The Y position of the joystick determines the speed of motion in the direction of the wand. The X position of the joystick determines the speed of rotation about the CAVE's Y axis. Joystick values in the range -.2 to .2 are ignored; this provides a dead zone to eliminate noise. The motion is scaled by dt, the time passed since the last call to navigate(), in order to maintain a smooth speed. */ void navigate(void) { float jx=CAVE_JOYSTICK_X,jy=CAVE_JOYSTICK_Y,dt,t; static float prevtime = 0; t = CAVEGetTime(); dt = t - prevtime; prevtime = t; if (fabs(jy)>0.2) { float wandFront[3]; CAVEGetVector(CAVE_WAND_FRONT,wandFront); CAVENavTranslate(wandFront[0]*jy*SPEED*dt, wandFront[1]*jy*SPEED*dt, wandFront[2]*jy*SPEED*dt); } if (fabs(jx)>0.2) CAVENavRot(-jx*90.0f*dt,'y'); } /* init_shmem - initializes shared memory. The data is allocated from a shared memory arena, and so will be common to all processes forked after this is called. */ struct _balldata *init_shmem(void) { struct _balldata *ball; ball = CAVEMalloc(2*sizeof(struct _balldata)); bzero(ball,2*sizeof(struct _balldata)); return ball; } /* compute - compute new positions for the balls. The height of the balls is a function of the current CAVE time. */ void compute(struct _balldata *ball) { float t = CAVEGetTime(); ball[0].y = fabs(sin(t)) * 6 + 1; ball[1].y = fabs(sin(t*1.2)) * 4 + 1; } static GLuint greenMat, blueMat; static GLUquadricObj *sphereObj; /* init_gl - initialize GL lighting & materials */ void init_gl(void) { float greenMaterial[] = { 0, 1, 0, 1 }; float blueMaterial[] = { 0, 0, 1, 1 }; glEnable(GL_LIGHT0); greenMat = glGenLists(1); glNewList(greenMat, GL_COMPILE); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, greenMaterial); glEndList(); blueMat = glGenLists(1); glNewList(blueMat, GL_COMPILE); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blueMaterial); glEndList(); sphereObj = gluNewQuadric(); } /* draw_balls - draw the two balls, using the shared data for their y coordinates */ void draw_balls(struct _balldata *ball) { glClearColor(0., 0., 0., 0.); glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); glEnable(GL_LIGHTING); /* Apply the navigation transformation */ CAVENavTransform(); glCallList(greenMat); glPushMatrix(); glTranslatef(2.0, ball[0].y, -5.0); gluSphere(sphereObj, 1.0, 8, 8); glPopMatrix(); glCallList(blueMat); glPushMatrix(); glTranslatef(-2.0, ball[1].y, -5.0); gluSphere(sphereObj, 1.0, 8, 8); glPopMatrix(); glDisable(GL_LIGHTING); }