/* navigate2.c /* An example of a navigation and interaction. Navigation is added /* to interact.c (without the joystick control of scaling). The positions /* and vectors used for interaction must be converted to world coordinates. */ #include #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 (!getbutton(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.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'); } void check_add(struct _balldata **list) { if (CAVEButtonChange(3) == -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 = 1; ball->grabbed = 0; ball->next = *list; *list = ball; } } struct _balldata * update_held(struct _balldata *ball) { if (!CAVEBUTTON1) { 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; } struct _balldata * check_grab(struct _balldata **list) { if (CAVEButtonChange(1) == 1) { struct _balldata *ball; float wandPos[3]; CAVEGetPosition(CAVE_WAND_NAV,wandPos); for (ball = *list; ball; ball = ball->next) { float dist; #define SQR(x) ((x)*(x)) dist = SQR(ball->x - wandPos[0]) + SQR(ball->y - wandPos[1]) + SQR(ball->z - wandPos[2]); if (dist < SQR(ball->radius)) { ball->grabbed = 1; return ball; } } } return NULL; } /* init_gl - initialize GL lighting & materials */ void init_gl(void) { float redMaterial[] = { DIFFUSE, 1, 0, 0, LMNULL }; lmdef(DEFLMODEL,1,0,NULL); lmbind(LMODEL,1); lmdef(DEFLIGHT,1,0,NULL); lmbind(LIGHT0,1); lmdef(DEFMATERIAL,1,0,redMaterial); } /* draw_balls - draw the balls, using the shared data for their positions & sizes */ void draw_balls(struct _balldata **ballList) { struct _balldata *ball; float sphereParam[4]; czclear(0,getgdesc(GD_ZMAX)); lmbind(MATERIAL,1); for (ball = *ballList; ball; ball = ball->next) /* Draw the grabbed ball in CAVE coordinates */ if (ball->grabbed) { sphereParam[0] = sphereParam[1] = sphereParam[2] = 0; sphereParam[3] = ball->radius; pushmatrix(); CAVEWandTransform(); sphdraw(sphereParam); popmatrix(); } /* Draw all the other balls in world coordinates */ else { sphereParam[0] = ball->x; sphereParam[1] = ball->y; sphereParam[2] = ball->z; sphereParam[3] = ball->radius; pushmatrix(); CAVENavTransform(); sphdraw(sphereParam); popmatrix(); } }