/* solo 17may2K*/ /* rembrandt style multisamping and texture caching */ /* thicker lines for the mesh */ /* grey sky */ /* netlens.c: CAVE2CAVE version of voodoo.c ---in process, JSE 4/30/99 */ #include /*#include */ #include #include #include #include #include #ifdef CAVE #include #include #endif #ifdef SOUND #include #include "vssClient.h" #endif /* texture.c - by David Blythe, SGI */ /* read_texture is a simplistic routine for reading an SGI .rgb image file. */ #include #include #include /* extern int caveyes;*/ void bwtorgba(unsigned char *b,unsigned char *l,int n) { while(n--) { l[0] = *b; l[1] = *b; l[2] = *b; l[3] = 0xff; l += 4; b++; } } void rgbtorgba(unsigned char *r,unsigned char *g,unsigned char *b,unsigned char *l,int n) { while(n--) { l[0] = r[0]; l[1] = g[0]; l[2] = b[0]; l[3] = 0xff; l += 4; r++; g++; b++; } } void rgbatorgba(unsigned char *r,unsigned char *g,unsigned char *b,unsigned char *a,unsigned char *l,int n) { while(n--) { l[0] = r[0]; l[1] = g[0]; l[2] = b[0]; l[3] = a[0]; l += 4; r++; g++; b++; a++; } } typedef struct _ImageRec { unsigned short imagic; unsigned short type; unsigned short dim; unsigned short xsize, ysize, zsize; unsigned int min, max; unsigned int wasteBytes; char name[80]; unsigned long colorMap; FILE *file; unsigned char *tmp, *tmpR, *tmpG, *tmpB; unsigned long rleEnd; unsigned int *rowStart; int *rowSize; } ImageRec; static void ConvertShort(unsigned short *array, unsigned int length) { unsigned short b1, b2; unsigned char *ptr; ptr = (unsigned char *)array; while (length--) { b1 = *ptr++; b2 = *ptr++; *array++ = (b1 << 8) | (b2); } } static void ConvertUint(unsigned *array, unsigned int length) { unsigned int b1, b2, b3, b4; unsigned char *ptr; ptr = (unsigned char *)array; while (length--) { b1 = *ptr++; b2 = *ptr++; b3 = *ptr++; b4 = *ptr++; *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4); } } static ImageRec *ImageOpen(char *fileName) { union { int testWord; char testByte[4]; } endianTest; ImageRec *image; int swapFlag; int x; endianTest.testWord = 1; if (endianTest.testByte[0] == 1) { swapFlag = 1; } else { swapFlag = 0; } #ifdef CAVE image = (ImageRec *)CAVEMalloc(sizeof(ImageRec)); #else image = (ImageRec *)malloc(sizeof(ImageRec)); #endif if (image == NULL) { fprintf(stderr, "Out of memory!\n"); exit(1); } if ((image->file = fopen(fileName, "rb")) == NULL) { perror(fileName); exit(1); } fread(image, 1, 12, image->file); if (swapFlag) { ConvertShort(&image->imagic, 6); } #ifdef CAVE image->tmp = (unsigned char *)CAVEMalloc(image->xsize*256); image->tmpR = (unsigned char *)CAVEMalloc(image->xsize*256); image->tmpG = (unsigned char *)CAVEMalloc(image->xsize*256); image->tmpB = (unsigned char *)CAVEMalloc(image->xsize*256); #else image->tmp = (unsigned char *)malloc(image->xsize*256); image->tmpR = (unsigned char *)malloc(image->xsize*256); image->tmpG = (unsigned char *)malloc(image->xsize*256); image->tmpB = (unsigned char *)malloc(image->xsize*256); #endif if (image->tmp == NULL || image->tmpR == NULL || image->tmpG == NULL || image->tmpB == NULL) { fprintf(stderr, "Out of memory!\n"); exit(1); } if ((image->type & 0xFF00) == 0x0100) { x = image->ysize * image->zsize * (int) sizeof(unsigned); #ifdef CAVE image->rowStart = (unsigned *)CAVEMalloc(x); image->rowSize = (int *)CAVEMalloc(x); #else image->rowStart = (unsigned *)malloc(x); image->rowSize = (int *)malloc(x); #endif if (image->rowStart == NULL || image->rowSize == NULL) { fprintf(stderr, "Out of memory!\n"); exit(1); } image->rleEnd = 512 + (2 * x); fseek(image->file, 512, SEEK_SET); fread(image->rowStart, 1, x, image->file); fread(image->rowSize, 1, x, image->file); if (swapFlag) { ConvertUint(image->rowStart, x/(int) sizeof(unsigned)); ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int)); } } return image; } static void ImageClose(ImageRec *image) { fclose(image->file); free(image->tmp); free(image->tmpR); free(image->tmpG); free(image->tmpB); free(image); } static void ImageGetRow(ImageRec *image, unsigned char *buf, int y, int z) { unsigned char *iPtr, *oPtr, pixel; int count; if ((image->type & 0xFF00) == 0x0100) { fseek(image->file, (long) image->rowStart[y+z*image->ysize], SEEK_SET); fread(image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize], image->file); iPtr = image->tmp; oPtr = buf; for (;;) { pixel = *iPtr++; count = (int)(pixel & 0x7F); if (!count) { return; } if (pixel & 0x80) { while (count--) { *oPtr++ = *iPtr++; } } else { pixel = *iPtr++; while (count--) { *oPtr++ = pixel; } } } } else { fseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize), SEEK_SET); fread(buf, 1, image->xsize, image->file); } } unsigned * read_texture(char *name, int *width, int *height, int *components) { unsigned *base, *lptr; unsigned char *rbuf, *gbuf, *bbuf, *abuf; ImageRec *image; int y; image = ImageOpen(name); if(!image) return NULL; (*width)=image->xsize; (*height)=image->ysize; (*components)=image->zsize; #ifdef CAVE base = (unsigned *)CAVEMalloc(image->xsize*image->ysize*sizeof(unsigned)); rbuf = (unsigned char *)CAVEMalloc(image->xsize*sizeof(unsigned char)); gbuf = (unsigned char *)CAVEMalloc(image->xsize*sizeof(unsigned char)); bbuf = (unsigned char *)CAVEMalloc(image->xsize*sizeof(unsigned char)); abuf = (unsigned char *)CAVEMalloc(image->xsize*sizeof(unsigned char)); #else base = (unsigned *)malloc(image->xsize*image->ysize*sizeof(unsigned)); rbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); gbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); bbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); abuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); #endif if(!base || !rbuf || !gbuf || !bbuf) return NULL; lptr = base; for(y=0; yysize; y++) { if(image->zsize>=4) { ImageGetRow(image,rbuf,y,0); ImageGetRow(image,gbuf,y,1); ImageGetRow(image,bbuf,y,2); ImageGetRow(image,abuf,y,3); rgbatorgba(rbuf,gbuf,bbuf,abuf,(unsigned char *)lptr,image->xsize); lptr += image->xsize; } else if(image->zsize==3) { ImageGetRow(image,rbuf,y,0); ImageGetRow(image,gbuf,y,1); ImageGetRow(image,bbuf,y,2); rgbtorgba(rbuf,gbuf,bbuf,(unsigned char *)lptr,image->xsize); lptr += image->xsize; } else { ImageGetRow(image,rbuf,y,0); bwtorgba(rbuf,(unsigned char *)lptr,image->xsize); lptr += image->xsize; } } ImageClose(image); free(rbuf); free(gbuf); free(bbuf); free(abuf); return (unsigned *) base; } #define ABS(x) ( (x)<0 ? -(x): (x)) #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) fsqrt(DOT((p),(p))) #define CROSS(p,q,r) {r[0]=p[1]*q[2]-p[2]*q[1];r[1]=p[2]*q[0]-p[0]*q[2];\ r[2]=p[0]*q[1]-p[1]*q[0];} #define GETvec3(a,b) {int ii; FOR(ii,0,3) a[ii]=b[ii];} #define DG M_PI/180 #define RD 180/M_PI #define S(u) fsin(u*DG) #define C(u) fcos(u*DG) #define CLAMP(x,u,v) (xv ? v: x)) #define SET(u, x, y, z) {u[0]=x;u[1]=y;u[2]=z;} #define CPY(u, v) SET(u, v[0], v[1], v[2]) #ifndef CAVE int users = 1; int *CAVENumUsers = &users; #endif /* global variables ... add new ones on top of the stack */ int frozturn=0; /* friz for console turning */ int frozball=0; /* friz for console balling */ /*** inim must NOT be shared, as it is updated in the display process ***/ int inim; int launch; char which[20]; /* audio needs this */ int delta; /* new variables for autotymer to change torus */ float gap, gap0=1.; /*very bad kludge ... for letting arguments reset default gap value */ int audiohandle; /* for telling vss the name of the .aud file */ float mysiz,speed, torq, focal, far; /*console navigation variables */ int win = 2; /* full screen, use 0 for demand sized */ int bground =0; /* black background is the default */ unsigned int BUT,XX,YY,SHIF; /* used in chaptrack gluttery */ int xt,yt; /* once was xt,yt,xm,ym for viewportery */ int audyes=0; /* VSS libs are present */ int afrmyes=0; /* audioframe by Camille */ int texyes=1; /* textures shall not be loaded */ int inimyes=1; /* inner image shall be drawn */ int ballyes=20; int modal,mode,morph,msg,binoc; /* pretty global */ float nose; int th0, th1, dth, ta0, ta1, dta; /* torus parameters */ #define TURNMODE (0) #define FLYMODE (1) #define NUMFURNITURE 10 /* things lying around */ #ifndef MAXMESH # define MAXMESH 24 /* The panel mesh is 12x12 */ #endif /* 24+1 x 24+1 = 625 x 8 points per meshvertex = 5000 */ /*** view contains only that data to be shared between CAVEs ***/ struct view { #ifdef CAVE CAVELOCK viewlock; #endif int viewnum; float color[3]; float duff[16], handmat[16]; int launch; float bullvect[6]; }; /* for the time being, avatars are NOT furniture */ struct furniture { float placemat[16]; float vert[(MAXMESH+1)*(MAXMESH+1)*8 + 100]; float dvert[(MAXMESH+1)*(MAXMESH+1)*8 + 100]; }; struct textures { char name[100]; int width, height, components; unsigned *image; GLuint texid; }; #define HEREICOME 0 struct comestruct{ int messtype; int viewnum; float color[3]; }; #define HEREIAM 1 struct herestruct{ int messtype; float duff[16], handmat[16]; int launch; }; /* Shared memory variables as per Stuart Levy 1994 */ struct share_var{ float s_siz; /*final scaling factor before projection */ int s_wnd; /*wand or maus flag */ int s_gnd; /*background color */ /* float s_lu[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_ta0 ; /* */ int s_ta1 ; /* */ float s_gap ; /* not used */ float s_right ; /* joystick wedge for simulator/bad joystick */ float s_forwd ; /* joystick wedge forward/backward */ int s_mass; /* used */ struct textures s_texture[3]; int s_texs; /* how many textures used */ int s_furn; /* active furniture */ int s_ballgored; /* by somebody's bull */ int s_ballpitch; /* times around, =0 invisible */ float s_ballwhere[3]; /* where the ball is at in the world */ /* maybe you want to know whichway it's moving too ? */ GLfloat s_aff[16],s_starmat[16]; /*affine matrices for object, stars*/ struct view s_myview; struct furniture s_furniture[NUMFURNITURE]; float s_bgcolor[3]; } *s_var; #define TOTALFURNITURE 4 #define NUM_TEXTURES 3 #define furn (s_var->s_furn) #define texture (s_var->s_texture) #define furnitures (s_var->s_furniture) /* thickness gkf */ #ifndef FURNITURE_H #define FURNITURE_H #define MYCYCLE(f,m) (f)=(((f)+(m)-1)%(m)),(f)=(++(f)%(m)) float *displace(int who, float vert[3]); void place(float place[3], float vert[3],float what[16]); void texenable(struct textures *t); void mesh(float x0, float x1, float y0, float y1, float s0, float s1, float t0, float t1, float z, int nx, int ny, float *mp); void cycletexture(void) { static int soak = 0; int acttex; soak = 1 - soak; /* printf("Soak=%i\n",soak); if(soak ==0 ) return; */ #ifdef CAVE if(!CAVEMasterDisplay()) return; #endif acttex = furnitures[furn].vert[4]; /* printf("Furniture/Texture=%i/%i\n",furn,acttex); */ acttex=(++acttex)%(NUM_TEXTURES+1); furnitures[furn].vert[4] = acttex; } void cyclefurn(void) { int acttex; #ifdef CAVE if(!CAVEMasterDisplay()) return; #endif (furn)=(++furn)%TOTALFURNITURE; } /*** Mesh ***/ void initmesh(struct furniture *ff, float width, int gaps, float *color, int texid) { float *pp; pp = ff->vert; pp[0] = 2*(gaps+1)*(gaps+1); /* first point has the number of vertices */ pp[1] = color[0]; /* save color in next 3 vertices */ pp[2] = color[1]; pp[3] = color[2]; pp[4] = texid; pp[5] = width; pp[6] = gaps; pp+=10; mesh(0.0,width,0.0,width,0,1,0,1,0,gaps,gaps,pp); } void placemesh(struct furniture *ff) { int ii,nn; float *pp; pp = ff->vert; nn = pp[0]; pp+=10; for(ii=0; iiplacemat); } void drawmesh(int who, struct furniture *ff, int dmode) { float *pp; int ii,jj; int gaps; int texid; pp = ff->vert; texid = pp[4]; if(dmode!=1) glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); if(dmode == 0)glLineWidth(2.); /*thickness gkf */ if(texyes && dmode>=2 && texid>0) { if(dmode == 3) glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glEnable(GL_TEXTURE_2D); texenable(&texture[texid-1]); } glColor3f(pp[1],pp[2],pp[3]); gaps = pp[6]; pp+=10; for (ii = gaps + 1; ii; ii--) { glBegin(GL_TRIANGLE_STRIP); for (jj = gaps + 1; jj; jj--) { glTexCoord2fv(pp); glVertex3fv(displace(who,pp + 4)); glTexCoord2fv(pp + 8); glVertex3fv(displace(who,pp + 12)); pp += 16; } glEnd(); } if(texyes) glDisable(GL_TEXTURE_2D); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } void mesh(float x0, float x1, float y0, float y1, float s0, float s1, float t0, float t1, float z, int nx, int ny, float *mp) { float y, x, s, t, dx, dy, ds, dt, vb[3], tb[2]; float v; dx = (x1 - x0) / nx; dy = (y1 - y0) / ny; ds = (s1 - s0) / nx; dt = (t1 - t0) / ny; y = y0; t = t0; vb[2] = z; while (y < y1) { x = x0; s = s0; while (x <= x1) { tb[0] = s; tb[1] = t; vb[0] = x; vb[1] = y; *mp++ = tb[0]; *mp++ = tb[1]; mp += 2; *mp++ = vb[0]; *mp++ = vb[1]; *mp++ = vb[2]; mp++; tb[1] = t + dt; vb[1] = y + dy; *mp++ = tb[0]; *mp++ = tb[1]; mp += 2; *mp++ = vb[0]; *mp++ = vb[1]; *mp++ = vb[2]; mp++; x += dx; s += ds; } y += dy; t += dt; } } /*** Floor ***/ void initfloor(struct furniture *ff, float width, int gaps, float *color, int texid) { float *pp; int ii,jj; float xx,yy,zz; float delta; float L; int doublegaps = gaps/2; pp = ff->vert; pp[0] = 4*gaps*doublegaps; /* first point has the number of vertices */ pp[1] = color[0]; /* save color in next 3 vertices */ pp[2] = color[1]; pp[3] = color[2]; pp[4] = texid; pp[5] = width; pp[6] = gaps; pp+=10; yy=0.0; delta=0.2; L=width; for(ii=0;iivert; nn = pp[0]; pp+=10; for(ii=0; iiplacemat); } void drawfloor(int who, struct furniture *ff, int dmode) { float *pp; int ii,jj,kk; int gaps; int texid; pp = ff->vert; texid = pp[4]; if(dmode!=1)glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); if(texyes && dmode>=2 && texid>0) { if(dmode == 3) glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glEnable(GL_TEXTURE_2D); texenable(&texture[texid-1]); } glColor3f(pp[1],pp[2],pp[3]); gaps = pp[6]; pp+=10; glBegin(GL_QUADS); for(ii=0;iivert; pp[0] = 2 * ( gaps * turns + 1); /* first point has the number of vertices */ pp[1] = color[0]; /* save color in next 3 vertices */ pp[2] = color[1]; pp[3] = color[2]; pp[4] = texid; pp[5] = rad; pp[6] = width; pp+=10; for(nn=0; nn<=(gaps*turns); nn++, pp+=10 ) { theta = nn * dt; pp[0] = rad * C(theta); /* x_n */ pp[2] = rad * S(theta); /* z_n */ pp[1] = nn * dy; /* y_n */ pp[3] = theta/360.0; /* Texture x */ pp[4] = pp[1] / hight; /* Texture y */ pp[5] = pp[0]; /* x_(n+1) */ pp[7] = pp[2]; /* z_(n+1) */ pp[6] = pp[1] + width; /* y_(n+1) */ pp[8] = theta/360.0; /* Texture x */ pp[9] = pp[6] / hight; /* Texture y */ } pp[0] = 0.0; pp[1] = hight; pp[2] = 0.0; } void placepole(struct furniture *ff) { int ii,nn; float *pp; pp = ff->vert; nn = pp[0]; pp+=10; for(ii=0; ii<=nn; ii++, pp+=5) place(pp,pp,ff->placemat); place(pp,pp,ff->placemat); } /* dmode 0: wireframe 1: solid 2: texture WIRE 3: texture FILL */ void drawpole(int who, struct furniture *ff, int dmode) { float *pp; int texid; int ii, nn; pp = ff->vert; nn = pp[0]; texid = pp[4]; if(dmode!=1) glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); if(texyes && dmode>=2 && texid>0) { if(dmode == 3) glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glEnable(GL_TEXTURE_2D); texenable(&texture[texid-1]); } glColor3f(pp[1],pp[2],pp[3]); pp+=10; glBegin(GL_TRIANGLE_STRIP); for(ii=0; ii < nn ; ii++, pp+=5) { glTexCoord2fv(pp + 3); glVertex3fv(displace(who,pp)); } glEnd(); if(texyes) glDisable(GL_TEXTURE_2D); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); /* glColor3f(0.0,0.0,1.0); glutWireSphere(0.5,20,10); */ } #endif /* FURNITURE_H */ #define myview (s_var->s_myview) #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 lu (s_var->s_lu )*/ #define aff (s_var->s_aff) #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 ta0 (s_var->s_ta0) #define ta1 (s_var->s_ta1) #define gap (s_var->s_gap) #define mass (s_var->s_mass) #define right (s_var->s_right) #define forwd (s_var->s_forwd) #define texs (s_var->s_texs) #define ballgored (s_var->s_ballgored) #define ballpitch (s_var->s_ballpitch) #define ballwhere (s_var->s_ballwhere) #define bgcolor (s_var->s_bgcolor) /*** define specific furniture ***/ #define mesh1 furnitures[0] #define mesh2 furnitures[1] #define pole1 furnitures[2] #define floor1 furnitures[3] void SendMessage(int); float *displace(int, float[3]); float *distar(int, float[3]); /*** this is a useful macro, and is used by avatarsC2C.h ***/ #ifdef CAVE #define VIEW(x) ((struct view *)CAVEUser[x]->app_data) #else #define VIEW(x) (&myview) #endif /* This is the CAVE2CAVE version of GKF's avatars.h ---JSE 5/3/99 */ /* KM's new face 11/1/98 */ /* rationalize this variable better, needs to be in deFaults */ #define UU .01 /* unit 1/8 inch to feet 8x12=96=100 */ /* the natural unit in noosh is 1ft too */ #define FF 1.0 /* 2. for a big face and hand */ /* drawarm is still provisional, this will change */ void arm(float rad, float pitch){ float th, ta, dth; dth=1/pitch; /* pitch = number of half turns */ glLineWidth(1); glBegin(GL_LINE_STRIP); for(th = 0 + 1.0; th < pitch*M_PI+ 1.0; th += dth ){ ta=th*dth; /* Deform here */ glVertex3f( rad*fsin(th) - rad /* * fsin(ta) */ , rad*fcos(ta) - rad , -rad*fcos(th) + rad /* *fsin(ta) */ ); }glEnd(); } void mvto(float *vv, float dx, float dy, float dz){ vv[0] += dx*UU; vv[1] += dy*UU; vv[2] += dz*UU; /* Deform here */ glVertex3fv(vv); } void marker(float *vv){ /* a little cubelet */ mvto(vv,2,0,0); mvto(vv,0,2,0); mvto(vv,-2,0,0); mvto(vv,0,0,2); mvto(vv,2,0,0); mvto(vv,0,-2,0); mvto(vv,-2,0,0); mvto(vv,0,0,-2); } void hand(){ float vv[3] ={0,0,0}; /* coords = thumbway, forward, fingerish */ glBegin(GL_LINE_STRIP); mvto(vv, 0, 0 , 0); /*a wrist */ mvto(vv, 3, 6 ,0 ); /*b */ mvto(vv, 5, 11,0 ); /*c*/ mvto(vv, 1, 4 ,0); /*d thumb */ mvto(vv, 8, 6 ,0); /*e*/ mvto(vv, 5, 6 ,0); /*f*/ mvto(vv, 3, 4 ,0); /*g*/ mvto(vv, -1, 1 ,0); /*h thumb tip*/ mvto(vv, -7, 0 ,0); /*i */ mvto(vv, -5, -4 ,0); /*j*/ mvto(vv, -8, -4 ,0); /*k forefinger*/ mvto(vv, 0 ,15 ,0); /* ak */ mvto(vv, 0 , 7 ,1); /*bk */ mvto(vv, 0 , 8 ,2); /*ck */ mvto(vv, 0 , 6 ,4); /*dk */ mvto(vv, 0 , 0 ,2); /*ek fore tip */ mvto(vv, 0 ,-4 ,1); /* fk */ mvto(vv, 0 ,-5 ,-1); /* gk */ mvto(vv, 0 ,-9 ,-2); /*hk */ mvto(vv, 0 ,-11, 1); /*ik */ mvto(vv, 0, 1, 6); /*l */ mvto(vv, 0, -2, 7); /*m middle */ mvto(vv, 4,-14,-4); /*n */ mvto(vv, -6, 0, 0); /*an middletip*/ mvto(vv, -3, 13, 0); /*bn*/ mvto(vv, 0, 2, -7); /*abn detour*/ mvto(vv, 0, -1,-6); /*bbn*/ mvto(vv, -2, 0,0 ); /*crack cbn*/ mvto(vv, 0, 1 , 6); /*dbn*/ mvto(vv, 0, -2 ,7); /*dbn*/ mvto(vv, 3, -12,0); /*dn*/ mvto(vv, -7, 0 ,0); /*aan ringtip*/ mvto(vv, -3, 13 ,0); /*bbn*/ mvto(vv, 0, 2, -7); /*abn detour*/ mvto(vv, 0, -1,-6); /*bbn*/ mvto(vv, -2, 0,0 ); /*crack cbn*/ mvto(vv, 0, 1 , 6 ); /*dbn*/ mvto(vv, 0, -2 ,7); /*dbn*/ mvto(vv, 3, -12,0); /*ddn*/ mvto(vv, -6, -1,-2); /*new p* end pinky/ mvto(vv, -4 , 8 ,0); /*q */ marker(vv); mvto(vv, 0, 8, 0 ); /* correction */ mvto(vv, 0 , 2, -7); /*aq */ mvto(vv, 0 , -1,-6); /*bq */ mvto(vv, -2 , -12,0); /* crack r */ mvto(vv, 3 , -15,0); /* */ mvto(vv, -2 , -9 ,0); /* */ glEnd(); arm(.1, 8.0); /*rad, pitch*/ } void drawhand(int who){ float temp[16]={-2,0,0,0, 0,0,-2,0, 0,-2,0,0, 0,0,0,1}; glColor3f(VIEW(who)->color[0], VIEW(who)->color[1], VIEW(who)->color[2]); glMultMatrixf(temp); hand(); } /*******************************************************************/ /* head avatar */ /*******************************************************************/ void planespiral(float rad, float pitch, float xx, float yy){ float th, ta, dth; dth=1/pitch; /* pitch = number of half turns */ rad *= UU; xx *= UU ; yy *=UU; glLineWidth(1); glBegin(GL_LINE_STRIP); for(th = 0 ; th < pitch*M_PI; th += dth ){ ta=th*dth; /* Deform here */ glVertex3f( rad*fsin(th) * fsin(ta) + xx , -rad*fcos(th) * fsin(ta) + yy , 0 ); }glEnd(); } /* remember to */ void glasses(){ float vv[3]={0,0,0}; glBegin(GL_LINE_STRIP); mvto(vv, 0, 0, 0); mvto(vv, 25, -3, 3); /*bidi2hinge*/ mvto(vv, 2, -3, 24); /* midtemple */ mvto(vv, -5, -3, 27); /* endtemple */ mvto(vv, 0, -3, 0); /* endtemple */ mvto(vv, 5, 0 ,-27); /*botmidtemple */ mvto(vv, -2, 0 ,-24); /*bothinge */ mvto(vv, 0, -7 , 0); /*bothinge */ mvto(vv, -22, 3 , -3); /* hinge2nose*/ mvto(vv, -2, 5 , 0 ); /* noseside*/ mvto(vv, -1, 0 , 0 ); /* nosebridge*/ mvto(vv, -1, 0 , 0 ); /* nosebridge */ mvto(vv, -2, -5 , 0 ); /* noseside */ mvto(vv, -22, -3 , 3); /* hinge2nose*/ mvto(vv, 0, 7 , 0); /*bothinge */ mvto(vv, -2, 0 , 24); /*bothinge */ mvto(vv, 5, 0 , 27); /*botmidtemple */ mvto(vv, 0, 3, 0); /*endtemple */ mvto(vv, -5, 3, -27); /*endtemple */ mvto(vv, 2, 3, -24); /* midtemple */ mvto(vv, 25, 3, -3); /*bidi2hinge*/ glEnd(); } void face(){float vv[3]={0,0,0}; glBegin(GL_LINE_STRIP); mvto(vv, 0, 0 , 0); mvto(vv, -10, 6, .5); mvto(vv, 10, 6, .5); mvto(vv, 10, 5, 2.5); mvto(vv, -10, 5, 2.5); mvto(vv, -20, 3, 3.5); mvto(vv, 20, 3, 3.5); mvto(vv, 20, 2, 5.5); mvto(vv, -20, 2, 5.5); mvto(vv, -10, -1, 6); mvto(vv, 10, -1, 6); mvto(vv, 10, -4, 4.5); mvto(vv, -10, -4, 4.5); mvto(vv, -7, -2.5, 3.5); mvto(vv, 7, -2.5, 3.5); glEnd(); glBegin(GL_LINE_STRIP); vv[0]=vv[1]=vv[2]=0; mvto(vv, 0, -11 , 2); mvto(vv, 0, -7, -5 ); mvto(vv, 0, -5, -4 ); mvto(vv, 0, -4, -1); mvto(vv, 0, -3, 3); mvto(vv, 0, 0, 6); mvto(vv, 0, -3, 0); mvto(vv, 1, 1, 0); /*mouth*/ mvto(vv, 1, 0, 0); mvto(vv, 7, -3, 0); mvto(vv, 1, 1, 0); mvto(vv, -1, -1, 0); mvto(vv, -7, 0, 0); mvto(vv, -1, -1, 0); mvto(vv, -1, -.5, 0); mvto(vv, 0, -3, 0); mvto(vv, 3, .5, 0); mvto(vv, -1, 3.5, 0);/*center*/ mvto(vv, 1, -3.5, 0); mvto(vv, 3, .5, 0); mvto(vv, -1, 3.5, 0);/*one*/ mvto(vv, 1, -3.5, 0); mvto(vv, 2, 1, 0); mvto(vv, 0, 2.5, 0); mvto(vv, 0, -2.5, 0); mvto(vv, 2, 2, 0); mvto(vv, -2, -3, 0); mvto(vv, -6, -3, 0); /*half mouth*/ mvto(vv, -2, -.5, 0); mvto(vv, -2, .5, 0); mvto(vv, -5, 3, 0); mvto(vv, -3, 4, 0);/*here*/ mvto(vv, 2, -3, 0); mvto(vv, 2, -1, 0); mvto(vv, 2, -.5, 0); mvto(vv, 4, -.5, 0); mvto(vv, 0, 3, 0); mvto(vv, -1.5, .5, 0); mvto(vv, -1, 1, 0); mvto(vv, -1, -4, 0); mvto(vv, 1, 4, 0); mvto(vv, -2, 0, 0); mvto(vv, -1, -3.5, 0); mvto(vv, 1, 3.5, 0); mvto(vv, -3, 0, 0); mvto(vv, 0, -3, 0); mvto(vv, 0, 3, 0); mvto(vv, -2, 1, 0); mvto(vv, 1, -1, 0); mvto(vv, 6, 3, 0); mvto(vv, 1, 0, 0); mvto(vv, 1, -1, 0); mvto(vv, .5, 0, 0); glEnd(); glBegin(GL_LINE_STRIP); mvto(vv, 0, -9, 0); mvto(vv, 0, -4, 0); mvto(vv, 0, -6, 0); mvto(vv, 0, 0, 6 ); mvto(vv, 0, 1, 8 ); mvto(vv, 0, 5, 4 ); glEnd(); } void drawface(int who){ float temp[16]={FF,0,0,0, 0,FF,0,0, 0,0,FF,0, 0,.3,-.5,1}; /* note, this is a gues as to where and how big the simulator head is */ glColor3f(VIEW(who)->color[0], VIEW(who)->color[1], VIEW(who)->color[2]); /* glColor3f(VIEW(who)->color[0], VIEW(who)->color[1], VIEW(who)->color[2]);*/ glMultMatrixf(temp); glasses(); face(); glColor3f(1,1,0); planespiral( 8, 10, 13, -10 ); glColor3f(0,1,1); planespiral( 8, 10, -13, -10 ); } /*** Levy's stars, modified for C2C gravilens (netlens.c) ---JSE ***/ #include #include #include #include #include #define NewA(type, count) ((type *)alloca((count)*sizeof(type))) #define NewN(type, count) ((type *)malloc((count)*sizeof(type))) typedef float Matrix[4*4]; typedef struct { float x[3]; } Point; int zoom2 = 1; /* Flag for "enlarge stars twofold" */ /* extern int caveyes; /* Hope this is defined somewhere else */ /* extern Matrix starmat; /* Hope this is defined elsewhere too */ void vtfmvector( Point *dst, register Point *src, register Matrix T ) { int i; for(i = 0; i < 3; i++) dst->x[i] = src->x[0]*T[i] + src->x[1]*T[i+4] + src->x[2]*T[i+8]; } struct starsize { float size; int base; int count; int color; } *starsizes; int nstarsizes = 0; float scolors[][3] = { .5, 1, 1, /* W */ .7, .8, 1, /* O */ .9, .9, 1, /* B */ 1, 1, 1, /* A */ 1, 1, .9, /* F */ 1, 1, .8, /* G */ 1, .8, .7, /* K */ 1, .7, .5, /* M */ }; float *starpos; #define SRADIX 91 #define SZERO '$' #define SSIZE '!' #define SSIZESCL 8 #define SRASCALE (8192 / (2*M_PI)) #define SDECSCALE (8192 / M_PI) #define SDECBIAS 4096 #define SCOLORBASE 0 #define SSIZEBASE 8 /* 1128 real stars, to about visual magnitude 4.7 */ /* from star2illi -m 4.7 -d 1.2 -c 3.5 */ char stardata[] = /* Show Pleiades at upper right, Orion at center of field */ "#@ -.98525 .062202 .1594 0 .16485 .095488 .98169 0 .045842 .99349 -.10433 0 0 0 1\n" "!<'=BH_" "!:(<$6`" "!9'iodI!9&7`Lw!9)Z~2Y7mh&!9*YQZ[" "!8&*.4G!8(@eS\\!8+:7Te" "!7'nLUM!7&Xh2oVCKK!7*5;Y=!7+arCl" "!6'z/B6q[g`!6&S~33J'W$!6*A,_'Z~2Y" "!5'@J`{@J`{FY.1!5&>3BTRa1Mes>N8BT58H_A9&PIw'9S!5+R{4M" "!4'TGm$:OgQkCn" "f-;R-Q}`!4*MQouCJ3:c).PGPLb+z\\h&fH&Xy>o[bv-!4+(Ebo!4%9?P'!4$B[9C" "!3'PBX?S[8S^K^FFo3EV;lPMFm7!3&/ieQ8iPrW;6=[09AZg;y`'EdfJ=Q!3(pIe1$XnZ!3*" "F<;>&Tm>g@ji+hf5c2?r%_;ruTU{!3+y59W!3%B9=%" "!2'dJI2P]kssyp@N1[=bCKfkKB*:Pc]+3[J)Eo0!2&?iBE'VoFzXX\\G15QX99ER$H9QU7_" "]BLA`DG.99?}\\4;LSC.Lec>D!2(8mH-!2)S3E@X4Z7LK8?!2*qwb$JiZy_'T96XaZ?B>N" "[B^VhoB,n2VA!2+zR_)/HS)" "!1'V)>_[cH~7:NOueHz]M.`TSd4Hd0Ok[Wz,-bR!1&L60m^N+K28ktFR6tfx!1)aSokav[ieak3" "%[*FbZ`nTvVQ8SF]tgN9/Vkjy7`/vtPr=;]YH]\\vUzEK!1*fPS?iA;kA}>LE,Ws;jSv.{c;=}OQ1Q\\7;{73e^P|gwp@,;DhqOW!0+,eOSJvejh\\>]" "27+u" "!/'505P=S2'yyI-Q}mUN2XfVyPe4lXz/1On]b:`+2pry.VKWr<3`&=mFL3Sk`NXj_ad3(W;Am6S!/(dT;G=CWNlrRX+*_mJV\\f!/)(09_ACDX3v1jCvoFDyT8]'6{fa^s'*mx]9aay_]A*RI(" "\\Ge7!/*&N`MXwCa]onRkdC4gNL0w6n/JY2Cqqoy(>Kx>EC(NJaW!/+;L\\<\\SDETPRe/XdK" ")T;DnzZidbX7" "!.'HBU|I|YH_EO?w2T.9cI[?GY==mb$E~hZP./^Xlq7_2Xf_LS;[IQ{!.&i6:&IA5fYf9}" ",U7:4/@.c>>$7rMYDT6Vee2`zHf5.]^_2B](&@k|^bB/gy7{Dg@J67Sn2)]+6HR9!.(?S\\$" "f.I@hpuG9UEkGbGfpVS\\P>^$_Wu=Ha:>Ixscd(!.)4lZ[bcdOOAA+NOI\\" "oW/wA']7p1Jg0mUT)eXcHY1i+;76gF_^nfT7!.*k/FNC(U[y]r/1{L0%8L[]]>s*0iBZR`6" "^YBzRC2m);LxA,>&J4JpTv-9cK;of]0_4:XorM3kzrFK{CR_P1hw:Ol2s+f}!.+0OF0!.%" "8{U}" "!-'g}UlaGZZfiREr$LS[?HznU^LV=^LV=K;3^DV9bKq8u_lXq0%BS[7N4nVQS!-)" "tLEmkWF0lCkd?s^wJiZy9|FX59Af|\\h;n=t2;u@>`}13Vd=@b.)VMl3S^PI\\!-**|Kq1@L>" "ASm-hLr3YoshG/qgLK1HZLqb/[R)O4lY$i$[v2%0[" "ieLu3t;rg>c^5HIr8d?==uDw$Z:0I)^%/'LWnlbWzx:GH;PL!-+ynM8.al|n9Z=O8sb!-%" "94Oe" "!,'(=5Gck`PsiS^5=OC@pL9l]H,%^;3DmZ,NiV=rZe[)d8O.ukH.,YazE3C2VClR`0n?`jG=j7->lb:jpr`6y\\J7}}TM5qOGDx_HQUD^a;7y" "k:XVkFN1tugnxfP{6|o:P0T=TK4JgrR*Z,jzZt8>" "[:?K\\n:E&{]1@R^Ncg6J*PjE-|Q46TWj=uJ~C3*UDk;bWrXw]E3[s1HHGw3GM:GrNnH3YSN%t2Zw" "uPnI" "!+'*)ee,r.a/IE69*U__@Z+-}.s.(=+15WPAB9oKf)dP32IR./&^W/qkr>)ku=Cr;CVxG;0.QI6H}IYQCUFzB6]iA8Onf<+uW]pwScu|jSo3yi88;M.DE;S^A`dqvDF|lg5?GwXM/2C>veJDwy*CP22\\~@+`vYUh)Wr?kYAKtjF[>wNmUyLW-" "8bS~AnEXb1f91*n~9?P'K;cEz&@g{[a}?`buz'nKaOsrdeuciaAZ8{bd*:p/Ji" "!*'(?|1(Ch^-592.,n9BR.cC?*d+mWPFxEhs%|1S&I_a,AUL;U?L>%HPJ$V%mjZ&mpYio$?E|B>-" "!)'8jZAUGN:cHV-6@N>{`1Av8GNH`k[`C&ec^+gJ`.zjve{M@g'X\\f/1aEiX^R:TeKNOfgC,}amj$9HC7'?<>x)ii}BBz1XD8KRW8|NZ@}BmI%l)_\\DC`kC(e~9ijy\\CklLN(2q" "UT3([CYQ\\.q~]q=^mWDX{W\\t$BN3%*dE41j3B$GnMa1ll]I'q1b^+-R[8hME@bC[DgMHFh>?OK5s" "TK3K^HK}_Wf:f0L{gVO3k'S.'Un[/7[b/7[b/{do2Itb:h[+AX86MXTbN7\\W_E^(`94.ahLoxrjl" "!&'6z[m??C*?xi]@OBoSR=%^p:a_MD0gUS6g}UFiO1ri\\;qo,^u(\\]@2\\Dd5/XL6LV,:01N=xW[" "@4ATSw4iWb7>W}qF`88Gc0K\\dsc`h_CPzTj((N[T.8^s3$E$=*U|?1Cp?H>^De[hK845Ky3JQ*TA" "SNM%Sa8ZW@lEjenelxQ4x-Qd}t]Y*qKa1,ik:uIUFLpk^h?mgSYGrq@tuIj[" "!%'7(Xe=}FzB,P@H3SCa>)_i$LUm>srq8XCu,G=+5/4+kBE4aXF5NX|ET6_G7BZGNEpSs2SViMu" "gpB8mf`,sJV+u0M,vfOyvf4\\y:GZzuEk" ; static int slow_stars = 0; void initstars() { char *cp; float ra, dec, cd; int maxstars = 5000; int maxsizes = 32; float *stars = NewA(float, maxstars*3); float *starp; int nstars = 0; struct starsize *sizes = NewA(struct starsize, maxsizes); struct starsize *sizep; int i, nsizes = 0; char line[512]; FILE *inf = fopen("stars.illi", "r"); #ifdef CAVE float r = 90.; #else float r = 1.; #endif const GLubyte *rend = glGetString(GL_RENDERER); Point sp; static Matrix startfm = { 0,0,-1,0, -1,0,0,0, 0,1,0,0, 0,0,0,1 }; if(rend==NULL || (rend[0]=='X'||rend[0]=='G')) slow_stars = 1; starp = &stars[0]; sizep = &sizes[0]; sizep->size = 1; sizep->base = 0; sizep->color = 3; nsizes = 0; cp = stardata; do { if(inf) { line[sizeof(line)-1] = '\0'; if(fgets(line, sizeof(line)-1, inf) == NULL) break; cp = line; } for(;;) { if(*cp >= '$') { if(nstars >= maxstars-1) { maxstars *= 3; starp = NewA(float, 3*maxstars); memcpy(starp, stars, nstars*3*sizeof(float)); stars = starp; starp = &stars[nstars*3]; } ra = ((cp[0] - SZERO)*SRADIX + (cp[1] - SZERO)) / SRASCALE; dec = ((cp[2] - SZERO)*SRADIX + (cp[3] - SZERO) - SDECBIAS) / SDECSCALE; cd = cosf(dec); sp.x[0] /*starp[2]*/ = -r * cd * cosf(ra); sp.x[1] /*starp[0]*/ = -r * cd * sinf(ra); sp.x[2] /*starp[1]*/ = r * sinf(dec); vtfmvector( (Point *)starp, &sp, startfm ); cp += 4; starp += 3; nstars++; } else if(*cp == '#') { /* Comments. * Also, "#@" hack allows specifying star transformation. */ if(cp[1] == '@') { cp += 2; for(i = 0; i<16; i++) startfm[i] = strtod(cp, &cp); cp--; } while(*++cp != '\n' && *cp != '\0') ; } else if(*cp == '!') { sizep->count = nstars - sizep->base; if(sizep->count > 0) nsizes++, sizep++; if(nsizes >= maxsizes) { maxsizes *= 3; sizep = NewA(struct starsize, maxsizes); memcpy(sizep, sizes, nsizes*sizeof(struct starsize)); sizes = sizep; sizep = &sizes[nsizes]; } sizep->size = (cp[1] - SZERO) / (float)SSIZESCL; sizep->color = (cp[2] - SZERO); sizep->base = nstars; cp += 3; } else if(*cp == '\0') { break; } else { cp++; } } } while(inf || *cp != '\0'); sizep->count = nstars - sizep->base; nstarsizes = nsizes+1; starsizes = NewN(struct starsize, nstarsizes); memcpy(starsizes, sizes, nstarsizes*sizeof(struct starsize)); starpos = NewN(float, 3*nstars); memcpy(starpos, stars, nstars*3*sizeof(float)); } void drawstars(int modal) { int s, i; float v, size; float vv[3]; struct starsize *sp; float *starp; int darkstars = (bgcolor[0]+bgcolor[1]+bgcolor[2] > 1.5); int myzoom = 1 + zoom2 + darkstars; int smooth = (!slow_stars || myzoom>1); if(getenv("NOSTARS")) return; vv[0]=VIEW(modal)->duff[12]; vv[1]=VIEW(modal)->duff[13]; vv[2]=VIEW(modal)->duff[14]; glMatrixMode(GL_MODELVIEW); glPushMatrix(); if(smooth) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_POINT_SMOOTH); glEnable(GL_BLEND); } else { glDisable(GL_POINT_SMOOTH); glDisable(GL_BLEND); } glDisable(GL_DEPTH_TEST); glMultMatrixf(starmat); for(i = nstarsizes; --i >= 0; ) { sp = &starsizes[i]; size = myzoom*sp->size; glPointSize( size ); v = size < 1 ? size : 1 - (ceil(size) - size) * .25; if(darkstars) { glColor3f( 1 - v*scolors[sp->color][0], 1 - v*scolors[sp->color][1], 1 - v*scolors[sp->color][2] ); } else { glColor3f( v*scolors[sp->color][0], v*scolors[sp->color][1], v*scolors[sp->color][2] ); } glBegin(GL_POINTS); for(s = sp->count, starp = &starpos[3*sp->base]; --s >= 0; starp += 3) { if(DOT(vv,starp)<0) { glVertex3fv(distar(modal,starp)); } else glVertex3fv( starp ); } glEnd(); } glPopMatrix(); glDisable(GL_POINT_SMOOTH); glEnable(GL_DEPTH_TEST); } /* 4:30 pm Monday 9 Nov increased the bungee length and paintball splats */ /* These variables should be globalized better inside voodoo */ #define BALLRAD 1.0 /* 2foot diameter ball */ #define BALLSPD .3 #define BOXSIZE 5.0 /* 10foot cave */ #define NHDSIZE 1.0 /* what is really nearby */ #define BUNGEE 50.0 #define NEAR(aa,bb,cc) (ABS((aa)[0]-(bb)[0]) 4.0 ) {vel[ii] *= - 1.0;} if(!frozball) FOR(ii,0,3) pos[ii] += BALLSPD * vel[ii]; glTranslatef(pos[0],pos[1],pos[2]); spiralball(BALLRAD, ballgored ? 42 : ballpitch); ballgored = 0; /* message to bleed received */ /* but the bulls need to know where the ball is to check their collision */ FOR(ii,0,3){ballwhere[ii]=pos[ii];} /* of course, ballwhere has to be in the furniture structure */ } /****************************************************************************/ /***************************DRAWBULLS***************************************/ /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ void drawbulls(int new, int who ){int ii, hit; float rad, pitch, ctr[3]; static float pos[3][3], vel[3][3]; static int virgin[3]={1,1,1}; if(new)virgin[who] = 1; rad = .2*BALLRAD; pitch=20; glColor3f(VIEW(who)->color[0],VIEW(who)->color[1],VIEW(who)->color[2]); /********************launch = 1 to retrieve bull, 1=01 3=11 2=10 **********/ /*****************eventually don't release until 2 ************************/ if((VIEW(who)->launch) == 1)virgin[who]=1; /**********(re)calculate starting position and velocity */ if(virgin[who]){ /*initialize the bull */ FOR(ii,0,3){ pos[who][ii]= (VIEW(who)->duff[ii])*(VIEW(who)->handmat[12]) + (VIEW(who)->duff[ii+4])*(VIEW(who)->handmat[13]) + (VIEW(who)->duff[ii+8])*(VIEW(who)->handmat[14]) + (VIEW(who)->duff[ii+12]); vel[who][ii]= (VIEW(who)->duff[ii])*(-(VIEW(who)->handmat[8])) + (VIEW(who)->duff[ii+4])*(-(VIEW(who)->handmat[9])) + (VIEW(who)->duff[ii+8])*(-(VIEW(who)->handmat[10])); } glTranslatef(pos[who][0],pos[who][1],pos[who][2]); spiralball(rad, pitch); if((VIEW(who)->launch) == 2)virgin[who] = 0; /* but this works ! */ /***********************end INITIALIZE BULL **********************************/ }else{ /************************** UPDATE BULL ***************************************/ FOR(ii,0,3) pos[who][ii] += 2 * BALLSPD * vel[who][ii]; /* advance position */ /* bull hit lens and signals this to lens with ballgored flag */ if(NEAR( pos[who], ballwhere, NHDSIZE)){ virgin[who] = 1; ballgored =1; } /* bull hit went too far and snaps back to wrist */ FOR(ii,0,3)ctr[ii]= VIEW(who)->duff[12+ii]; if(ABS(pos[who][0]- ctr[0])> BUNGEE || ABS(pos[who][1]-ctr[1])> BUNGEE || ABS(pos[who][2]-ctr[2])> BUNGEE)virgin[who]=1; /* bull hit avatar's head, changes to their color and becomes big and solid */ FOR(ii,0,3)ctr[ii]= VIEW((who+1)%*CAVENumUsers)->duff[12+ii]; if(NEAR( pos[who], ctr, NHDSIZE)){virgin[who] = 1; pitch = 42; rad = 2*BALLRAD; glColor3f(VIEW((who+1)%*CAVENumUsers)->color[0], VIEW((who+1)%*CAVENumUsers)->color[1],VIEW((who+1)%*CAVENumUsers)->color[2]); } /* FOR(ii,0,3) ctr[ii]= viewer[(who+2)%].duff[12+ii]; if(NEAR( pos[who], ctr, NHDSIZE)){virgin[who] = 1; pitch = 42; rad = 2*BALLRAD; glColor3f(viewer[(who+2)%3].color[0], viewer[(who+2)%3].color[1],viewer[(who+2)%3].color[2]); } */ /************************** DRAW BULL ***************************************/ glTranslatef(pos[who][0],pos[who][1],pos[who][2]); spiralball(rad, pitch); /********************************************************************************/ } /* end else */ } /* end drawbulls */ /*** Initialization ***/ /*** texture inits ***/ void definetextures(void) { /* strcpy(texture[0].name,"images/venus.rgb"); */ /* strcpy(texture[0].name,"images/dali.rgb"); */ /* either is called mural.rgb, choose which at run time*/ /* don't keep changing the source code */ /* pillar = dali2 floortile = dollar_front */ strcpy(texture[0].name,"images/mural.rgb"); strcpy(texture[1].name,"images/pillar.rgb"); strcpy(texture[2].name,"images/floortile.rgb"); } int texinit(struct textures *t) { t->texid = 0; /* not yet bound to a texture object. */ if(strlen(t->name)>0 && t->image==NULL) { t->image = read_texture(t->name, &t->width, &t->height, &t->components); if (t->image == NULL) { fprintf(stderr, "Error: Can't load image file \"%s\".\n", t->name); return 0; } else { printf("%s:%d x %d image loaded with ", t->name, t->width, t->height); printf("%d components\n", t->components); } if (t->components < 3 || t->components > 4) { printf("Error: must be RGB or RGBA image\n"); return 0; } } return 1; } void texenable(struct textures *t) { /* the block below needs to be debugged in a shared memory setting */ #if defined(GL_EXT_texture_object) && !defined(CAVE) if(t->texid != 0) { glBindTextureEXT( GL_TEXTURE_2D, t->texid ); return; } glGenTexturesEXT( 1, &t->texid ); glBindTextureEXT( GL_TEXTURE_2D, t->texid ); #endif glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); #ifdef ALIASED_TEXTURES glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, t->components, t->width, t->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, t->image); #else /* better to use mipmapped, antialiased textures */ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); gluBuild2DMipmaps( GL_TEXTURE_2D, 4, t->width, t->height, GL_RGBA, GL_UNSIGNED_BYTE, t->image ); #endif } /*** furniture ***/ void definefurniture(void) /*** user-defined placement of furniture ***/ { /*** mesh1 ***/ mesh1.placemat[0]=1.0; mesh1.placemat[5]=1.0; mesh1.placemat[10]=1.0; mesh1.placemat[15]=1.0; mesh1.placemat[12]=-5.0; mesh1.placemat[13]=-5.0; mesh1.placemat[14]=-5.0; /*** mesh2 ***/ mesh2.placemat[2]=1.0; mesh2.placemat[5]=1.0; mesh2.placemat[8]=-1.0; mesh2.placemat[15]=1.0; mesh2.placemat[12]=5.0; mesh2.placemat[13]=-5.0; mesh2.placemat[14]=-5.0; /*** pole1 ***/ /* glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(-4.5,0.0,0.0); glTranslatef(0.0,-5.0,0.0); glTranslatef(0.0,0.0,4.5); glGetFloatv(GL_MODELVIEW_MATRIX,pole1.placemat);*/ pole1.placemat[0]=1.0; pole1.placemat[5]=1.0; pole1.placemat[10]=1.0; pole1.placemat[15]=1.0; pole1.placemat[12]=-4.5; pole1.placemat[13]=-5.0; pole1.placemat[14]=4.5; /*** floor1 ***/ floor1.placemat[0]=1.0; floor1.placemat[5]=1.0; floor1.placemat[10]=1.0; floor1.placemat[15]=1.0; floor1.placemat[12]=-5.0; floor1.placemat[13]=-5.0; floor1.placemat[14]=-5.0; } void place(float place[3], float vert[3],float what[16]) { int ii,jj; float temp[4]; GETvec3(temp, vert); temp[3]=1; for(ii=0;ii<3;ii++) { place[ii]=0.0; for(jj=0;jj<4;jj++) place[ii] += temp[jj]*what[ii+4*jj];} } void initfurniture(void) { int ii; float color[3]; definefurniture(); /*** mesh1 ***/ color[0] = 0.3; color[1] = 0.8; color[2] = 0.2; initmesh(&mesh1,10,MAXMESH,color,1); /* 10:width, MAXMESH:gaps,1:texid */ placemesh(&mesh1); /*** mesh2 ***/ color[0] = 0.0; color[1] = 0.8; color[2] = 0.9; initmesh(&mesh2,10,MAXMESH/3,color,0); /* 0 = no texture here */ placemesh(&mesh2); /*** pole1 ***/ color[0] = 1.0; color[1] = 0.27; color[2] = 0.0; initpole(&pole1, 8, 12, 0.5, 10.0,0.50,color,2); /* 8turns 24nodes /turn .5 radius 10 height .5 width color texture */ placepole(&pole1); /*** floor1 ***/ color[0] = 0.0; color[1] = 1.0; color[2] = 0.0; initfloor(&floor1, 10, 6, color,3); /* 10:width, 6:gaps, 3:texture */ placefloor(&floor1); } void deFault(void) { int ii; for(ii=0;ii<16;ii++) starmat[ii]=aff[ii] = (ii/4==ii%4) ? 1 : 0; for(ii=0;ii<16;ii++) myview.duff[ii]=myview.handmat[ii] = (ii/4==ii%4) ? 1 : 0; #ifdef CAVE aff[12]=0; aff[13]= 5; aff[14]= -10; #else aff[12]=0; aff[13]= 0; aff[14]= -15; #endif binoc=0; nose=.06; wnd = 1; siz = 1.; mode=TURNMODE; speed=.1; torq=.02; focal = 2.; far =26.; mysiz=.01; morph=0; mass=25; modal=0; speed=.5; torq=.02; /* experiment with a background flag */ if(bground == 1) bgcolor[0] = bgcolor[1] = bgcolor[2] = 0.8; /*initfurniture(); furn=0;*/ /*SendMessage(HEREICOME);*/ } /*** Graphics routines ***/ void invertaff(float mm[16], float nn[16]){ mm[0]=nn[0]; mm[5]=nn[5]; mm[10]=nn[10]; mm[1]=nn[4]; mm[2]=nn[8]; mm[6]=nn[9]; mm[4]=nn[1]; mm[8]=nn[2]; mm[9]=nn[6]; mm[12]=-nn[12]*nn[0]-nn[13]*nn[1]-nn[14]*nn[2]; mm[13]=-nn[12]*nn[4]-nn[13]*nn[5]-nn[14]*nn[6]; mm[14]=-nn[12]*nn[8]-nn[13]*nn[9]-nn[14]*nn[10]; mm[15]=1; } void printmatrix(GLfloat m[16]) { int ii; printf("\nM={"); for(ii=0; ii<4; ii++) printf("%f,%f,%f,%f\n",m[ii],m[ii+4],m[ii+8],m[ii+12]); printf("\n}"); } /* displace === toylens */ float *displace(int modal, float vert[3]){ float vv[4], ss[3], axis[3], beta, alpha, theta; float vect[3], vect1[3], vect2[3], ntmp, def; float gamma, theta2; float place[3]; float displace[3]; int ii; FOR(ii,0,3)place[ii]=vert[ii]; /* where eye(who) is in world coords */ /* Eye have my doubts about this, this is closer to the heart, gkf 11.6.98 */ vv[0]=VIEW(modal)->duff[12]; vv[1]=VIEW(modal)->duff[13]; vv[2]=VIEW(modal)->duff[14]; for(ii=0;ii<3;ii++){ vv[ii] -= ballwhere[ii]; place[ii] -= ballwhere[ii]; } ss[0]=place[0]-vv[0]; /* last time place is used */ ss[1]=place[1]-vv[1]; ss[2]=place[2]-vv[2]; CROSS(vv,ss,axis); if(NRM(vv)>0.5 && NRM(place)>0.5 && NRM(axis)>0){ /* then you want to displace the vertex else exit*/ gamma = DOT(place,vv)/(NRM(place)*NRM(vv)); beta = acosf( -DOT(ss,vv)/(NRM(ss)*NRM(vv)) ); alpha = mass*NRM(place)/(10*NRM(vv)*(NRM(vv)+NRM(place))); /* theta = 0.5*(beta + sqrt((1-gamma)*alpha + beta*beta));*/ if(!inim) theta = 0.5*(beta + sqrt((1-gamma)*alpha + beta*beta)); else theta = 0.5*(beta - sqrt((1-gamma)*alpha + beta*beta)); CROSS(axis,vv,vect2); ntmp = NRM(vv); vect1[0] = -vv[0]/ntmp; vect1[1] = -vv[1]/ntmp; vect1[2] = -vv[2]/ntmp; ntmp = NRM(vect2); vect2[0] /= ntmp; vect2[1] /= ntmp; vect2[2] /= ntmp; /* FOR(ii,0,3) vect[ii] = NRM(ss)*(cos(theta)*vect1[ii] + sin(theta)*vect2[ii]);*/ if(!inim){ FOR(ii,0,3) vect[ii] = (NRM(ss)+0.1)*(cos(theta)*vect1[ii] + sin(theta)*vect2[ii]); } else { FOR(ii,0,3) vect[ii] = (NRM(vv)+1.1)*(cos(theta)*vect1[ii] + sin(theta)*vect2[ii]); } FOR(ii,0,3) displace[ii] = ballwhere[ii] + vv[ii] + vect[ii]; } else FOR(ii,0,3) displace[ii] = ballwhere[ii] + place[ii]; return displace; } /* end displace */ float *distar(int modal, float vert[3]){ float vv[4], ss[3], axis[3], beta, alpha, theta; float vect[3], vect1[3], vect2[3], ntmp, def; float gamma, theta2; float place[3]; float displace[3]; int ii; FOR(ii,0,3)place[ii]=vert[ii]; /* where eye(who) is in world coords */ vv[0]=VIEW(modal)->duff[12]; vv[1]=VIEW(modal)->duff[13]; vv[2]=VIEW(modal)->duff[14]; for(ii=0;ii<3;ii++){ vv[ii] -= ballwhere[ii]; } ss[0]=place[0]-vv[0]; /* last time place is used */ ss[1]=place[1]-vv[1]; ss[2]=place[2]-vv[2]; CROSS(vv,place,axis); if(NRM(vv)>0.5 && NRM(place)>0.5 && NRM(axis)>0){ /* then you want to displace the vertex else exit*/ gamma = DOT(place,vv)/(NRM(place)*NRM(vv)); beta = acosf( -DOT(place,vv)/(NRM(place)*NRM(vv)) ); alpha = mass*NRM(place)/(10*NRM(vv)*(NRM(vv)+NRM(place))); /* theta = 0.5*(beta + sqrt((1-gamma)*alpha + beta*beta));*/ if(!inim) theta = 0.5*(beta + sqrt((1-gamma)*alpha + beta*beta)); else theta = 0.5*(beta - sqrt((1-gamma)*alpha + beta*beta)); CROSS(axis,vv,vect2); ntmp = NRM(vv); vect1[0] = -vv[0]/ntmp; vect1[1] = -vv[1]/ntmp; vect1[2] = -vv[2]/ntmp; ntmp = NRM(vect2); vect2[0] /= ntmp; vect2[1] /= ntmp; vect2[2] /= ntmp; /* FOR(ii,0,3) vect[ii] = NRM(ss)*(cos(theta)*vect1[ii] + sin(theta)*vect2[ii]);*/ if(!inim){ FOR(ii,0,3) vect[ii] = (NRM(place)+0.1)*(cos(theta)*vect1[ii] + sin(theta)*vect2[ii]); } else { FOR(ii,0,3) vect[ii] = (NRM(place)+1.1)*(cos(theta)*vect1[ii] + sin(theta)*vect2[ii]); } FOR(ii,0,3) displace[ii] = vect[ii]; } else FOR(ii,0,3) displace[ii] = vert[ii]; return displace; } /* end distar */ /*** Audio ***/ 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 audiofunc(void) { } void audioclean(void) { #ifdef SOUND AUDterminate(audiohandle); EndSoundServer(); #endif } /*** Navigation ***/ #ifdef CAVE void cavetrack(void) { float head_pos[3], wand_pos[3], wand_or[3]; static float ohead_pos[3], owand_pos[3]; static int opaw = 0, paw, joy = 0; static int friz = 0; paw = wnd ? (CAVEBUTTON1*2+CAVEBUTTON2)*2+CAVEBUTTON3 : mauspaw; if(paw) joy = 1; /*** middle button ***/ if(opaw!=2 && paw==2) /* cycle the modes */ modal = (modal+1)%(*CAVENumUsers); if(opaw == 2 && paw == 3) /* shrink object */ siz /= 1.5; if(opaw == 2 && paw == 6) /* grow object */ siz *= 1.5; if(opaw==2 && paw == 7) /* reset */ {deFault(); SET(ohead_pos,0.,0.,0.); SET(owand_pos,0.,0.,0.); } /*** right button ***/ if(opaw == 1 && paw == 1) friz = 1-friz; if(opaw == 1 && paw == 3) /* decrease mass */ if(mass > 2) mass -= 2; if(opaw == 1 && paw == 5) /* increase mass */ mass += 2; /*** left button ***/ myview.launch = 0; /* clean this logic up someday */ if(opaw != 4 && paw == 4) /* acquire bull */ myview.launch = 1; if(opaw == 4 && paw == 4) /* hold bull */ myview.launch = 3; if(opaw == 4 && paw != 4) /* release bull */ myview.launch = 2; /*** query tracker ***/ CAVEGetSensorPosition(CAVESENSOR(0),CAVE_TRACKER_FRAME,head_pos); CAVEGetSensorPosition(CAVESENSOR(1),CAVE_TRACKER_FRAME,wand_pos); CAVEGetSensorOrientation(CAVESENSOR(1),CAVE_TRACKER_FRAME,wand_or); /*** build handmat ***/ glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslatef(wand_pos[0]-head_pos[0], wand_pos[1]-head_pos[1], wand_pos[2]-head_pos[2]); glRotatef(wand_or[0], 1.,0.,0.); glRotatef(wand_or[1],0.,1.,0.); glRotatef(wand_or[2],0.,0.,1.); glGetFloatv(GL_MODELVIEW_MATRIX,myview.handmat); glPopMatrix(); /*** update aff ***/ glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslatef(ohead_pos[0]-head_pos[0], ohead_pos[1]-head_pos[1], ohead_pos[2]-head_pos[2]); /* torq is broken right now, the .02 is a hacked fix */ if(!friz) /* if not parked */ { glRotatef(wand_or[0]*(-.02), 1.,0.,0.); glRotatef(wand_or[1]*(-.02),0.,1.,0.); glRotatef(wand_or[2]*(-.02),0.,0.,1.); } /*** Joystick ***/ { float thumbX, thumbY ; /* -1 to +1 */ thumbX = CAVE_JOYSTICK_X ; thumbY = CAVE_JOYSTICK_Y ; if(joy && (fabsf(thumbX) > .02 || fabsf(thumbY)) > .02) glTranslatef(thumbX*speed, 0. , thumbY*speed); } /* temporary; end scope of local variables thumbX,thumbY */ /* This wedges the joystick in the simulator, kill it if it interferes with CAVE */ /* It might also correct joystick drift in a bad tracking situation */ glTranslatef(right*speed,0.,forwd*speed); /*** Tractor ***/ if(friz) glTranslatef(wand_pos[0]-owand_pos[0], wand_pos[1]-owand_pos[1], wand_pos[2]-owand_pos[2]); /*** mult and get aff ***/ glMultMatrixf(aff); glGetFloatv(GL_MODELVIEW_MATRIX,aff); glPopMatrix(); /*** Update ***/ /* do a memcopy here someday */ {int ii; for(ii=0;ii<12;ii++) starmat[ii]=aff[ii];} opaw=paw; CPY(ohead_pos,head_pos); CPY(owand_pos,wand_pos); audiofunc(); /*printf("%f,%f,%f\n",head_pos[0],head_pos[1],head_pos[2]); printmatrix(aff);*/ } /*end cavetrack */ #endif 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(aff[12],aff[13],aff[14]); if(!frozturn){ glRotatef(dx*torq,0.,1.,0.); glRotatef(dy*torq,1.,0.,0.); } if(but&(1<app_data); messtype=*(int *)buffer; switch (messtype){ case HEREIAM:{ struct herestruct *heremsg; heremsg=((struct herestruct *)buffer); CAVESetWriteLock(theview->viewlock); memcpy(theview->duff, heremsg->duff, 16*sizeof(float)); memcpy(theview->handmat, heremsg->handmat, 16*sizeof(float)); theview->launch = heremsg->launch; CAVEUnsetWriteLock(theview->viewlock); break; printf("got it\n"); } case HEREICOME:{ struct comestruct *comemsg; comemsg=((struct comestruct *)buffer); CAVESetWriteLock(theview->viewlock); theview->viewnum=comemsg->viewnum; theview->color[0]=comemsg->color[0]; theview->color[1]=comemsg->color[1]; theview->color[2]=comemsg->color[2]; CAVEUnsetWriteLock(theview->viewlock); printf("Other's col is %f,%f,%f\n",theview->color[0],theview->color[1],theview->color[2]); break; } } } void AddUser(CAVE_USER_ST *user,void *app_data) { struct view *newview; newview=user->app_data=CAVEMalloc(sizeof(struct view)); ((struct view *)user->app_data)->viewlock=CAVENewLock(); SendMessage(HEREICOME); printf("Added user\n"); } void DeleteUser(CAVE_USER_ST *user,void *app_data) { CAVEFree(user->app_data); printf("Mem freed\n"); } void netinit(void) { CAVEUser[0]->app_data=&myview; myview.viewlock=CAVENewLock(); myview.viewnum=*CAVENumUsers; /*printf("My num is %d\n",myview.viewnum);*/ switch(myview.viewnum){ case 1:SET(myview.color, 1, 0, 0);break; case 2:SET(myview.color, 0, 1, 0);break; case 3:SET(myview.color, 0, 0, 1);break; case 4:SET(myview.color, 1, 0, 1);break; default :SET(myview.color, 1, 1, 0);break; } SendMessage(HEREICOME); } void caveframe(void) { int ii; if(!CAVEMasterDisplay()) { CAVEDisplayBarrier; return; } CAVEDisplayBarrier; cavetrack(); invertaff(myview.duff,aff); SendMessage(HEREIAM); } void drawcaveinit(void) { CAVEFar = 1000.; glClearColor(0.,0.,0.,0.); glClearDepth(1.); } #endif /*** there are too many push/pop's in the layers of dravatar!!! ***/ void dravatars(void) { int ii; for(ii=0;ii<*CAVENumUsers;ii++) { glPushMatrix(); glMultMatrixf(VIEW(ii)->duff); if(ii)drawface(ii); glMultMatrixf(VIEW(ii)->handmat); /* has headshift in it */ drawhand(ii); glPopMatrix(); } } void drawfurniture(int who) { drawmesh(who,&mesh1,3); drawmesh(who,&mesh2,0); drawpole(who,&pole1,3); drawfloor(who,&floor1,3); if(inimyes) { inim=1; drawmesh(who,&mesh1,3); drawmesh(who,&mesh2,0); drawpole(who,&pole1,3); drawfloor(who,&floor1,3); inim=0; } } void drawall(void) { int ii; #ifdef GL_MULTISAMPLE_SGIS glEnable( GL_MULTISAMPLE_SGIS ); #endif /* dravatars(); */ glPushMatrix(); /* glutWireIcosahedron();*/ drawball(); glPopMatrix(); /* FOR(ii,0,*CAVENumUsers){glPushMatrix(); drawbulls(0,ii); glPopMatrix();} glPushMatrix();*/ drawfurniture(modal); /* glPopMatrix(); */ /* gkf slevy */ } #ifdef CAVE void drawcave(void) { float head_pos[3]; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawstars(modal); CAVEGetSensorPosition(CAVESENSOR(0),CAVE_TRACKER_FRAME,head_pos); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(head_pos[0],head_pos[1],head_pos[2]); glMultMatrixf(aff); /* glScalef(siz,siz,siz);*/ drawall(); glPopMatrix(); } #endif void drawcons(void){ glClearColor(bgcolor[0],bgcolor[1],bgcolor[2],0.); /* grey sky gkf */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if(binoc) glViewport(0,yt/4,xt/2,yt/2); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-mysiz*xt/yt,mysiz*xt/yt,-mysiz,mysiz,mysiz*focal,far); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); drawstars(modal); glTranslatef(-binoc*nose,0.0,0.0); glMultMatrixf(aff); drawall(); if(binoc){ glViewport(xt/2,yt/4,xt/2,yt/2); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); drawstars(modal); glTranslatef(binoc*nose,0.0,0.0); glMultMatrixf(aff); drawall(); } glViewport(0,0,xt,yt); /* if(msg) messages();*/ glutSwapBuffers(); } void idle(void){ /*do this when nothing else is happening*/ /* if(morph) autotymer(0);*/ /* advance autotymer */ chaptrack(BUT,XX,YY,SHIF); invertaff(myview.duff,aff); glutPostRedisplay(); audiofunc(); } void mousepushed(int but,int stat,int x,int y){ if(stat==GLUT_DOWN) BUT |= (1<M?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 */ TOGGLE(' ', mode); /* fly/turn modes */ 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 */ PRESS('m', if(mass > 2) mass -= 2, mass += 2); IF(27) {audioclean(); exit(0); } /* ESC exit */ } void special_keybo(int key, int x, int y){ if(key==GLUT_KEY_HOME){frozturn = 1-frozturn; } if(key==GLUT_KEY_INSERT){frozball = 1-frozball; } /* gkf */ } void arguments(int argc,char **argv) { extern char *optarg; extern int optind; int chi; /* w: needs ONE number after -w, c means NO number follows*/ while ((chi = getopt(argc,argv,"w:d:g:b:")) != -1) switch(chi) {case 'w': win=atoi(optarg); break; case 'g': gap0=atof(optarg); break; case 'b': bground=atoi(optarg);break; } if (optind!=argc) fprintf(stderr,"%s: Incorrect usage\n",argv[0]); } void getmem(void) { #ifdef CAVE s_var = CAVEMalloc(sizeof(struct share_var)); #endif s_var = malloc(sizeof(struct share_var)); memset(s_var, 0, sizeof(struct share_var)); /* textures assumed 0-filled */ if(s_var==NULL) {fprintf(stderr,"No room to share! %x \n",s_var); exit(1);} } void dataprep(void) { int ii; initstars(); audioprep(); if(texyes) { definetextures(); for(ii=0;ii<3;ii++) texinit(texture+ii); } initfurniture(); deFault(); ballpitch=ballyes; } void main(int argc, char **argv) { arguments(argc,argv); #ifdef CAVE CAVESetOption(CAVE_NET_UPDATELOCALDATA, 1); CAVEConfigure(&argc, argv, NULL); #endif getmem(); dataprep(); #ifdef CAVE CAVEAddCallback(CAVE_NETADDUSER_CALLBACK, AddUser, NULL); CAVEAddCallback(CAVE_NETDELETEUSER_CALLBACK, DeleteUser, NULL); CAVEAddCallback(CAVE_NETAPPDATA_CALLBACK, RecvMessage, NULL); CAVEInit(); /* Each wall is (part of) a forked process from here on.*/ CAVEFrameFunction(caveframe,0); /*is restricted to MasterWall, so once per frame */ CAVEInitApplication(drawcaveinit, 0); netinit(); CAVEDisplay(drawcave, 0); while(!CAVEgetbutton(CAVE_ESCKEY)) { /* cavekeybo(); moved to caveframe */ sginap(5); /* or sleep(.01) = sginap(1) seconds */ } audioclean(); CAVEExit(); #else /** console **/ glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE); switch(win) { case 0: break; case 1: glutInitWindowSize(640, 480); glutInitWindowPosition(0,1024-480); break; case 2: glutInitWindowPosition(0,0); break; } glutCreateWindow("<* Lens 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(); #endif }