/* sample.c /* An example CAVE program, featuring navigation and interaction. */ #include #include /* The data that will be shared between processes */ struct _balldata { float x,y,z; float radius; int grabbed; struct _balldata *next; }; void init_gl(void),draw_balls(struct _balldata **); void check_add(struct _balldata **list); struct _balldata * update_held(struct _balldata *ball); struct _balldata * check_grab(struct _balldata **list); void navigate(void); main(int argc,char **argv) { struct _balldata **ballList,*heldBall=NULL; CAVEConfigure(&argc,argv,NULL); ballList = (struct _balldata **) CAVEMalloc(sizeof(struct _balldata *)); *ballList = NULL; CAVEInit(); CAVEInitApplication(init_gl,0); CAVEDisplay(draw_balls,1,ballList); while (!CAVEgetbutton(CAVE_ESCKEY)) { navigate(); check_add(ballList); if (heldBall) heldBall = update_held(heldBall); else heldBall = check_grab(ballList); sginap(1); } CAVEExit(); } #define SPEED 5.0f /* Max navigation speed in feet per second */ /* navigate - perform the navigation calculations. */ 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.125) { 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.125) CAVENavRot(-jx * 90.0f * dt,'y'); } /* check_add - if button 1 is released, create a new ball and add it to the list */ void check_add(struct _balldata **list) { if (CAVEButtonChange(1) == -1) { struct _balldata *ball; float wandPos[3],wandFront[3]; ball = (struct _balldata *) CAVEMalloc(sizeof(struct _balldata)); if (!ball) { fprintf(stderr,"OUT OF MEMORY!\n"); return; } CAVEGetPosition(CAVE_WAND_NAV,wandPos); CAVEGetVector(CAVE_WAND_FRONT_NAV,wandFront); ball->x = wandPos[0] + wandFront[0]*2; ball->y = wandPos[1] + wandFront[1]*2; ball->z = wandPos[2] + wandFront[2]*2; ball->radius = 0.5 + drand48(); ball->grabbed = 0; ball->next = *list; *list = ball; } } /* update_help - when button 2 is released, move the held ball to the wand's position. Returns NULL if the ball is released, or the ball pointer if it is still held. */ struct _balldata * update_held(struct _balldata *ball) { if (!CAVEBUTTON2) { float wandPos[3]; CAVEGetPosition(CAVE_WAND_NAV,wandPos); ball->x = wandPos[0]; ball->y = wandPos[1]; ball->z = wandPos[2]; ball->grabbed = 0; return NULL; } return ball; } /* check_grab - if button 2 is pressed while the wand is inside a ball, grab that ball. The pointer to the grabbed ball is returned. */ struct _balldata * check_grab(struct _balldata **list) { #define SQR(x) ((x)*(x)) if (CAVEBUTTON2) { struct _balldata *ball; float wandPos[3]; CAVEGetPosition(CAVE_WAND_NAV,wandPos); for (ball = *list; ball; ball = ball->next) { float distSquared; distSquared = SQR(ball->x - wandPos[0]) + SQR(ball->y - wandPos[1]) + SQR(ball->z - wandPos[2]); if (distSquared < SQR(ball->radius)) { ball->grabbed = 1; return ball; } } } return NULL; } static GLUquadricObj *sphereObj; /* init_gl - initialize GL lighting & materials, and create GLU object for the balls */ void init_gl(void) { float greenMaterial[] = { 0, 1, 0, 1 }; glEnable(GL_LIGHT0); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, greenMaterial); sphereObj = gluNewQuadric(); } /* draw_balls - draw the balls, using the shared data for their positions & sizes */ void draw_balls(struct _balldata **ballList) { struct _balldata *ball; glClearColor(0., 0., 0., 0.); glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); glEnable(GL_LIGHTING); CAVENavTransform(); for (ball = *ballList; ball; ball = ball->next) if (ball->grabbed) { float wandPos[3]; glPushMatrix(); CAVEGetPosition(CAVE_WAND_NAV, wandPos); glTranslatef(wandPos[0], wandPos[1], wandPos[2]); gluSphere(sphereObj, ball->radius, 8, 8); glPopMatrix(); } else { glPushMatrix(); glTranslatef(ball->x, ball->y, ball->z); gluSphere(sphereObj, ball->radius, 8, 8); glPopMatrix(); } glDisable(GL_LIGHTING); }