//szg-1.1 11jun07 gkf //Portal ready 3jun07 very bad stars and very very bad gesture drift //cripple gesture for now //museum mode 4mar06 // this seems to be working in mac gcc++ and szg-0.7 19feb06 // This is *****ztan.cpp**** for the portal 03jun07 #define LINUX #include // #define MAC #define SZG #define GOVERNOR = 10 //seems awfully slow #ifdef SZG #include "arPrecompiled.h" //must be the first line #include "arMasterSlaveFramework.h" //#include "arGraphicsHeader.h" what's this for? it's in opengl_stars #endif //#ifndef SZG //whereve there's so szg-libraries //#ifdef WIN32 //#include //#include //#include //#else //#ifdef MAC //#include //#include //#include //#else //#ifdef LINUX // THE LINUX/SGI CASE //#include //#include //#include //#endif //#endif //#endif //#endif //19feb06 ... dual runs on SZG/GLUT but only in 0.7 //18feb06 won't compile in 1.0 on the MAC ... open gl-errors // adding SZG begun 18feb06 ... compiles in glut on mac /* this is really CAVEtangle ! */ /* OH JOY 27jun02 gkf installed the gestural illiNavigator and it works */ /*There was a problem where tangle did not show up in simulator mode */ /*To correct this, I added the line mauspaw =0; wnd =1; siz =2. to deFault()*/ /*This was obviously a problem with the siz variable not being set*/ /* above correction made 2jun2k by Doug Nachand */ /*this is CAVEtangle to be, started 1jun2K from tngl.c */ /*major bugfix on drawsurf by slevy, there is a type conflict using gap */ /****************************************************************/ /**** skel.c = OpenSkelGlut.c = Noosh97 with CAVE removed ****/ /**** (C) 1994 Board of Trustees University of Illinois ****/ /**** A Model Real-Time Interactive OpenGL Application ****/ /**** George Francis, Glenn Chappell, Chris Hartman ****/ /**** e-mail gfrancis@math.uiuc.edu ****/ /******* revised 16jan2K by gkf**********************************/ /****************************************************************/ #include #include #include #include /* for the speedometer */ //#include the way the mac likes it gluttistry #define MAX(x,y) (((x)<(y))?(y):(x)) #define MIN(x,y) (((x)<(y))?(x):(y)) #define ABS(u) ((u)<0 ? -(u): (u)) #define FOR(a,b,c) for((a)=(b);(a)<(c);(a)++) #define DOT(p,q) ((p)[0]*(q)[0]+(p)[1]*(q)[1]+(p)[2]*(q)[2]) #define NRM(p) sqrt(DOT((p),(p))) #define DG M_PI/180 #define S(u) sin(u*DG) #define C(u) cos(u*DG) #define CLAMP(x,u,v) (xv ? v: x)) /*%%%%%%%%%%%%%%%%%begin CAVEish ONE %%%%%%%%%%%%%%%%%%*/ /* 23apr2K */ #ifdef CAVE #include /* for the shared vars */ #include #include #endif /* CAVE */ // int caveyes ; /* read cave...yes! */ enum {console, cave, cube} eyes; #define caveyes (eyes==cave) /* to make opengl_stars.c work */ //cube-shared but not cave-shared these following are: float del; // gesture hand translate attenuator float eps; // gesture hand rotate attenuator int morph; // homotopy int resethand; // gesture wandbutton flag int gesture; // gesture wandbutton flag int trailmake; // just to make it compile // what to do about sizz?? /*Shared memory variables as per Stuart Levy 1994 */ struct share_var{ float sizz; // of the final world float s_heta; /* furling angle in degrees */ float s_beta; /* curling unit 0..1 */ // float s_siz; /*final scaling factor before projection */ int s_wnd; /*wand or maus flag */ int s_gnd; /* background colore, temporarily a gp flag */ float s_luxx[3]; /* current light direction */ int s_mauspaw ; /*binary for mouse button state */ int s_th0 ; /* since the autotymer changes these */ int s_th1 ; /* they need to be shared */ int s_dth ; int s_ta0 ; /* */ int s_ta1 ; /* */ int s_dta ; float s_gap ; /* */ float s_wrist ; /* */ int s_joy ; /* */ float s_affmat[16],s_starmat[16]; /*affine matrices for object, stars*/ } *s_var; #define sizz (s_var-> sizz) #define heta (s_var->s_heta) #define beta (s_var->s_beta) // #define siz (s_var->s_siz) #define wnd (s_var->s_wnd) #define gnd (s_var->s_gnd) /* use only if printframe function is present */ #define luxx (s_var->s_luxx ) #define affmat (s_var->s_affmat) #define starmat (s_var->s_starmat) #define mauspaw (s_var->s_mauspaw) #define th0 (s_var->s_th0) #define th1 (s_var->s_th1) #define dth (s_var->s_dth) #define ta0 (s_var->s_ta0) #define ta1 (s_var->s_ta1) #define dta (s_var->s_dta) #define gap (s_var->s_gap) #define wrist (s_var->s_wrist) #define joy (s_var->s_joy) /***********************************************************************/ //the following getmem worked in Canvas but not in Portal, replace with portal-znail for now #if 0 void getmem(void){ /* remember, you need (share_var*) for C++ compiler */ if(caveyes) #ifdef CAVE s_var =CAVEMalloc(sizeof(struct share_var)) /* no ; here ! */ #endif /* CAVE */ ; /* but ; here */ else /* nonCAVE */ s_var =malloc(sizeof(struct share_var)); if(s_var==NULL){fprintf(stderr,"No room to share! %x \n",s_var); exit(1);} } #endif //from znail.cpp of Portal void getmem(void){ if(eyes==cave) #ifdef CAVE s_var = CAVEMalloc(sizeof(struct share_var)) #endif ; else /* CONSOLE or SYZYGY */ s_var = (struct share_var *)malloc(sizeof(struct share_var)); if(s_var==NULL) {fprintf(stderr,"No room to share! %x \n",s_var); exit(1);} } /* putting dataprep here simplifies the includes down to two */ void deFault(void); /* prototyped here, but defined later */ void initstars(void); /* prototype here, definede in opengl_stars.c */ void audioprep(void){}; /* defined here, once defined later, remove {} */ void dataprep(void){ audioprep(); deFault(); initstars(); } /*%%%%%%%%%%%%%%%%%end CAVEish ONE %%%%%%%%%%%%%%%%%%*/ /* #include "caveONE.c" */ /* global variables */ float gap0=1.; /* default gap */ float joy0=1.; /* default joy */ float siz0=12.; /* default sizz needs to be 12 in cube */ float wrist0=-0.3; /* default wrist */ float lux[3]={1.,2.,3.}; /*world light direction vector */ float amb, pwr ; /* ambient fraction, pseudo-specular power */ float mysiz,speed, torq, focal, far; /*console navigation variables */ int win = 1; /* 2 full screen, use 0 for demand sized */ unsigned int BUT, XX, YY,SHIF; /* used in chaptrack gluttery */ int xt,yt; /* once was xt,yt,xm,ym for viewportery */ int mode,msg,binoc; /* pretty global */ int umm, rndr ; /* an index in 0,1,2, and renderflag */ float dheta, rh1, rh0; #define FLYMODE (0) #define TURNMODE (1) int ii, jj, kk; float tmp, temp; /* saves gray hairs later */ float mat[16]; float nose; /* to eye distance in console */ /**********************************************************************/ #define BR 2 //denominator for museum mode #define DR .5 //denominator for museum mode void autotymer(int reset){ /* cheap animations */ #define TYME(cnt,max,act) {static int cnt; if(first)cnt=max; else\ if(cnt?cnt--:0){ act ; goto Break;}} static int first = 1; /* the first time autymer is called */ if(reset)first=1; /* or if it is reset to start over */ TYME( furl , 180*BR,heta += 1*DR) TYME( pause , 50, ) TYME( furl , 180*BR,heta += 1*DR) TYME( dwell , 50, ) TYME( unfurl , 360*BR,heta -= 1*DR) TYME( dwell , 50, ) TYME( uncurl , 100*BR,beta -= .01*DR) TYME( dwell , 50, ) TYME( uncurl , 100*BR,beta += .01*DR) TYME( dwell , 50, ) TYME(finish , 1 , first = 1 ) first = 0; Break: ; /* yes Virginia, C has gotos */ } /**********************************************************************/ int cdth, fdth, cdta, fdta; /**********************************************************************/ void deFault(void){ float foo; /* surface patch */ beta = 1.0; heta=0.; dheta=1.; gap = gap0; joy=joy0; sizz=siz0; wrist=wrist0; th0 = -20 ; th1 = 20; cdth=20; fdth= 10 ; dth = fdth; ta0 = -200 ; ta1 = 200; cdta=20; fdta= 2; dta = fdta; rh0 = .25 ; rh1 = 2.; rndr = 1; umm = 0; msg=1; // portal binoc=0; nose=.06; mode=TURNMODE; speed=.1; torq=.02; focal = 2.; far =13.; mysiz=.01; morph=1; FOR(ii,0,16) starmat[ii]=affmat[ii] = (ii/4==ii%4); /* identities */ foo=NRM(lux); FOR(ii,0,3)lux[ii]/=foo; amb = .3; pwr = 10. ; mauspaw =0; wnd =1; sizz =2.; /*CAVE initials */ if(eyes==cave){affmat[12]=0; affmat[13]= 5; affmat[14]= -10 ; } if(eyes==cube){affmat[12]=0; affmat[13]= 5; affmat[14]= -5 ; } if(eyes==console){affmat[12]=0; affmat[13]= 0; affmat[14]= -4.2 ; } gesture=0; //not in museum mode in the PORTAL eps =0.02; //hand rotation gesture attenuation del =0.2; //hand translation gesture attenuation resethand=0; autotymer(1); /* reset autotymer to start at the beginning */ } /**********************************************************************/ void drawvert(int th, int ta){ float lmb,spec,nn[3], dog, cat; nn[0] = C(th)*C(ta); /* unit sphere radius vector */ nn[1] = S(th)*C(ta); nn[2] = S(ta); lmb = DOT(nn,luxx);lmb =(lmb<0 ? .2 : lmb); lmb = MAX(amb, lmb); spec = CLAMP((1.1 - pwr+pwr*lmb), 0., 1.); dog = (float)(ta-ta0)/(float)(ta1-ta0); cat = (float)(th-th0)/(float)(th1-th0); glColor3f( MAX(spec, lmb*dog), /* map R^2(dog,cat)->R^3(RGBspace */ MAX(spec, lmb*(.25 + ABS(cat -.5))), /* dog cat model of Hartman */ MAX(spec, lmb*(1 - cat))); /* illiLight by Ray Idaszak 1989 */ glVertex3f( C(th) + .5*nn[0], S(th) + .5*nn[1], .5*nn[2]); } /* end drawvert */ /**********************************************************************/ void drawtor(void){ int th, ta; dth = (int)((th1-th0)/24); /* 24 meridian strips */ dta = (int)((ta1-ta0)/24); /* 24 triangle pairs per strip */ for(th=th0; th < th1; th += dth){ glBegin(GL_TRIANGLE_STRIP); for(ta=ta0; ta < ta1; ta += dta){ drawvert(th,ta); drawvert(th+(int)(gap*dth),ta); } glEnd(); } /* end for.theta loop */ } /* end drawtor */ /**********************************************************************/ /* mapping to a ribbon */ void ribbon(float vv[3],int th,int ta) { int inx; float rr, v1,v2,v3,a1,a2,a3,s2,c2,tmp,rh, lambda; /* ribbon */ vv[umm] = 0.; vv[(umm+1)%3] = .01*th; vv[(umm+2)%3] = .01*ta; /* spherical radius of point */ rh = NRM(vv); rr = (rh1-rh)/(rh1-rh0); lambda = beta*M_PI*(1-C(180*rr)); /* ogived rr*/ c2 = cos(lambda); s2 = sin(lambda); /* twisted spherical shell */ v1 = vv[0]*c2 - s2*vv[1]; v2 = vv[1]*c2 + s2*vv[0]; v3 = vv[2]; /* Kauffman's quator: rot(lambda,axis) */ a1 = sin(heta*DG); a2 = 0; a3 = cos(heta*DG); tmp =(1-c2)*(v1*a1+v2*a2+v3*a3); vv[0]= v1*c2 + s2*(a2*v3-a3*v2) + tmp*a1; vv[1]= v2*c2 + s2*(a3*v1-a1*v3) + tmp*a2; vv[2]= v3*c2 + s2*(a1*v2-a2*v1) + tmp*a3; } /**********************************************************************/ void paint(float lmb,float dog,float cat){ /* note dog and cat float 0..1 */ float rr,gg,bb; float spec; rr = dog; /* Chris Hartman, 1991 */ gg = ABS(cat - 0.5) + .25; bb = 1. - cat; lmb = MAX(lmb,amb); spec=MIN(1.,( 1. - pwr + pwr*lmb)); /* Ray Idaszak, 1988 */ rr = MAX(lmb*rr, spec); gg = MAX(lmb*gg, spec); bb = MAX(lmb*bb, spec); glColor3f(rr,gg,bb); } /**********************************************************************/ /* draw outside orb */ void draworb(void ){ int ii,jj; float vv[3]; FOR(ii,0,3){ /* lRGBrange(50*(ii!=0),50*(ii!=1),50*(ii!=2), 255*(ii!=0),255*(ii!=1),255*(ii!=2),znear,zfar); */ /* linewidth(thick); depthcue(1); */ glBegin(GL_LINE_STRIP); FOR(jj,0,128){ vv[ii]= 0.; vv[(ii+1)%3]= rh1*sin(jj*M_PI/64); vv[(ii+2)%3]= rh1*cos(jj*M_PI/64); glVertex3fv(vv); } glEnd(); /* depthcue(0); */ } } /**********************************************************************/ // void drawsurf(void(*surf)()) void drawsurf(void(*surf)(float*,int,int)) { int th, ta; float dog, vv[3], aa[3], vo[3], nn[3], lmb; for(th=th0; th < th1; th += dth){ if(rndr)glBegin(GL_TRIANGLE_STRIP); dog = (float)(th-th0)/(th1-th0); paint(.8,dog, 0); (*surf)(vo,th,ta0); glVertex3fv(vo); /* first vertex */ (*surf)(aa,(int)(th+dth-gap),ta0); glVertex3fv(aa); /* first rung */ for(ta = ta0+dta; ta <= ta1; ta += dta){ (*surf)(vv,th,ta ); /* normal on vo aa vv */ nn[0]=(aa[1]-vv[1])*(vo[2]-vv[2])-(aa[2]-vv[2])*(vo[1]-vv[1]); nn[1]=(aa[2]-vv[2])*(vo[0]-vv[0])-(aa[0]-vv[0])*(vo[2]-vv[2]); nn[2]=(aa[0]-vv[0])*(vo[1]-vv[1])-(aa[1]-vv[1])*(vo[0]-vv[0]); lmb = DOT(luxx,nn)/NRM(nn); if(lmb<0.)lmb = -lmb; paint(lmb, dog,(float)(ta-ta0)/(float)(ta1-ta0)); if(!rndr){ glBegin(GL_LINE_STRIP); glVertex3fv(vo); glVertex3fv(vv); } /* rail */ glVertex3fv(vv); (*surf)(aa,(int)(th+dth-gap),ta); glVertex3fv(aa); /*subsequent rung*/ vo[0]=vv[0]; vo[1]=vv[1]; vo[2]=vv[2]; if(!rndr)glEnd(); } /* end tau loop */ if(rndr)glEnd(); } /* end theta loop */ } /**********************************************************************/ void drawall(void){ draworb(); if(gnd)drawtor(); drawsurf(ribbon); umm = (umm+1) % 3; drawsurf(ribbon); umm = (umm-1) % 3; /*something wrong here big time*/ } /**********************************************************************/ #include "dawn.c" #include "opengl_stars.c" #if 0 void drawstars(void){ static float star[1000][3]; static int virgin=1; if(virgin){ /* first time set up the stars */ FOR(ii,0,1000)FOR(jj,0,3)star[ii][jj]=random()/(float)0x40000000-1.; virgin=0; /* never again */ } glMatrixMode(GL_MODELVIEW); glPushMatrix(); /* insurance of superstition */ glMultMatrixf(starmat); glColor3f(1.0,1.0,0.0); glBegin(GL_POINTS); FOR(ii,0,1000)glVertex3fv(star[ii]); glEnd(); glPopMatrix(); glClear(GL_DEPTH_BUFFER_BIT); /* so the stars are behind everything */ } #endif /**********************************************************************/ void arguments(int argc,char **argv){ eyes = cube; //where znail does it while(--argc){++argv; if(argv[0][0]=='-')switch(argv[0][1]){ case 'w': win =atoi(argv[1]); argv++; argc--; break; case 'c': eyes=console;break; case 'v': eyes=cave;break; case 'k': eyes=cube;break; case 'g': gap0 =atof(argv[1]); argv++; argc--; break; case 's': siz0 =atof(argv[1]); argv++; argc--; break; case 'i': wrist0 =atof(argv[1]); argv++; argc--; break; case 'L': lux[0]=atof(argv[1]); lux[1]=atof(argv[2]); }}} /**********************************************************************/ void keyboard(unsigned char key, int x, int y){ #define IF(K) if(key==K) #define PRESS(K,A,b) IF(K){b;}IF((K-32)){A;} /*was backwards in previous versions */ #define TOGGLE(K,flg) IF(K){(flg) = 1-(flg); } #define CYCLE(K,f,m) PRESS((K), (f)=(((f)+(m)-1)%(m)),(f)=(++(f)%(m))) #define SLIDI(K,f,m,M) PRESS(K,(--fM?M:f)) #define SLIDF(K,f,m,M,d) PRESS(K,((f -= d)M?M:f)) /* Only ASCII characters can be processes by this GLUT callback function */ IF(27) { exit(0); } /* ESC exit */ TOGGLE('v',binoc); /* cross-eyed STEREO */ //relieve the wusser spacebar CYCLE(',', mode,TURNMODE+1); /* fly/turn modes */ TOGGLE('m',morph); /* autotymer on/off */ TOGGLE('w',msg); /* writing on/off */ PRESS('n', nose -= .001 , nose += .001 ); /* for binoculars */ PRESS('s',speed /= 1.02, speed *= 1.02); /* flying speed */ PRESS('q',torq /= 1.02, torq *= 1.02); /* turning speed */ PRESS('o', focal *= 1.1 , focal /= 1.1) /* telephoto */ PRESS('i', mysiz /= 1.1, mysiz *= 1.1) /* rescale the world */ PRESS('p', far *= 1.01 , far /= 1.01) /* rear clipping plane */ PRESS('z', deFault(), deFault()); /* zap changes */ PRESS('g',gap /= .9, gap *= .9); /* gap parameter */ PRESS('a',amb /= .9, amb *= .9); /* ambient fraction */ PRESS('r',pwr /= .9, pwr *= .9); /* pseudo-spec power */ PRESS('j', dheta /=2, dheta *=2); PRESS('h', heta -=dheta, heta +=dheta); PRESS('b', beta -=.01, beta +=.01); CYCLE('u', umm, 3); } /**********************************************************************/ void special_keybo(int key, int x, int y){ /*non-ASCII keypresses go here, if you're lucky enough to know their names */ fprintf(stderr," non-ASCII character was pressed.\n"); fprintf(stderr," use special_keybo() to process it\n"); } /**********************************************************************/ float speedometer(void){ double dbl; static double rate; static int ii=0; static struct timezone notused; static struct timeval now, then; if(++ii % 8 == 0){ /* 8 times around measure time */ gettimeofday(&now, ¬used); /* elapsed time */ dbl = (double)(now.tv_sec - then.tv_sec) +(double)(now.tv_usec - then.tv_usec)/1000000; then = now; rate = 8/dbl; } return((float)rate); } /**********************************************************************/ void char2wall(float x,float y,float z, char buf[]){ char *p; glRasterPos3f(x,y,z); for(p = buf;*p;p++) glutBitmapCharacter( caveyes?GLUT_BITMAP_TIMES_ROMAN_24:GLUT_BITMAP_9_BY_15,*p); } /**********************************************************************/ // seems that messages is somebody's reserved word ... postit forever void postit(void){ char buf[256]; /* console messages are done differently from cave */ #define LABEL2(x,y,W,u) {sprintf(buf,(W),(u));char2wall(x,y,0.,buf);} glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0,3000,0,3000); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); /*bull's eye*/ if(mode==TURNMODE) glColor3f(0x22/255.,0x88/255.,0xdd/255.); else glColor3f(.8,.8,.8); LABEL2(1500,1500,"%s","o"); /* writings */ if(mode==TURNMODE) glColor3f(1.,0.,1.); else glColor3f(1.,1.,0.); LABEL2(80,80,"%4.1f fps",speedometer()); LABEL2(80,2840,\ "(ESC)ape (V)Binoc (MAUS2)Fore (BAR)Flymode %s (H)omotopy (W)riting", mode?"FLYING":"CONTROL"); LABEL2(10,10,"illiOpenSkelGLUT 18feb06\ by Francis, Bourd, Hartman & Chappell, U Illinois, 1995..2003 %s",""); LABEL2(80,2770,"(N)ose %0.3f",nose); LABEL2(80,2700,"(S)peed %0.4f",speed); LABEL2(80,2630," tor(Q) %0.4f",torq); LABEL2(80,2560,"near clipper %g", mysiz*focal); LABEL2(80,2490,"f(O)cal factor %g",focal); LABEL2(80,2420,"my s(I)ze %.2g",mysiz); LABEL2(80,2350,"far cli(P)er= %.2g",far); LABEL2(80,2280,"(Z)ap %s",""); LABEL2(80,2210,"(G)ap %.2g",gap); LABEL2(80,2140,"(A)mb %.2g",amb); LABEL2(80,2070,"(H)eta furl %.4g",heta); LABEL2(80,2000,"(B)eta curl %.4g",beta); LABEL2(80,1930,"(J)dheta %.4g ",dheta); LABEL2(80,1860,"(U)mm %d ",umm); LABEL2(80,1790,"ho(M)otopy %d ",morph); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); } /**********************************************************************/ void chaptrack(int but,int xx,int yy,int shif){ long dx,dy; dx = xx -.5*xt; dx = abs(dx)>5?dx:0; dy = yy -.5*yt; dy = abs(dy)>5?dy:0; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); if(mode==TURNMODE) glTranslatef(affmat[12],affmat[13],affmat[14]); glRotatef(dx*torq,0.,1.,0.); glRotatef(dy*torq,1.,0.,0.); if(but&(1<M?M:f)) #define CAVESLIDF(K,f,m,M,d) CAVEPRESS(K,((f -= d)M?M:f)) CAVEPRESS(CAVE_PKEY, far *= 1.01, far /= 1.01) /* rear clipping plane*/ CAVEPRESS(CAVE_QKEY, speed /= 1.02, speed *= 1.02);/* flying speed */ CAVEPRESS(CAVE_RKEY, torq /= 1.02, torq *= 1.02); /* turning speed */ CAVETOGGLE(CAVE_YKEY,wnd); /* mauspaw vs wandpaw *//* not yet implemented */ CAVEPRESS(CAVE_ZKEY, deFault(), deFault()); /* zap changes */} void graffiti(void){ /* used to be called speedo */ char buf[256]; /*messages written into here */ #define LABEL3(x,y,z,W,u){sprintf(buf,(W),(u));char2wall(x,y,z,buf);} static float last=0.,fps; /*for measuring time */ if(!CAVEMasterDisplay()) return; /* USE CAVEMasterWall in papeBeta */ /* in grafiXlab we have old CAVElib? */ if(floor(2.*(*CAVETime))>floor(2.*last)){ /* rationalize this */ last=*CAVETime; fps=*CAVEFramesPerSecond; } if(mode==TURNMODE){ glColor3f(1.,.8,1.); /* bright MAG */ LABEL3(-3.8,1.,-5.0,\ "(L)auto (M)mode 3=shrink 6=grow 5=freeze 7=reset (R)cyclejoy=%d",joy); } else { glColor3f(1.,1.,0.); LABEL3(-3.8,1.0,-5.0, " FLY-by-gesture, (hold M)tractor, (R)cyclejoy=%d",joy); } LABEL3(-4.8,8.0,-5.0, "illiTangle\ by Francis, Bourd, Hartman & Chappell, (C) 1995..2002 U.Illinois %s","") LABEL3(-4.8,1.0,-5.0,"%5.1f fps",fps); } void cavetrack(void){ float azi,ele,rol,hx,hy,hz,wx,wy,wz; static float ohx,ohy,ohz; /*old head position */ static float owx,owy,owz; /*old wand position */ static int opaw = 0,paw, friz=0; int doit ; /* all joy */ if(!CAVEMasterDisplay()) return; /* doit once per frame */ paw = wnd ? (CAVEBUTTON1*2+CAVEBUTTON2)*2+CAVEBUTTON3 : mauspaw; /* if(paw) joy = 1; /* activate joystick by clicking any button, but see anon*/ if(opaw!=2 && paw==2) mode = (mode+1)%(TURNMODE+1); /* click modes */ if(mode==TURNMODE){ /* hold middle button and click right to shrink */ if (opaw == 2 && paw == 3)sizz /= 1.5; /*shrink object */ if (opaw == 2 && paw == 6)sizz *= 1.5; /* grow object */ if (opaw != 4 && paw == 4)morph = 1-morph;/* shape changer */ if (opaw != 5 && paw == 5)friz = 1-friz; /* parking option */ } if(opaw != 1 && paw == 1)joy = joy<2?joy+1:0; /* easy joy */ if(opaw==5 && paw == 5)gap *= 1.1; /* hold right and */ if(opaw==3 && paw == 3)gap /= 1.1; /* +left -right */ if(opaw==2 && paw == 7){ /* restart, the most useful feature */ deFault(); ohx=ohy=ohz=0; owx=owy=owz=0; } if(wnd){ CAVEGetWandOrientation(azi,ele,rol); CAVEGetHead(hx,hy,hz); /*position*/ CAVEGetWand(wx,wy,wz); /*position*/ } else{ /* fix this for CAVE mouse flying */ azi = .5*512; ele = .5*-512; } glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslatef(ohx-hx,ohy-hy,ohz-hz); if(mode==TURNMODE) glTranslatef(affmat[12],affmat[13],affmat[14]); if(friz==0){ /* then wand rotations turn */ glRotatef(rol*(mode?torq:-torq),0.,0.,1.); glRotatef(ele*-torq, 1.,0.,0.); glRotatef(azi*-torq,0.,1.,0.); } if(joy==2&&((fabsf(CAVE_JOYSTICK_Y)>.02)||(fabsf(CAVE_JOYSTICK_X)>.02))) glTranslatef(CAVE_JOYSTICK_X*speed,0.,CAVE_JOYSTICK_Y*speed); doit=(mode==TURNMODE)&&(opaw==1)&&(paw==1); if(joy==1)glTranslatef((wx-hx)*speed*doit, (wy-hy+1.5)*speed*doit, (-wz+hz+wrist)*speed); /* auto calibrate ? */ if(opaw==2 && paw==2)glTranslatef(wx-owx, wy-owy, wz-owz); /*wand tractor */ if(mode == TURNMODE) glTranslatef(-affmat[12],-affmat[13],-affmat[14]); glMultMatrixf(affmat); glGetFloatv(GL_MODELVIEW_MATRIX,affmat); {int ii,jj; for(ii=0;ii<3;ii++){ luxx[ii]=0; /* calculite */ for(jj=0;jj<3;jj++) luxx[ii] += affmat[ii*4+jj]*lux[jj];} } if(mode==FLYMODE && !friz) /*make the star matrix rotate*/ { glLoadIdentity(); glRotatef(rol*(mode?torq:-torq),0.,0.,1.); glRotatef(ele*-torq,1.,0.,0.); glRotatef(azi*-torq,0.,1.,0.); glMultMatrixf(starmat); glGetFloatv(GL_MODELVIEW_MATRIX,starmat); } glPopMatrix(); opaw=paw; ohx=hx; ohy=hy; ohz=hz; owx=wx; owy=wy; owz=wz; if(morph) autotymer(0); /* advance autotymer */ /* audiofunc(); */ } //end cavetrack void drawcaveinit(void){ /* kludge? needed why ? */ CAVEFar = 1000.; glClearColor(0.,0.,0.,0.); glClearDepth(1.); } void drawcave(void){ float hx,hy,hz; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawstars(); graffiti(); CAVEGetHead(hx,hy,hz); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(hx,hy,hz); glMultMatrixf(affmat); glScalef(sizz,sizz,sizz); drawall(); glPopMatrix(); } #endif /* CAVE */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%end CAVE %%%%%%%%%%%%%%*/ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%begin SZG %%%%%%%%%%%%%%*/ #ifdef SZG // preexchange callback bool cubeinit(arMasterSlaveFramework& fw, arSZGClient& ){ ar_setNavMatrix(ar_translationMatrix(0,-5,0)); //initial position fw.addTransferField("affmat", affmat, AR_FLOAT, 16); fw.addTransferField("starmat", starmat, AR_FLOAT, 16); fw.addTransferField("sizz", (&sizz), AR_FLOAT, 1); fw.addTransferField("del", (&del), AR_FLOAT, 1); fw.addTransferField("eps", (&eps), AR_FLOAT, 1); fw.addTransferField("resethand", (&resethand), AR_INT, 1); fw.addTransferField("gesture", (&gesture), AR_INT, 1); fw.addTransferField("heta", (&heta), AR_FLOAT, 1); /* furling angle in degrees */ fw.addTransferField("beta", (&beta), AR_FLOAT, 1); /* curling unit 0..1 */ fw.addTransferField("wnd", (&wnd), AR_INT,1 ); /*wand or maus flag */ fw.addTransferField("gnd", (&gnd), AR_INT,1 ); /* background color, temporarily a gp flag */ fw.addTransferField("mauspaw", (&mauspaw), AR_INT,1); // mausbutton state flag fw.addTransferField("luxx", (&luxx), AR_FLOAT,3); // current light position fw.addTransferField("th0", (&th0), AR_INT,1 ); fw.addTransferField("th1", (&th1), AR_INT,1 ); fw.addTransferField("dth", (&dth), AR_INT,1 ); fw.addTransferField("ta0", (&ta0), AR_INT,1 ); fw.addTransferField("ta1", (&ta1), AR_INT,1 ); fw.addTransferField("dta", (&dta), AR_INT,1 ); fw.addTransferField("gap", (&gap), AR_INT,1 ); fw.addTransferField("wrist", (&wrist), AR_INT,1 ); fw.addTransferField("joy", (&joy), AR_INT,1 ); fw.addTransferField("gap", (&gap), AR_INT,1 ); fw.addTransferField("morph", (&morph), AR_INT, 1); return true; } // keyboard callback void clefs(arMasterSlaveFramework& , unsigned char key, int x, int y){ keyboard(key,x,y); } //headsup callback void overlay(arMasterSlaveFramework&) {if(msg)postit; else return;} //Portal likes this // canvas likes this: void overlay(void) {if(msg)postit(); else return;} // pre-exchange callback //gesturetrack gkf: 2jun04 /***************************************************************/ /* Given a rotation matrix convert it into a quaternion */ /* Given a quaternion convert it into a rotation matrix */ /* By Robert Shuttleworth, illiMath2001, July 2001 */ /* */ /***************************************************************/ void normalize(float *vec){ int ii; float temp = vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2] + vec[3]*vec[3]; if (temp == 1){ /* printf(" The vector is of unit length.\n"); */ } else{ temp = sqrt(temp); for(ii=0;ii<4;ii++)vec[ii] /= temp; } } void printquat(float *quat){ printf("\n Quaternion: \n"); printf(" w = %f ", quat[0]); printf(" x = %f ", quat[1]); printf(" y = %f ", quat[2]); printf(" z = %f ", quat[3]); } void printmat(float *mat){ printf("\n Matrix: \n"); printf(" %f %f %f %f \n", mat[0], mat[4], mat[8], mat[12]); printf(" %f %f %f %f \n", mat[1], mat[5], mat[9], mat[13]); printf(" %f %f %f %f \n", mat[2], mat[6], mat[10], mat[14]); printf(" %f %f %f %f \n", mat[3], mat[7], mat[11], mat[15]); } void q2m(float *quat, float *mat){ /* quaternion yields a rotation */ float w = quat[0], x = quat[1], y = quat[2], z = quat[3]; float ww, xx, yy, zz, xy, xz, yz, wz, wy, wx; ww = w*w; xx = x*x; yy = y*y; zz = z*z; xy = x*y; xz = x*z; yz = y*z; wz = w*z; wy = w*y; wx = w*x; xz = x*z; mat[0]=ww+xx-yy-zz; mat[4]=2*xy - 2*wz; mat[8]=2*wy + 2*xz; mat[1]=2*wz + 2*xy; mat[5]=ww-xx+yy-zz; mat[9]=2*yz - 2*wx; mat[2]=2*xz - 2*wy; mat[6]=2*wx + 2*yz; mat[10]=ww-xx-yy+zz; mat[3] = mat[7] = mat[11] = mat[12] = mat[13] = mat[14] = 0; mat[15] = ww + xx + yy + zz; /* this is a check */ } void m2q(float *mat, float *quat){ /* isometry yields a quaternion */ float tmp; int ii, jj; float tr[4] ={ /* pseudo traces */ mat[0] + mat[5] + mat[10], mat[0] - mat[5] - mat[10], -mat[0] + mat[5] - mat[10], -mat[0] - mat[5] + mat[10]}; // printf("trace %f %f %f %f \n" , tr[0],tr[1],tr[2],tr[3]); ii=1; jj=2; /* find the largest tr */ if(tr[0] > tr[1]) ii = 0; if(tr[3] > tr[2]) jj = 3; if(tr[jj] > tr[ii]) ii = jj; // printf("\n %i is the largest trace. \n", ii); tmp = 4*sqrt(tr[ii]+1)/2; switch(ii){ case 0: quat[0] = tmp/4; quat[1] = (mat[6] - mat[9]) / tmp; quat[2] = (mat[8] - mat[2]) / tmp; quat[3] = (mat[1] - mat[4]) / tmp; break; case 1: quat[0] = (mat[6] - mat[9]) / tmp; quat[1] = tmp/4; quat[2] = (mat[1] + mat[4]) / tmp; quat[3] = (mat[8] + mat[2]) / tmp; break; case 2: quat[0] = (mat[8] - mat[2]) / tmp; quat[1] = (mat[4] + mat[1]) / tmp; quat[2] = tmp/4; quat[3] = (mat[9] + mat[6]) / tmp; break; case 3: quat[0] = (mat[1] - mat[4]) / tmp; quat[1] = (mat[8] + mat[2]) / tmp; quat[2] = (mat[9] + mat[6]) / tmp; quat[3] = tmp/4; break; } } void loadIdentity(float* mat) {int ii; for(ii=0;ii<16;ii++) mat[ii]=float(ii/4 == ii%4);} void getmat(float *target, float *source){ memcpy(target,source, 16*sizeof(float)); } void multmatinv(float *T){ // of an Euclidean isometry float N[16]; getmat(N,T); N[1] = T[4]; N[2] = T[8]; N[6] = T[9]; N[4] = T[1]; N[8] = T[2]; N[9] = T[6]; N[12]= -T[0]*T[12]-T[1]*T[13]-T[2]*T[14]; N[13]= -T[4]*T[12]-T[5]*T[13]-T[6]*T[14]; N[14]= -T[8]*T[12]-T[9]*T[13]-T[10]*T[14]; glMultMatrixf(N); } void updateaffmat(float *oldhand, float *newhand){ float dx=0, dy=0, dz=0 ; float dhand[16]; float quat[4]; //we do arithmetic on an unused stack for convenience glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); multmatinv(newhand); glMultMatrixf(oldhand); glGetFloatv(GL_TEXTURE_MATRIX, dhand); glPopMatrix(); //dhand= newhand^-1 * oldhand dx=del*dhand[12]; dhand[12]=0; //attenuation is about right dy=del*dhand[13]; dhand[13]=0; dz=del*dhand[14]; dhand[14]=0; //use a bit of the translation in dhand and then strip translation if(gesture==2){ //shrink dhand m2q(dhand,quat); quat[0]= 1-eps + eps*quat[0]; quat[1] *= eps; quat[2] *= eps; quat[3] *= eps; normalize(quat); q2m(quat,dhand); } #define GT .01 #define LT .05 if(gesture==1){ static float gt=0; gt+=GT; quat[0]=C(LT) ; quat[1]=S(LT)*C(gt)*C(1.618*gt); quat[2]=S(LT)*S(gt)*C(1.618*gt); quat[3]=S(LT)*S(1.618*gt); normalize(quat); q2m(quat,dhand); } if(mode==FLYMODE){ glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMultMatrixf(dhand); //rotate the stars glMultMatrixf(starmat); glGetFloatv(GL_TEXTURE_MATRIX,starmat); } glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); if(mode==TURNMODE) glTranslatef(affmat[12],affmat[13],affmat[14]); glMultMatrixf(dhand); //just the rotation of it glTranslatef(dx,dy,dz); if(mode==TURNMODE) glTranslatef(-affmat[12],-affmat[13],-affmat[14]); glMultMatrixf(affmat); glGetFloatv(GL_TEXTURE_MATRIX,affmat); } void readbuttons(arMasterSlaveFramework& fw){ const int butn[6]= { fw.getButton(0), fw.getButton(1), fw.getButton(2), fw.getButton(3), fw.getButton(4), fw.getButton(5) }; static int obutn[6]={0,0,0,0,0,0}; if(obutn[0]==0 & butn[0] == 1) morph=1-morph; //}{A}button = portal(L) if(obutn[1]==0 & butn[1] == 1) resethand=1; //{B}button = portal(M) // if(obutn[2]==0 & butn[2] == 1) gesture=(gesture==2)?0:2;//{C}button = portal(R) // very very bad drift when gesture is toggled if(obutn[4]==0 & butn[4] == 1) mode=1-mode; //{Y} button if(obutn[5]==0 & butn[5] == 1) deFault(); //{Z}ap if(obutn[3]==0 & butn[3] == 1) //{A} trail cycle { static int cnt=0; switch(++cnt){ case 1 : trailmake=1; break; //turn on trail case 2 : gap=6; break; //erase surface case 3 : cnt= 0; trailmake=0; gap=gap0; break; //as before }} #ifdef DiVE if(obutn[1]==0 & butn[1] == 1) morph=1-morph; //{R}ed button if(obutn[3]==0 & butn[3] == 1) gesture=1-gesture; //{B}lue bbutton if(obutn[2]==0 & butn[2] == 1) resethand=1; //{G}reen button if(obutn[4]==0 & butn[4] == 1) mode=1-mode; //{J}oy button if(obutn[5]==0 & butn[5] == 1) deFault(); //{T}rigger zap if(obutn[0]==0 & butn[0] == 1) //{Y}ellow trail cycle { static int cnt=0; switch(++cnt){ case 1 : trailmake=1; break; //turn on trail case 2 : gap=6; break; //erase surface case 3 : cnt= 0; trailmake=0; gap=gap0; break; //as before }} #endif memcpy(obutn,butn,6*sizeof(int)); } void gesturetrack(arMasterSlaveFramework& fw){ //the present logic is legacy stuff from zyspace, rationalize it! if (!fw.getMaster())return; //only the master should listen //this is the gesture navigator static float oldhand[16]; float handmat[16]; arMatrix4 arhand=fw.getMatrix(1); getmat(handmat,arhand.v); //geotrack(arhand.v) gets arhand.v and used as float* handmat static bool reshand=true; if(resethand){reshand=true; resethand=false;} //do we really need two flags? if(gesture){ updateaffmat(oldhand,handmat); } if(reshand){reshand=false; getmat(oldhand, handmat);} //this is the Pape navigator //this should really be done on the arithmetic (Texture) stack glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); const float joy0 = fw.getAxis(0); //joystick right-left const float joy1 = fw.getAxis(1); //joystick fore-aft const float xx = arhand.v[8]; const float yy = arhand.v[9]; const float zz = arhand.v[10]; // printf(" xx %g yy %g zz %g \n",xx,yy,zz); const float da = .5*joy0; const float ds = .1*joy1; //joystick translates in the wand direction glTranslatef(xx*ds, yy*ds, zz*ds); glRotatef(da, 0.,1.,0.); glMultMatrixf(affmat); glGetFloatv(GL_MODELVIEW_MATRIX,affmat); glPopMatrix(); //this is an illogical place for this but maybe it works again {int ii,jj; for(ii=0;ii<3;ii++){ luxx[ii]=0; /* calculite */ for(jj=0;jj<3;jj++) luxx[ii] += affmat[ii*4+jj]*lux[jj];} } readbuttons(fw); } #if 0 //replaced by gesturetrack but also works void cubetrack(arMasterSlaveFramework& fw){ int ii; if (!fw.getMaster()) return; // chokes here but it's in skel1j const int butn[3]={fw.getButton(0), fw.getButton(1), fw.getButton(2)}; const float j0 = fw.getAxis(0); const float j1 = fw.getAxis(1); arMatrix4 handmatrix=fw.getMatrix(1); const float xx = handmatrix.v[8]; const float yy = handmatrix.v[9]; const float zz = handmatrix.v[10]; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslatef(xx*j1/10,0,0); glTranslatef(0,yy*j1/10,0); glTranslatef(0,0,zz*j1/10); glRotatef(j0/2.0, 0.,1.,0.); glMultMatrixf(aff); glGetFloatv(GL_MODELVIEW_MATRIX,aff); {int ii,jj; for(ii=0;ii<3;ii++){ luxx[ii]=0; /* calculite */ for(jj=0;jj<3;jj++) luxx[ii] += affmat[ii*4+jj]*lux[jj];} } glPopMatrix(); if(butn[0] == 1) deFault(); if(butn[2] == 1)morph = 1-morph; } #endif // post-exchange callback , leftover from trails void diddle(arMasterSlaveFramework& fw){ /* console idle */ #if 0 doit = ++doit % MANY; // MANY = 8 // if(moving && trailmake && (doit==2))maketrail(); // kludge for moving=1; {static float ox,oy,oz; moving = (ox!=affmat[12]|oy!=affmat[13]|oz!=affmat[14])?1:0 ; ox=affmat[12];oy=affmat[13];oz=affmat[14];} if(moving && trailmake && (doit==2))maketrail(); // if(trailwryte){printf("trail is "); writetrail(); } if(morph && (doit==2)) autotymer(0); as in october snail //this works in znail but not in ztan, why-oh-why-oh? {static int click=GOVERNOR; // as in znail if(morph&&click==0)autotymer(0); click=click>0?click-1:GOVERNOR;} #endif if(morph==1)autotymer(0); } // draw callback void cubedraw(arMasterSlaveFramework& fw){ glPushMatrix(); glTranslatef(0,5,0); glScalef(sizz,sizz,sizz); dawn(1); drawstars(); glPopMatrix(); glMultMatrixf(affmat); glScalef(sizz,sizz,sizz); drawall(); } #endif /*%%%%%%%%%%%%%%%%%%%%%%%%%%% end SZG %%%%%%%%%%%%%%*/ int main(int argc, char **argv){ arguments(argc,argv); if(eyes==cave) #ifdef CAVE CAVEConfigure(&argc, argv, NULL) #endif ; getmem(); dataprep(); if(eyes==cave){ #ifdef CAVE CAVEInit(); /* Each wall is (part of) a forked process from here on.*/ CAVEFrameFunction(cavetrack,0); /*is restricted to MasterWall, so once per frame */ CAVEInitApplication(drawcaveinit, 0); CAVEDisplay(drawcave, 0); while(!CAVEgetbutton(CAVE_ESCKEY)) { cavekeybo(); /* is asynchronous from display processes */ } audioclean(); CAVEExit(); #endif ;} else if(eyes==console){ /*console main*/ glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_DEPTH); switch(win) { case 0: break; case 1: glutInitWindowSize(640, 480); glutInitWindowPosition(0,1024-480); break; case 2: glutInitWindowPosition(0,0); break; } glutCreateWindow("<* illiSkel in C/OpenGL/GLUT *>"); if(win==2) glutFullScreen(); glEnable(GL_DEPTH_TEST); glutDisplayFunc(drawcons); glutKeyboardFunc(keyboard); glutSpecialFunc(special_keybo); glutMouseFunc(mousepushed); glutMotionFunc(mousemoved); glutPassiveMotionFunc(mousemoved); glutReshapeFunc(reshaped); glutIdleFunc(idle); glutMainLoop(); } else if(eyes==cube){ //syzygy main //fff = new arMasterSlaveFramework; which is new? arMasterSlaveFramework* fff = new arMasterSlaveFramework(); // if(!fff->init(argc,argv)) return 1; // fff->setInitCallback(cubeinit); fff->setStartCallback(cubeinit); // fff->setPreExchangeCallback(cubetrack); fff->setPreExchangeCallback(gesturetrack); fff->setDrawCallback(cubedraw); fff->setPostExchangeCallback(diddle); fff->setKeyboardCallback(clefs); fff->setOverlayCallback(overlay); // framework.setClipPlanes( .1, 1000 ); // framework.setEyeSpacing(6/(12*2.54)); //return framework.start() ? 0 : 1; if(!fff->init(argc,argv)) return 1; return fff->start() ? 0:1; } }