// for szg-1.1 //znail without the governor 9jun07 /* eyes == cube by default */ /*4jun04: caution: znail -c is now console, not cube !*/ /* 18may04 easyznail uses Ben's pre-compiled libraries */ /* some fixes 12may attempted on fire*/ /* resume 8may in CUBE on fire alone */ /* ok spirit g++ worked but ISL windows can't find gl/glut.h /* compile shit from the g++ compiler on spirit 3may04*/ /* znail.cpp works on my Tecra, does not compile on Spirit */ /* second base, get something seeable */ /* resumed 1may04 with Stan Blank scaffolding*/ /* syzygy begun 29jun03 */ /* modified to run on WindowsNT gkf 23feb98 */ /* znail.cpp for syzygy */ //#define SYZYGY //#ifdef SYZYGY for later #include "arPrecompiled.h" //must be the first line #include "arMasterSlaveFramework.h" #define UNIX // #ifdef UNIX // #include // dual compile issue here // #endif // #ifdef WIN32 #include // #endif // arMatrix4 affmat; //not used for now // Stan needs in his preexchage // GLint but1, but2, but3; /*****************************/ int gesture; float eps; float del; int resethand; #include #include #include #include #include #ifdef WIN32 #include // #include #endif #include #ifdef SOUND /* #include */ #include #include "vssClient.h" #endif #ifdef CAVE #include #include #endif /* Examples of useful geometric macros, use inliners in C++ */ #define MAX(x,y) (((x)<(y))?(y):(x)) #define MIN(x,y) (((x)<(y))?(x):(y)) #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 CLAMP(x,u,v) (xv ? v: x)) #define fabsf(x) (((x)<0)?-(x):(x)) #define random rand #define M_PI 3.1415926 #define DG M_PI/180 #define S(u) sin(u*DG) #define C(u) cos(u*DG) #define GOVERNOR 2 /* global variables ... add new ones on top of the stack */ char which[20]; /* audio needs this */ int delta; /* new variables for autotymer to change torus */ float gap0=1.; /*very bad kludge ... for letting arguments reset default gap value */ int audiohandle; /* for telling vss the name of the .aud file */ float lux[3]={1.,2.,3.}; /*light source direction vector */ float luxx[3]; //somehow forgot this float mysiz,speed, torq, focal, Far; /*console navigation variables */ int win = 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 */ enum {console, cave, cube} eyes; #define caveyes (eyes==cave) /* to make opengl_stars.c work */ // int caveyes=0; /* rename? ----------> caveflag */ int mode,morph,msg,binoc; /* pretty global */ /* note mode, alfa, beta, lima DO need to be shared to make autotymer right */ #define FLYMODE (0) #define TURNMODE (1) /*%%%%%%%%%%%%%%%%%%%%%%%%%%snailvars%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ static float dth,cdth, fdth, dta,cdta,fdta; static float amb,pwr; /*%%%%%%%%%%%%%%%%%%%%%%%%%%snailvars%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*Shared memory variables as per Stuart Levy 1994 */ struct share_var{ int s_mode ; /* because drawhoop uses it to change color */ float s_alfa ; /* because autotymer changes these display vars */ float s_beta ; float s_lima ; float s_one ; float s_two ; float s_tri ; float s_th0 ; float s_th1 ; float s_ta0 ; float s_ta1 ; float s_gap ; float s_sizz ; /*final scaling factor before projection */ int s_wnd; /*wand or maus flag */ int s_gnd; /*background color */ float s_luxx[3]; /* current light direction */ int s_mauspaw ; /*binary for mouse button state */ GLfloat s_affmat[16],s_starmat[16]; /*affine matrices for object, stars*/ } *s_var; #define mode (s_var->s_mode) #define alfa (s_var->s_alfa) #define beta (s_var->s_beta) #define lima (s_var->s_lima) #define one (s_var->s_one) #define two (s_var->s_two) #define tri (s_var->s_tri) #define th0 (s_var->s_th0) #define th1 (s_var->s_th1) #define ta0 (s_var->s_ta0) #define ta1 (s_var->s_ta1) #define gap (s_var->s_gap) #define sizz (s_var->s_sizz) #define wnd (s_var->s_wnd) #define gnd (s_var->s_gnd) /* use only if printframe function is present */ #define lu (s_var->s_lu ) /* else the right wall isn't specularized */ #define affmat (s_var->s_affmat) #define starmat (s_var->s_starmat) #define mauspaw (s_var->s_mauspaw) /* these are used only in console mode */ float nose; /* to eye distance in console */ 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);} } //---------------------szg-------------------------- // #ifdef SYZYGY //why doesn't this flag work? why is this here bool cubeinit(arMasterSlaveFramework& fw, arSZGClient& ){ //there used to be the name "ben" but Stan hasn't ... ugly! //that this function needs to know how it will be called ar_setNavMatrix(ar_translationMatrix(0,-5,0)); //initial position glEnable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); /* what if we don't ? */ //this is how Syzygy does shared memory. 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("mode", (&mode), AR_INT, 1); fw.addTransferField("luxx", luxx, AR_FLOAT, 3); fw.addTransferField("mauspaw", &mauspaw, AR_INT, 1); fw.addTransferField("th0", (&th0), AR_INT, 1); fw.addTransferField("th1", (&th1), AR_INT, 1); fw.addTransferField("ta0", (&ta0), AR_INT, 1); fw.addTransferField("ta1", (&ta1), AR_INT, 1); fw.addTransferField("lima", (&lima), AR_FLOAT, 1); fw.addTransferField("one", (&one), AR_FLOAT, 1); fw.addTransferField("beta", (&beta), AR_FLOAT, 1); fw.addTransferField("gap", (&gap), AR_FLOAT, 1); fw.addTransferField("morph", (&morph), AR_INT, 1); return true; } // #endif void char2wall(GLfloat x,GLfloat y, GLfloat z, char buf[]){ char *p; glRasterPos3f(x,y,z); for(p = buf;*p;p++) glutBitmapCharacter(GLUT_BITMAP_9_BY_15,*p); } void autotymer(int); /* to allow deFault to call the autotymer later */ void deFault(void){ int ii; float tmp; msg=1; binoc=0; nose=.06; mauspaw = 0; wnd = 1; sizz = 12.; mode=TURNMODE; speed=.003; torq=.0006; focal = 2.; Far =13.; mysiz=.01; morph=0; for(ii=0;ii<16;ii++) starmat[ii]=affmat[ii] = (ii/4==ii%4) ? 1 : 0; tmp=NRM(lux); for(ii=0;ii<3;ii++)lux[ii]/=tmp; if(eyes==cave){affmat[12]=0; affmat[13]= 5; affmat[14]= -5 ; } if(eyes==cube){affmat[12]=0; affmat[13]= 0; affmat[14]= 0 ; } if(eyes==console){affmat[12]=0; affmat[13]= 0; affmat[14]= -4.2;} /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%snailstuff%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /* ftym = 0 is ok */ /* surface patch */ alfa = 2; beta = 1; lima=0.; gap = 1; th0 = 90 ; th1 = 269; cdth=10; fdth= 6; ta0 = 90 ; ta1 = 270; cdta=10; fdta= 6; dta = fdta; dth = fdth; /* initial quaternion */ one = -45. ; two =0; tri =0.; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%snailstuff%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ gesture=0; eps=0.002; //hand rotation gesture attenuation del=0.02; //hand translation gesture attenuation resethand=0; autotymer(1); /* reset autotymer to start at the beginning */ } /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%snailfrag%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ void snailvert(float *vv, float th, float ta, int again ) { float li, tw, tmp, tmp1, tmp2, pp[4]; int ii,jj; static int first; static float C0, S0; static float C1, S1, C2, S2, C3, S3,lrp1,lrp2,lrp3; first = again; if(first){ /* these are constant for one full tope of the surface */ first=0; C0=C(lima); S0=S(lima); /*the trigs made a big difference */ C1=C(one); S1=S(one); C2=C(two); S2=S(two); C3=C(tri); S3=S(tri); lrp1 = (1.- .5*S(lima*2.))*(1. - .293*(one+45.)/(-45.) ); lrp2 = (1. + .414*(one+45.)/(-45.) ); lrp3 = (1. + .67*(one+45.)/(-45.) ); /*these algs didn't make any */ } li = C0 - S0*C(ta); /* limaconic homotopy */ pp[1] = C(alfa*th)*C(ta)*li*lrp1; /* Sudanese Moebius Band */ pp[2] = S(alfa*th)*C(ta)*li*lrp1; /* Dan Asimov, ca 1980*/ pp[3] = C(beta*th)*S(ta)*li*lrp2; /* Larry Siebenmann, 1982 */ pp[0] = S(beta*th)*S(ta)*li*lrp2; /* Blaine Lawson, 1972 */ tmp = pp[0]; /*turn(pp,0,1,one),turn(pp,0,2,two),turn(pp,0,3,tri); */ tmp1 = tmp *C1 - S1*pp[1]; tmp2 = tmp1 *C2 - S2*pp[2]; pp[0] = tmp2 *C3 - S3*pp[3]; pp[1] = pp[1]*C1 + S1*tmp ; pp[2] = pp[2]*C2 + S2*tmp1 ; pp[3] = pp[3]*C3 + S3*tmp2 ; vv[0] = pp[1]*lrp3*7./(10.+9.*pp[0]); /* project from 4D to 3D */ vv[1] = pp[2]*lrp3*7./(10.+9.*pp[0]); vv[2] = pp[3]*lrp3*7./(10.+9.*pp[0]); } void drawsnail(void) { float th,ta; float vv[3], aa[3], vo[3], nn[3], lmb; float spec, dog, cat, rr, gg, bb ; snailvert(vo,th0,ta0,1); /* first */ for(th=th0; th < th1; th += dth) { /* bgntmesh(); */ glBegin(GL_TRIANGLE_STRIP); snailvert(vo,th,ta0+dta,0); ta=ta0; while(1) { snailvert(vv,th,ta,0 ); /* normal on vo aa vv */ snailvert(aa,th+dth-gap,ta,0); 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); lmb = fabsf(lmb); spec = MIN(1, 1*(1-10+10*lmb)); dog = (ta-ta0)/(float)(ta1-ta0); cat = (th-th0)/(float)(th1-th0); gg = MAX(lmb*dog ,spec); rr = MAX(lmb*(.25 + fabsf(cat -.5)),spec); bb = MAX(lmb*(1 - cat ) ,spec); /*RGBcolor((short)(255.*rr),(short)(255.*gg),(short)(255.*bb));*/ glColor3f( rr, gg, bb ); /* v3f(vv); v3f(aa); */ glVertex3fv(vv); glVertex3fv(aa); vo[0]=vv[0]; vo[1]=vv[1]; vo[2]=vv[2]; if (ta >= ta1) break; ta += dta; if (ta > ta1) ta=ta1; } /* end while */ /* endtmesh(); */ glEnd(); } /* end for theta */ } void drawhoop(float ta, float dt) { float yy, th, lmb,spec; static int imax; static float vv[3],aa[3],vo[3],nn[3]; glBegin(GL_TRIANGLE_STRIP); snailvert(vo,th0+dth,ta,1); for(th=th0;thR^3(RGBspace */ MAX(lmb*(.25 + fabsf(cat -.5)),spec), /* dog cat model of Hartman */ MAX(lmb*(1 - cat ),spec)); /* illiLight by Ray Idaszak 1989 */ glVertex3f(C(th) + .5*nn[0],S(th) + .5*nn[1],.5*nn[2]); } 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+gap*dth,ta); } glEnd(); } } void drawall(void){ drawtor(); } #endif /* blankout torus */ #include "dawn.c" #include "opengl_stars.c" #if 0 void drawstars(void){ int i; static float star[1000][3]; static int virgin=1; if(virgin){ int ii,jj; float fact; virgin=0; for(ii=0;ii<1000;ii++) { for(jj=0;jj<3;jj++) star[ii][jj] = random()/(float)0x40000000-1.; if(eyes==cave){ fact = 90./NRM(star[ii]); for(jj=0;jj<3;jj++) star[ii][jj] *= fact; } } } glMatrixMode(GL_MODELVIEW); glPushMatrix(); glMultMatrixf(starmat); glColor3f(1.0,1.0,0.0); glBegin(GL_POINTS); for(i=0;i<1000;i++) glVertex3fv(star[i]); glEnd(); glPopMatrix(); glClear(GL_DEPTH_BUFFER_BIT); } #endif void audioprep(void){ #ifdef SOUND if (!FBgnSoundServer()) fprintf(stderr,"UDP connection to sound server failed\n"); else if ((audiohandle = AUDinit("noosh.aud")) == -1) fprintf(stderr,"Couldn't open noosh.aud\n"); #endif } void dohoot(void) {strcpy(which,"hoot");} void dotrump(void){strcpy(which,"trump");} void doflute(void){strcpy(which,"flute");} void dodrum(void) {strcpy(which,"drum");} void audiofunc(void){ #ifdef SOUND #define LIRP(X,A,B,x,a,b) (X = A + (x-a)*(B-A)/(b-a)) static float freq=440., ampl=1., indx=20., cmra=2.; static float data[4]; static omode =0; static ofocal = 0; static beep =0; /* the sound server */ if(omode > mode){dohoot(); beep = 1;} if(omode < mode){dodrum(); beep = 1;} LIRP(freq, 440, 1760, th0, 10, 170); /* frequeny mimics th1 */ LIRP(indx, 10, 1, focal, .03, 2.0); /* index mimics focal */ if(ofocal != focal){dodrum(); beep = 1;} /* there is an fp bug here */ if(beep){data[0] = freq; /* pitch in Herz */ data[1] = ampl; /* the sum of all amplitudes must be < 1.0 */ data[2] = indx; data[3] = cmra; AUDupdate(audiohandle, which, 4, data); /* send message to vss */ beep = 0; } omode = mode; ofocal = focal; #endif } void audioclean(void){ #ifdef SOUND AUDterminate(audiohandle); EndSoundServer(); #endif } void arguments(int argc,char **argv){ /* Pat Hanrahan 1989 */ eyes=cube; //as default in the Portal 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 'g': gap0 =atof(argv[1]); argv++; argc--; break; case 'L': lux[0]=atof(argv[1]); lux[1]=atof(argv[2]); lux[2]=atof(argv[3]); argv +=3; argc -=3; break; }}} void dataprep(void){ audioprep(); deFault(); initstars(); } void autotymer(int reset){ #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( snl2mob,72, ta0++; ta1--) /*shrink snail to moebius*/ TYME( mob2snl,72, ta0--; ta1++) /*grow moebius to snail*/ TYME( snl2xcp,90, lima++ ) /*curlup to crosscap*/ TYME( xcp2rom,45, one--) /*swim to roman */ TYME( romdwll,20, ) /*dwell on roman */ TYME( rom2xcp,45, one++) /*swim from roman */ TYME( xcp2snl,90, lima--) /*uncurl from crosscap*/ TYME( snl2mob,72, ta0++; ta1--) /*shrink to moebius */ TYME( twist ,100, beta += .01 ) /*twist to annulus ===== it doesnt do this*/ TYME( ann2tor,66, ta0--; ta1++) /*grow annulus to torus*/ TYME( tordwll,20, ) /*dwell on torus */ TYME( tor2ann,66, ta0++; ta1--) /*shrink from torus*/ TYME( twist, 100, beta += .01 ) /*twist to moebius*/ TYME( mob2box,66,ta0--; ta1++ ) /*grow to knotbox*/ TYME( boxdwll,20, ) /*dwell on knotbox*/ TYME( box2mob,66,ta0++; ta1-- ) /*shrink0 from knotbox */ TYME( untwist,200, beta -= .01 ) /*untwist all the way*/ TYME( mob2snl,72, ta0--; ta1++) /*grow to snail */ TYME( snldwll,20, ) /*dwell on snail */ TYME(finish , 1 , first = 1 ) /*da capo */ first = 0; Break: ; /*yes Virginia, C has gotos */ }/*end autotymer*/ /*Beware of competing keys in CAVEsimulation and wnd==1 */ /* you may want to remap these keys to avoid the conflict */ 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 */ TOGGLE('v',binoc); /* cross-eyed STEREO */ TOGGLE('w',msg); /* writing on/off */ TOGGLE('h',morph); /* autotymer on/off */ PRESS('n', nose -= .001 , nose += .001 ); /* for binoculars */ CYCLE('m', mode,TURNMODE+1); /* fly/turn modes */ //temporary, m for bar due to cube simulator confusion PRESS('i', mysiz /= 1.1, mysiz *= 1.1) /* rescale the world */ PRESS('o', focal *= 1.1 , focal /= 1.1) /* telephoto */ PRESS('p', Far *= 1.01 , Far /= 1.01) /* rear clipping plane */ PRESS('s',speed /= 1.02, speed *= 1.02); /* flying speed */ PRESS('q',torq /= 1.02, torq *= 1.02); /* turning speed */ PRESS('g',gap /= .99, gap *= .99); /* gap parameter */ PRESS('z', deFault(), deFault()); /* zap changes */ IF(27) {audioclean(); exit(0); } /* ESC exit */ } void clefs(arMasterSlaveFramework& , unsigned char key, int x, int y){ keyboard(key,x,y); } 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"); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ #ifdef CAVE /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ void cavekeybo(void){ #define CAVEIF(K) if(CAVEgetbutton(K)) #define CAVEPRESS(K,A,b) CAVEIF(K){if(CAVEgetbutton(CAVE_LEFTSHIFTKEY)||\ CAVEgetbutton(CAVE_RIGHTSHIFTKEY)){b;}else{A;}} #define CAVETOGGLE(K,flg) CAVEIF(K){(flg) = 1-(flg); } #define CAVECYCLE(K,f,m) CAVEPRESS((K),(f)=(((f)+(m)-1)%(m)),(f)=(++(f)%(m)) ) #define CAVESLIDI(K,f,m,M) CAVEPRESS(K,(--fM?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 */ } //for CAVE, cube and console use postit void graffiti(void){ /* used to be called speedo */ char buf[256]; /*postit 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(!CAVEMasterWall()) return; /* USE CAVEMasterWall in papeBeta */ if(floor(2.*(*CAVETime))>floor(2.*last)){ /* rationalize this */ last=*CAVETime; fps=*CAVEFramesPerSecond; } if(mode==TURNMODE){ glColor3f(1.,0.,1.); LABEL3(-3.8,1.,-5.0,\ " click 4=auto 2=mode 1=freeze 2+3=shrink\ 2+6=grow 1+5=gap 1+3=close %s",""); } else { glColor3f(1.,1.,0.); LABEL3(-3.8,1.0,-5.0, " push thumb-button to fly, 2=tractor 7=reset %s",""); } LABEL3(-4.8,7.0,-5.0, "illiSnail \ by Francis, Hartman & Chappell, (C) 1994..1997 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, joy = 0, friz; 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*/ 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 != 1 && paw == 1)friz = 1-friz; /* parking option */ if(opaw==1 && paw == 5)gap *= 1.2; /* hold right and */ if(opaw==1 && paw == 3)gap /= 1.2; /* +left -mid */ } if (opaw != 4 && paw == 4)morph = 1-morph;/* shape changer */ 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){ /* if not parked */ glRotatef(rol*(mode?torq:-torq),0.,0.,1.); glRotatef(ele*-torq, 1.,0.,0.); glRotatef(azi*-torq,0.,1.,0.); } if(joy&&((fabsf(CAVE_JOYSTICK_Y)>.02)||(fabsf(CAVE_JOYSTICK_X)>.02))) glTranslatef(CAVE_JOYSTICK_X*speed,0.,CAVE_JOYSTICK_Y*speed); 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(); } 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 #ifdef UNIX 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); } #endif #ifdef WIN32 float speedometer(void){ /* this one is for win32*/ double dbl; static double rate; static int ii=0; static struct _timeb lnow, lthen; if(++ii % 8 == 0){ /* 8 times around measure time */ _ftime(&lnow); dbl = (double)(lnow.time - lthen.time) +(double)(lnow.millitm - lthen.millitm)/1000; lthen = lnow; rate = 8/dbl; } return((float)rate); } #endif void postit(void){ char buf[256]; /* console postit 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 ) %s(M)ode (H)omotopy (W)riting", mode?"TURN":"FLY"); LABEL2(10,10,"illiSnail 11jun07\ by Francis, Bourd, Hartman & Chappell, U Illinois, 1995..2008 %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); 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<0?click-1:GOVERNOR;} glutPostRedisplay(); /*redraw the window*/ chaptrack(BUT,XX,YY,SHIF); audiofunc(); } void mousepushed(int but,int stat,int x,int y){ if(stat==GLUT_DOWN) BUT |= (1< 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){ //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); } 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=1-gesture; //{C}button=Portal(R) if(obutn[4]==0 & butn[4] == 1) mode=1-mode; //{Y}button if(obutn[5]==0 & butn[5] == 1) deFault(); //{Z}button {static int click=GOVERNOR; if(morph&&click==0)autotymer(0); click=click>0?click-1:GOVERNOR;} 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 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; {static int gov = GOVERNOR; if(morph&&gov==0)autotymer(0); gov= gov>0?gov-1:GOVERNOR;} } #endif void cubecleanup(arMasterSlaveFramework&) { //now we want to do any calculations that would rely on the shared stuff // return true; } 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 void overlay(arMasterSlaveFramework&){ postit(); } //----------------------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->setInit(cubeinit); fff->setStartCallback(cubeinit); // fff->setPreExchangeCallback(cubetrack); fff->setPreExchangeCallback(gesturetrack); fff->setPostExchangeCallback(cubecleanup); fff->setDrawCallback(cubedraw); 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; } }