#define WIN /* 16jul bafarmer */ /*12jul gkf fix projections */ /*11jul gkf windows/unix and the marker spot */ /*gkf 9jul02 rotsphere */ /* gkf 2jul02 projection */ /****************************************************************/ /**** 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**********************************/ /******* Exercise one solved and Stuarts gadgets too ************/ /****************************************************************/ #ifdef WIN #define random rand /* for windows */ /* put this into the source code */ #pragma warning (disable:4305) /* double-to-float */ #pragma warning (disable:4101) /* unreferenced local variable */ #pragma warning (disable:4056) /* overflow in fp constant arithmetic */ #pragma warning (disable:4047) #pragma warning (disable:4024) #pragma warning (disable:4133) #endif #include #include #include #ifdef IRIX #include /* for the speedometer */ #include #endif #ifdef WIN #include /* for the speedometer */ #include #endif #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))) #ifdef WIN #define M_PI (355./113.) /*for windows*/ #endif #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)) #define VERT 6 /* global variables */ float r1, r2; /* torus radiie */ float gap, gap0=1.; /* kludge so that arguments() can set a default gap0 */ float lux[3]={1.,2.,3.}; /*world light direction vector */ float luxx[3]; /* object space direction vector*/ float amb, pwr ; /* ambient fraction, pseudo-specular power */ float mysiz,speed, torq, focal, wfar; /*console navigation variables */ int win = 1; /* 2 full screen, use 0 for demand sized */ int which ; /* a bit map for development */ unsigned int BUT, XX, YY,SHIF; /* used in chaptrack gluttery */ int xt,yt; /* once was xt,yt,xm,ym for viewportery */ int mode,morph,msg,binoc; /* pretty global */ int th0, th1, dth, ta0, ta1, dta; /* torus parameters */ #define FLYMODE (0) #define TURNMODE (1) int place; /* matrix is being rotated by the mouse */ #define AFF (0) #define SPH (1) int ii, jj, kk; float tmp, temp; /* saves gray hairs later */ float aff[16], starmat[16], mat[16]; float prj[16]= { 3,0,0,0, /* conformal projection */ 0,3,0,0, 0,0,10,-2, 0,0,-10,1}; float sph[16]; /* jms-rotate-sphere-matrix */ int binoc; /* flag */ float nose; /* to eye distance in console */ int hasnumber, number, decimal, sign ; /* for Stuart's number parser */ float vv[VERT][3]={{ 0.300775, 1.301248,-0.702434}, {-0.976281,-0.910795, 0.701983}, { 0.976171,-0.910795,-0.702076}, {-0.300495, 1.300967, 0.702620}, {-1.276451,-0.390204,-0.702474}, { 1.276282,-0.390420, 0.702384}}; float pcan[16]; /* place the can */ float ptor[16]; /* place the tor arc */ float ww[VERT][3]; float alpha; float color[3]; float lift; float aitch=1.0, kay= -2, ell = -10; int tan1,tan2,cur2; float thick; int friz; int tubed; /* whether the curves are tubed*/ int proj; /*whether you see the projection*/ char clefs[128]; /* which keys were pressed last */ /**********************************************************************/ /*** picking variables and definitions ********************************/ #define BUFSIZE 512 #define GETS(w,v) {w[0]=v[0]; w[1]=v[1]; w[2]=v[2];} int dragmode; int pCubeId; /* we picked cube number Id */ int mousePosition[3]; int zz=0; /**********************************************************************/ /* processhits - decides which object is to be the picked object */ /**********************************************************************/ void processhits(GLint numbHits, GLuint buffer[]){ GLuint biggestZ, currentZ, id; biggestZ = currentZ = id = 0; if(dragmode){ return;} /* if we have annother point selected */ if(numbHits!=0){ /* if we have a hit */ /* we know that if each object has exactly 1 name */ /* @ 4*i we have the number of names for the ith hit */ /* @ 4*i+1 we have the minZ vaule of the ith hit */ /* @ 4*i+2 we have the maxZ vaule of the ith hit */ /* @ 4*i+3 we have the name of the object we hit */ /* compare the minZ values */ biggestZ = buffer[1]; id = buffer[3]; for(ii=0; iibuffer[ii*4+1]){ biggestZ = buffer[ii*4+1]; id = buffer[ii*4+3]; } /*fprintf(stderr,"There was a hit \n");*/ pCubeId = id; } }else{ pCubeId = -1; } } /********************************************************************/ /* wherehead - determines the local coord sys for the control points*/ /********************************************************************/ void wherehead(float x,float y, float z, float *mat, float *vect){ /* solve xyz = mat*vect for vect*/ vect[0]=mat[0]*(x)+ mat[1]* (y)+ mat[2]*(z); vect[1]=mat[4]*(x)+ mat[5]* (y)+ mat[6]*(z); vect[2]=mat[8]*(x)+ mat[9]* (y)+ mat[10]*(z); } /**********************************************************************/ /* dragtrack - the picking tracker */ /**********************************************************************/ void dragtrack(int but, int xx, int yy, int shif){ float dx,dy,dz; float tempvec[3]; #define SCAL .02 dx =SCAL*(float)(xx-mousePosition[0]); /*displacement of mouse*/ dy =-1*SCAL*(float)(yy-mousePosition[1]); dz = SCAL*(float)(zz-mousePosition[2]); mousePosition[0]=xx; mousePosition[1]=yy; mousePosition[2]=zz; wherehead(dx, dy, dz, aff, tempvec); /* move the control point */ if(dragmode && pCubeId>=0){ vv[pCubeId][0] += tempvec[0]; vv[pCubeId][1] += tempvec[1]; vv[pCubeId][2] += tempvec[2]; } } /**********************************************************************/ /* drawpickedpoint - hilights the control point that is picked */ /**********************************************************************/ void drawpickedpoint(float *point){ /* input the point you picked */ glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(point[0], point[1], point[2]); glScalef(r2*1.2, r2*1.2, r2*1.2); /* slightly bigger that the corner */ glColor3f(1, 1, 0); glutSolidSphere(1, 10, 10); glPopMatrix(); } /**********************************************************************/ /* drawcontrolspheres - draws the picking spheres */ /**********************************************************************/ void drawcontrolspheres(void){ glMatrixMode(GL_MODELVIEW); glColor3f(1, 0, 0); for(ii=0; iiR^3(RGBspace */ MAX(spec, lmb*color[1]/*(.25 + ABS(cat -.5))*/), /* dog cat model of Hartman */ MAX(spec, lmb*color[2]/*(1 - cat)*/)); /* illiLight by Ray Idaszak 1989 */ glVertex3f( r1*C(th) + r2*nn[0], r1*S(th) + r2*nn[1], r2*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+gap*dth,ta); } glEnd(); } /* end for.theta loop */ } /* end drawtor */ /**********************************************************************/ void drawcube(void){ kommrusch(1,3);} /**********************************************************************/ void drawall(void){ drawtor(); /* drawcube(); */ } /**********************************************************************/ 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 */ } /************************ steering ***********************************/ void arguments(int argc,char **argv){ /* Pat Hanrahan 1989 */ while(--argc){++argv; if(argv[0][0]=='-')switch(argv[0][1]){ case 'w': win =atoi(argv[1]); argv++; argc--; 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; }}} /**********************************************************************/ /* Stuart Levy 1998 improved gadgets getnumber, bump */ /**********************************************************************/ float getnumber(float dflt){ /* dflt is an action or a constant */ if(!hasnumber)return dflt; /* in case no number to put in */ tmp = sign ? -number : number; return decimal>0 ? tmp/(float)decimal : tmp ; } /**********************************************************************/ void bump(float *val, float incr){ /* use bump(&nose, .01) for example */ float abs = fabs(incr); char frmt[8], code[32]; int digits = 1; if(hasnumber){ *val = getnumber(0); return; } if(abs <= .003) digits=3; else if(abs <= .03) digits=2; sprintf(frmt, "%%.%de" , digits); sprintf(code, frmt, incr >0 ? (*val)*(1+abs):(*val)/(1+abs)); sscanf(code, "%f", val); } /********************from SLevy 2jan02 ********************************/ int getbutton(char key) { int uu = clefs[key & 127]; clefs[key & 127]=0; return uu; } /**********************************************************************/ void keyboard(unsigned char key, int x, int y){ clefs[key&127]=1; /* globalize the keys that were pressed */ #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) = getnumber(1-(flg));} #define CYCLE(K,f,m) PRESS((K), \ getnumber((f)=(((f)+(m)-1)%(m))), getnumber((f)=(++(f)%(m)))) /* Only ASCII characters can be processes by this GLUT callback function */ IF(27)exit(0); /* ESC exit */ TOGGLE('v',binoc); /* cross-eyed STEREO */ /* CYCLE(' ', mode,TURNMODE+1); /* fly/turn modes */ #if 0 /* TOGGLE('h',morph); /* autotymer on/off */ #endif TOGGLE('w',msg); /* writing on/off */ TOGGLE('f',friz); /* firz on/off */ TOGGLE('d',tubed); /*whether curves are tubed*/ TOGGLE('y',proj); /*shpere or projection*/ PRESS('n', bump(&nose, -.001), bump(&nose,.001)) /* for binoculars */ PRESS('s', bump(&speed,-.02), bump(&speed,.02)) /* flying speed */ PRESS('q', bump(&torq, -.02), bump(&torq,.02)) /* turning speed */ PRESS('o', bump(&focal,-.1) , bump(&focal,.1)) /* telephoto */ /* CYCLE('y',which,3) /* what you see */ PRESS('i', bump(&mysiz,-.1) , bump(&mysiz, .1)) /* rescale the world */ /* PRESS('p', bump(&wfar, -.01) , bump(&wfar, .01)) /* rear clipping plane */ TOGGLE(' ', place) /* AFF or SPH */ PRESS('z', deFault(), deFault()) /* zap changes */ PRESS('g',bump(&gap, -.1), bump(&gap,.1)) /* gap parameter */ PRESS('a',bump(&amb, -.1), bump(&amb,.1)) /* ambient fraction */ PRESS('r',bump(&pwr, -.1), bump(&pwr,.1)) /* pseudo-spec power */ PRESS('u',bump(&r2, -.1), bump(&r2,.1)) /* thickness of tor */ /* PRESS('u',bump(&thick, -.1), bump(&thick,.1)) /*thickness of tubes*/ PRESS('t',bump(&alpha, -.01), bump(&alpha,.01)) /*transparency*/ PRESS('h',bump(&aitch, -.01), bump(&aitch,.01)) PRESS('k',bump(&kay, -.01), bump(&kay,.01)) PRESS('l',bump(&ell, -.01), bump(&ell,.01)) IF(','){tan1=1-tan1;} /*1st tangent visible*/ IF('<'){tan2=1-tan2;} /*2nd tangent visible*/ IF('>'){cur2=1-cur2;} /*2-curve visible*/ updateprojector(); /*this part doesn't work yet:*/ if(key=='y') if(proj==1) { focal=.41; alpha=0; glTranslatef(0,0,100); } else { focal=2; alpha=1; glTranslatef(0,0,-100); } /* Stuart Levy's gadget parser from avn.c */ if(key >= '0' && key <= '9'){ hasnumber = 1; number = 10*number + (key - '0'); decimal *= 10;} else if(key == '.'){ decimal = 1;} else if(key == '-'){ sign = -1;} else {hasnumber = number = decimal = sign = 0;} glutPostRedisplay(); } /**********************************************************************/ void special_keybo(int key, int x, int y){ clefs[0]= key ; switch(key){ /* HOME END PAGE_DOWN RIGHT F1 etc see glut.h */ case GLUT_KEY_F1: th0++; th1--; break; case GLUT_KEY_F2: th0--; th1++; break; /* default: fprintf(stderr,"non-ASCII char [%d] pressed.\n", key); */ } hasnumber=number=decimal=0; glutPostRedisplay(); } /**********************************************************************/ #if 0 /**********************************************************************/ 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"); } #endif /**********************************************************************/ #ifdef WIN 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 /**********************************************************************/ #ifdef IRIX 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 /**********************************************************************/ void char2wall(float x,float y,float z, char buf[]){ char *p; glRasterPos3f(x,y,z); for(p = buf;*p;p++) glutBitmapCharacter(GLUT_BITMAP_9_BY_15,*p); } /**********************************************************************/ void messages(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(place==AFF) glColor3f(1.,0.,1.); else glColor3f(1.,1.,.0); LABEL2(1500,1500,"%s","o"); /* writings */ if(place==AFF) 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 (W)riting", mode?"FLYING":"CONTROL"); LABEL2(10,10,"illiTantrix \ by Y. Malysheva, A. Chatwani, E. Denne, U Illinois, 2002 %s",""); LABEL2(80,2770,"(N)ose %0.3f",nose); LABEL2(80,2700,"(S)peed %0.3f",speed); LABEL2(80,2630," tor(Q) %0.3f",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 %0.3f",mysiz); /* LABEL2(80,2350,"wfar cli(P)er= %0.3f",wfar); */ LABEL2(80,2280,"(Z)ap %s",""); LABEL2(80,2210,"(G)ap %0.3f",gap); LABEL2(80,2140,"(A)mb %0.3f",amb); LABEL2(80,2070,"pw(R) %0.3f",pwr); LABEL2(80,930,"tube rad(U) %0.3f",r2); LABEL2(80,860,"tube(D) curves %i",tubed); LABEL2(80,790,"(T)ransparency %0.3f",alpha); LABEL2(80,720,"(F)riz %i",friz); LABEL2(80,650,"(P)lace %i",place); LABEL2(80,570,"tantrix(,) %i",tan1); LABEL2(80,500,"tantrix 2(<) %i",tan2); LABEL2(80,430,"two curve(>) %i",cur2); LABEL2(80,360,"curve projection: %s",""); LABEL2(80,290,"(H)h = %0.3f",aitch); LABEL2(80,220,"(K)k = %0.3f",kay); LABEL2(80,150,"(L)l = %0.3f",ell); LABEL2(80,80,"(Y)which = %i",which); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); } /**********************************************************************/ void chaptrack(int but,int xx,int yy,int shif){ long dx,dy; if(friz) return; dx = xx -.5*xt; dx = abs(dx)>1?dx:0; dy = yy -.5*yt; dy = abs(dy)>1?dy:0; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); if(mode==TURNMODE) glTranslatef(aff[12],aff[13],aff[14]); glRotatef(dx*torq,0.,1.,0.); glRotatef(dy*torq,1.,0.,0.); if(but&(1<5?dx:0; dy = yy -.5*yt; dy = abs(dy)>5?dy:0; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); if(mode==TURNMODE) glTranslatef(sph[12],sph[13],sph[14]); glRotatef(dx*torq,0.,1.,0.); glRotatef(dy*torq,1.,0.,0.); if(but&(1<0) { glColor3f(1,.1,.15); color[0]=1;color[1]=.1; color[2]=.15; garc(ww[ii], ww[(ii+1)%VERT]); /* great arc */ } if(tan2>0) { glColor3f(1,.4,.1); color[0]=1; color[1]=.4;color[2]=.1; for(jj=0; jj<3; jj++) { u[jj]=-ww[ii][jj]; v[jj]=-ww[(ii+1)%VERT][jj]; } garc(u,v); } } } /**********************************************************************/ void IIcurve() { int i,j,m; float normal[3]; float A[3], B[3], C[3], D[3], E[3], F[3], *A_cross_B, *D_cross_E; float prev_x, prev_y, prev_z, next_x, next_y, next_z, curr_x, curr_y, curr_z; float dot, theta, dtheta; float perp[3]; float denom; float x1,x2,x3,y1,y2,y3,z1,z2,z3; int counter = 0; float vector1[3], vector2[3], vector3[3], vector4[3]; /*get all the vertices and all of the lines*/ for(i= 0; i < VERT; i++){ for(j = (i+2); j%VERT != (i+VERT-2)%VERT; j++){ /* Store v(i), v(i-1), and v(i+1) */ curr_x = vv[i][0]; curr_y = vv[i][1]; curr_z = vv[i][2]; prev_x = vv[(i+VERT-1)%VERT][0]; prev_y = vv[(i+VERT-1)%VERT][1]; prev_z = vv[(i+VERT-1)%VERT][2]; next_x = vv[(i+1)%VERT][0]; next_y = vv[(i+1)%VERT][1]; next_z = vv[(i+1)%VERT][2]; /* Calculate vectors to use to calculate if v(i-1) and v(i+1) are on plane */ A[0] = prev_x - curr_x; A[1] = prev_y - curr_y; A[2] = prev_z - curr_z; B[0] = vv[j%VERT][0] - curr_x; B[1] = vv[j%VERT][1] - curr_y; B[2] = vv[j%VERT][2] - curr_z; C[0] = vv[(j+1)%VERT][0] - curr_x; C[1] = vv[(j+1)%VERT][1] - curr_y; C[2] = vv[(j+1)%VERT][2] - curr_z; D[0] = next_x - curr_x; D[1] = next_y - curr_y; D[2] = next_z - curr_z; E[0] = vv[j%VERT][0] - curr_x; E[1] = vv[j%VERT][1] - curr_y; E[2] = vv[j%VERT][2] - curr_z; F[0] = vv[(j+1)%VERT][0] - curr_x; F[1] = vv[(j+1)%VERT][1] - curr_y; F[2] = vv[(j+1)%VERT][2] - curr_z; /* Begin taking determinant of matrices with cross project of top two rows, dot the 3rd row */ A_cross_B = calloc(3, sizeof(float)); D_cross_E = calloc(3, sizeof(float)); A_cross_B = cross(A, B); D_cross_E = cross(D, E); /* if both determinants have the same sign, then on the same side of the plane, so draw */ if (((DOT(A_cross_B, C)) * (DOT(D_cross_E, F))) > 0){ /* calculate vectors for great arc */ vector1[0] = vv[j%VERT][0] - vv[i][0]; vector1[1] = vv[j%VERT][1] - vv[i][1]; vector1[2] = vv[j%VERT][2] - vv[i][2]; denom = sqrt(vector1[0]*vector1[0] + vector1[1]*vector1[1] + vector1[2]*vector1[2]); vector1[0] = vector1[0]/denom; vector1[1] = vector1[1]/denom; vector1[2] = vector1[2]/denom; vector2[0] = vv[(j+1)%VERT][0] - vv[i][0]; vector2[1] = vv[(j+1)%VERT][1] - vv[i][1]; vector2[2] = vv[(j+1)%VERT][2] - vv[i][2]; denom = sqrt(vector2[0]*vector2[0] + vector2[1]*vector2[1] + vector2[2]*vector2[2]); vector2[0] = vector2[0]/denom; vector2[1] = vector2[1]/denom; vector2[2] = vector2[2]/denom; /* vectors for antipodal two curve */ vector3[0] = -vector1[0]; vector3[1] = -vector1[1]; vector3[2] = -vector1[2]; vector4[0] = -vector2[0]; vector4[1] = -vector2[1]; vector4[2] = -vector2[2]; glColor3f(0,0,1); color[0] = 0; color[1] = 0; color[2] = 1; garc(vector2, vector1); garc(vector3, vector4); } } } } /**********************************************************************/ void drawbox(float *matr) { glColor3f(1,1,1); glBegin(GL_LINE_STRIP); glVertex3f(0,0,0); glVertex3f(matr[0],matr[1],matr[2]); glVertex3f(matr[0]+matr[4],matr[1]+matr[5],matr[2]+matr[6]); glVertex3f(matr[0]+matr[4]+matr[8],matr[1]+matr[5]+matr[9],matr[2]+matr[6]+matr[10]); glVertex3f(matr[0]+matr[8],matr[1]+matr[9],matr[2]+matr[10]); glVertex3f(matr[8],matr[9],matr[10]); glVertex3f(matr[4]+matr[8],matr[5]+matr[9],matr[6]+matr[10]); glVertex3f(matr[4],matr[5],matr[6]); glVertex3f(0,0,0); glEnd(); } /**********************************************************************/ void spot(float *n) { float lmb,spec,grey; lmb = DOT(n,luxx); lmb =(lmb<0 ? .2 : lmb); lmb = MAX(amb, lmb); spec = CLAMP((1.1 - pwr+pwr*lmb), 0., 1.); grey=MAX(spec,lmb*.8); glColor4f(grey*color[0],grey*color[1],grey*color[2],alpha); glVertex3fv(n); } /**********************************************************************/ void drawball() { float u,v; float n[3],m[3]; for(u=0; u<361;u+=30) { glBegin(GL_TRIANGLE_STRIP); for(v=-90; v<91;v+=15) { n[0]=C(u)*C(v); n[1]=S(u)*C(v); n[2]=S(v); m[0]=C(u+30)*C(v); m[1]=S(u+30)*C(v); m[2]=S(v); spot(n); spot(m); } glEnd(); } } void drawsphere() { if(which==0)drawdot(0,1,0); if(alpha==1) { glColor4f(1,1,0,alpha); color[0]=1;color[1]=1;color[2]=.1; drawball(); tantrix(); if(cur2>0) { IIcurve(); } } else if(alpha==0) { glColor3f(1,.1,.1); tantrix(); if(cur2>0) { IIcurve(); } } else { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glClear(GL_COLOR_BUFFER_BIT); glColor4f(1,1,.1,alpha); color[0]=1;color[1]=1;color[2]=.1; drawball(); glDisable(GL_BLEND); tantrix(); if(cur2>0) { IIcurve(); } } } /**********************************************************************/ void trot(float a[3], float b[3]) { int ii; float tt[3],nn[3],bb[3];/*tangent, normal, binormal - rot. frame*/ float dot; float v2[3];/*temp. for new vertex*/ for(ii=0; ii<3; ii++) pcan[ii]=tt[ii]=(b[ii]-a[ii])/sqrt((b[0]-a[0])*(b[0]-a[0]) +(b[1]-a[1])*(b[1]-a[1]) +(b[2]-a[2])*(b[2]-a[2])); if(tt[1]==0&&tt[2]==0)/*if tt is parallel to i=(1,0,0)*/ { nn[0]=nn[2]=0;/*(then then normal can be j and binormal k)*/ nn[1]=1; bb[0]=bb[1]=0; bb[2]=tt[0]; } else /*otherwise we can take cross product of i and tt*/ { dot=sqrt(tt[1]*tt[1]+tt[2]*tt[2]); nn[0]=0; nn[1]=tt[2]/dot; nn[2]=-tt[1]/dot; /*bb=tt cross nn*/ bb[0]=tt[1]*nn[2]-tt[2]*nn[1]; bb[1]=tt[2]*nn[0]-tt[0]*nn[2]; bb[2]=tt[0]*nn[1]-tt[1]*nn[0]; } for(ii=0; ii<3; ii++) { pcan[4+ii]=nn[ii]; pcan[8+ii]=bb[ii]; pcan[12+ii]=a[ii]; pcan[(ii+1)*4-1]=0; } pcan[15]=1; glMultMatrixf(pcan); } /**********************************************************************/ void drawcyll(float *a, float *b) { float theta, length, vertex[3]; length=sqrt((b[0]-a[0])*(b[0]-a[0]) +(b[1]-a[1])*(b[1]-a[1]) +(b[2]-a[2])*(b[2]-a[2])); glPushMatrix(); glPushMatrix(); glTranslatef(a[0], a[1], a[2]); glScalef(r2,r2,r2); drawball(); glPopMatrix(); trot(a,b); glScalef(length,r2,r2); glBegin(GL_TRIANGLE_STRIP); for(theta=0; theta<(2*(3.14)+.2); theta+=((3.142)/4)) { vertex[0]=0;vertex[1]=cos(theta);vertex[2]=sin(theta); spot(vertex); vertex[0]=1;vertex[1]=cos(theta);vertex[2]=sin(theta); glVertex3fv(vertex); } glEnd(); glPopMatrix(); } /**********************************************************************/ void drawknot() { int ii; glColor3f(.2,1,.5); color[0]=.2;color[1]=1; color[2]=.5; for(ii=0; ii"); 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(); }