Path: utzoo!censor!geac!torsqnt!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!usc!ucsd!pacbell.com!ames!sgi!shinobu!odin!thor.corp.sgi.com!kj From: kj@thor.corp.sgi.com (Kenneth Harris) Newsgroups: comp.sys.sgi Subject: Re: Problems with mapw() in GL on Personal Iris Keywords: Silicon Graphics, 3D-Pick, GL (Graphic Language) Message-ID: <1990Nov30.060427.18685@odin.corp.sgi.com> Date: 30 Nov 90 06:04:27 GMT References: Silicon Graphics, 3D-Pick, GL (Graphic Language) <3238@zgdvda.zgdvda.uucp> Sender: news@odin.corp.sgi.com (Net News) Reply-To: kj@thor.corp.sgi.com (Kenneth Harris) Organization: Silicon Graphics Inc. Lines: 513 Here's my favorite mapw program: # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by guest on Fri Nov 30 06:01:33 GMT 1990 # Contents: README main.c makefile mymapw.c echo x - README sed 's/^@//' > "README" <<'@//E*O*F README//' This is the code I use to do mapw. Basically, I got the source and rewrote it to make sense. To run the program type "make mymapw", then "mymapw". You can then pick a screen coordinate with the left mouse. It will appear as a point. You can then manipulate the view of the scene by press the "1" or "2" key and moving mousex. The picked point will then appear as a line. @//E*O*F README// chmod u=rw,g=r,o=r README echo x - main.c sed 's/^@//' > "main.c" <<'@//E*O*F main.c//' #include #include #include # define DEBUG(variable,type) fprintf(stderr,"variable = %type\n",variable) long getdval(dev) Device dev; /* get delta valuator */ { static long valtab[VALCOUNT]; long val; int ival; if (ISVALUATOR(dev)) { ival=dev-VALOFFSET; val=valtab[ival]; valtab[ival]=getvaluator(dev); return(valtab[ival]-val); } } long getdbut(dev) Device dev; /* get delta button */ /* -1 : up transtion 0 : steady state 1 : down transition */ { static long valtab[BUTCOUNT]; long val; int ival; if (ISBUTTON(dev)) { ival=dev-BUTOFFSET; val=valtab[ival]; valtab[ival]=getbutton(dev); return(valtab[ival]-val); } } long gated(but,val) Device but,val; /* "gate" a valuator with a button */ { if (getdbut(but) == 1) (void) getdval(val); if (getbutton(but)) return(getdval(val)); else return(0); } extern void mymapw(Screencoord sx,Screencoord sy,float unitz,float world[]); main() { long dev; int focus; short val; int domap; int rx,ry; int mx,my; float v1[3],v2[3]; int done; winopen("mapw"); doublebuffer(); gconfig(); /* ortho(-1.0,1.0,-1.0,1.0,-10.0,10.0); */ perspective(450,1.0,0.5,10.0); qenter(REDRAW); qdevice(ESCKEY); qdevice(DIAL0); qdevice(DIAL1); setvaluator(DIAL0,0,-30000,30000); setvaluator(DIAL1,0,-30000,30000); qdevice(LEFTMOUSE); qdevice(MIDDLEMOUSE); done=FALSE; while(!done){ while (qtest()) { dev=qread(&val); if (dev == ESCKEY) { done=TRUE; } else if (dev == INPUTCHANGE) { focus=val; } else if (dev == DIAL0) { rx=val; } else if (dev == DIAL1) { ry=val; } else if (dev == LEFTMOUSE) { if (val == 1) { mx=getvaluator(MOUSEX); my=getvaluator(MOUSEY); domap=TRUE; } } else if (dev == REDRAW) { reshapeviewport(); } else printf("dev,val:%d %d\n",dev,val); } if (focus) { rx += gated(ONEKEY,MOUSEX); ry += gated(TWOKEY,MOUSEX); } color(BLACK); clear(); pushmatrix(); polarview(4.0,rx,ry,0); if (domap) { domap=FALSE; mymapw(mx,my,-1.0,v1); mymapw(mx,my, 1.0,v2); } color(WHITE); drawaxes(); /* bgnline(); v3f(v1); v3f(v2); endline(); */ move(v1[0],v1[1],v1[2]); draw(v2[0],v2[1],v2[2]); popmatrix(); swapbuffers(); } } drawaxes() /* draw unit axes */ { cmov( 0.0, 0.0, 0.0); charstr("0"); cmov( 1.0, 0.0, 0.0); charstr("+x"); cmov(-1.0, 0.0, 0.0); charstr("-x"); cmov( 0.0, 1.0, 0.0); charstr("+y"); cmov( 0.0,-1.0, 0.0); charstr("-y"); cmov( 0.0, 0.0, 1.0); charstr("+z"); cmov( 0.0, 0.0,-1.0); charstr("-z"); } @//E*O*F main.c// chmod u=rw,g=r,o=r main.c echo x - makefile sed 's/^@//' > "makefile" <<'@//E*O*F makefile//' CFLAGS = -g LDFLAGS = -lgl_s -lm OBJECTS = main.o mymapw.o CCF = $(CC) $(CFLAGS) main: $(OBJECTS) $(CCF) $(OBJECTS) $(LDFLAGS) -o $@ @//E*O*F makefile// chmod u=rw,g=r,o=r makefile echo x - mymapw.c sed 's/^@//' > "mymapw.c" <<'@//E*O*F mymapw.c//' #include #include #include /*---------------------------------------------------------------------*/ /* y = x * mat ; transform a 4d vector through a 4x4 matrix /*---------------------------------------------------------------------*/ static transform4d (float y[],float x[],Matrix mat) { int i,j; for (i=0;i<4;i++) { y[i]=0; for (j=0;j<4;j++) y[i] += x[j] * mat[j][i]; } } /*---------------------------------------------------------------------*/ /* new = [left][right] ; multiply two matrices together /*---------------------------------------------------------------------*/ static multmatrix4d (Matrix new,Matrix left,Matrix right) { transform4d (new[0],left[0],right); transform4d (new[1],left[1],right); transform4d (new[2],left[2],right); transform4d (new[3],left[3],right); } /*---------------------------------------------------------------------*/ /* to = from.invert ; invert a matrix - to can be the same as from /* ??? should be merged with gl_invertmat??? /*---------------------------------------------------------------------*/ static invert4d (Matrix to,Matrix from) { float wtemp[4][8]; register float m0,m1,m2,m3,s; register float *r0,*r1,*r2,*r3, *rtemp; r0 = wtemp[0]; r1 = wtemp[1]; r2 = wtemp[2]; r3 = wtemp[3]; r0[0] = from[0][0]; /* build up [A][I] */ r0[1] = from[0][1]; r0[2] = from[0][2]; r0[3] = from[0][3]; r0[4] = 1.0; r0[5] = 0.0; r0[6] = 0.0; r0[7] = 0.0; r1[0] = from[1][0]; r1[1] = from[1][1]; r1[2] = from[1][2]; r1[3] = from[1][3]; r1[4] = 0.0; r1[5] = 1.0; r1[6] = 0.0; r1[7] = 0.0; r2[0] = from[2][0]; r2[1] = from[2][1]; r2[2] = from[2][2]; r2[3] = from[2][3]; r2[4] = 0.0; r2[5] = 0.0; r2[6] = 1.0; r2[7] = 0.0; r3[0] = from[3][0]; r3[1] = from[3][1]; r3[2] = from[3][2]; r3[3] = from[3][3]; r3[4] = 0.0; r3[5] = 0.0; r3[6] = 0.0; r3[7] = 1.0; if (r0[0] == 0.0) { /* swap rows if needed */ if (r1[0] == 0.0) { if (r2[0] == 0.0) { if (r3[0] == 0.0) goto singular; rtemp = r0; r0 = r3; r3 = rtemp; } else { rtemp = r0; r0 = r2; r2 = rtemp; } } else { rtemp = r0; r0 = r1; r1 = rtemp; } } m1 = r1[0]/r0[0]; /* eliminate first variable */ m2 = r2[0]/r0[0]; m3 = r3[0]/r0[0]; s = r0[1]; r1[1] = r1[1] - m1 * s; r2[1] = r2[1] - m2 * s; r3[1] = r3[1] - m3 * s; s = r0[2]; r1[2] = r1[2] - m1 * s; r2[2] = r2[2] - m2 * s; r3[2] = r3[2] - m3 * s; s = r0[3]; r1[3] = r1[3] - m1 * s; r2[3] = r2[3] - m2 * s; r3[3] = r3[3] - m3 * s; s = r0[4]; if (s != 0.0) { r1[4] = r1[4] - m1 * s; r2[4] = r2[4] - m2 * s; r3[4] = r3[4] - m3 * s; } s = r0[5]; if (s != 0.0) { r1[5] = r1[5] - m1 * s; r2[5] = r2[5] - m2 * s; r3[5] = r3[5] - m3 * s; } s = r0[6]; if (s != 0.0) { r1[6] = r1[6] - m1 * s; r2[6] = r2[6] - m2 * s; r3[6] = r3[6] - m3 * s; } s = r0[7]; if (s != 0.0) { r1[7] = r1[7] - m1 * s; r2[7] = r2[7] - m2 * s; r3[7] = r3[7] - m3 * s; } if (r1[1] == 0.0) { /* swap rows if needed */ if (r2[1] == 0.0) { if (r3[1] == 0.0) goto singular; rtemp = r1; r1 = r3; r3 = rtemp; } else { rtemp = r1; r1 = r2; r2 = rtemp; } } m2 = r2[1]/r1[1]; /* eliminate second variable */ m3 = r3[1]/r1[1]; r2[2] = r2[2] - m2 * r1[2]; r3[2] = r3[2] - m3 * r1[2]; r3[3] = r3[3] - m3 * r1[3]; r2[3] = r2[3] - m2 * r1[3]; s = r1[4]; if (s != 0.0) { r2[4] = r2[4] - m2 * s; r3[4] = r3[4] - m3 * s; } s = r1[5]; if (s != 0.0) { r2[5] = r2[5] - m2 * s; r3[5] = r3[5] - m3 * s; } s = r1[6]; if (s != 0.0) { r2[6] = r2[6] - m2 * s; r3[6] = r3[6] - m3 * s; } s = r1[7]; if (s != 0.0) { r2[7] = r2[7] - m2 * s; r3[7] = r3[7] - m3 * s; } if (r2[2] == 0.0) { /* swap last 2 rows if needed */ if (r3[2] == 0.0) goto singular; rtemp = r2; r2 = r3; r3 = rtemp; } m3 = r3[2]/r2[2]; /* eliminate third variable */ r3[3] = r3[3] - m3 * r2[3]; r3[4] = r3[4] - m3 * r2[4]; r3[5] = r3[5] - m3 * r2[5]; r3[6] = r3[6] - m3 * r2[6]; r3[7] = r3[7] - m3 * r2[7]; if (r3[3] == 0.0) goto singular; s = 1.0/r3[3]; /* now back substitute row 3 */ r3[4] = r3[4] * s; r3[5] = r3[5] * s; r3[6] = r3[6] * s; r3[7] = r3[7] * s; m2 = r2[3]; /* now back substitute row 2 */ s = 1.0/r2[2]; r2[4] = s * (r2[4] - r3[4] * m2); r2[5] = s * (r2[5] - r3[5] * m2); r2[6] = s * (r2[6] - r3[6] * m2); r2[7] = s * (r2[7] - r3[7] * m2); m1 = r1[3]; r1[4] = (r1[4] - r3[4] * m1); r1[5] = (r1[5] - r3[5] * m1); r1[6] = (r1[6] - r3[6] * m1); r1[7] = (r1[7] - r3[7] * m1); m0 = r0[3]; r0[4] = (r0[4] - r3[4] * m0); r0[5] = (r0[5] - r3[5] * m0); r0[6] = (r0[6] - r3[6] * m0); r0[7] = (r0[7] - r3[7] * m0); m1 = r1[2]; /* now back substitute row 1 */ s = 1.0/r1[1]; r1[4] = s * (r1[4] - r2[4] * m1); r1[5] = s * (r1[5] - r2[5] * m1); r1[6] = s * (r1[6] - r2[6] * m1); r1[7] = s * (r1[7] - r2[7] * m1); m0 = r0[2]; r0[4] = (r0[4] - r2[4] * m0); r0[5] = (r0[5] - r2[5] * m0); r0[6] = (r0[6] - r2[6] * m0); r0[7] = (r0[7] - r2[7] * m0); m0 = r0[1]; /* now back substitute row 0 */ s = 1.0/r0[0]; r0[4] = s * (r0[4] - r1[4] * m0); r0[5] = s * (r0[5] - r1[5] * m0); r0[6] = s * (r0[6] - r1[6] * m0); r0[7] = s * (r0[7] - r1[7] * m0); to[0][0] = r0[4]; /* copy results back */ to[0][1] = r0[5]; to[0][2] = r0[6]; to[0][3] = r0[7]; to[1][0] = r1[4]; to[1][1] = r1[5]; to[1][2] = r1[6]; to[1][3] = r1[7]; to[2][0] = r2[4]; to[2][1] = r2[5]; to[2][2] = r2[6]; to[2][3] = r2[7]; to[3][0] = r3[4]; to[3][1] = r3[5]; to[3][2] = r3[6]; to[3][3] = r3[7]; return; singular: fprintf(stderr,"invert4d"); return; } static void scr2unit(Screencoord sx,Screencoord sy,float unit[]) /* convert from screen coordinates to unit cube coordinates */ { Screencoord vl, vr, vb, vt; long ox,oy; getorigin(&ox,&oy); /* 4d getviewport isn't screen coords */ sx -= ox; sy -= oy; getviewport (&vl,&vr,&vb,&vt); unit[0] = (2.0*sx - vl - vr)/(vr - vl + 1); unit[1] = (2.0*sy - vb - vt)/(vt - vb + 1); } static void unit2world(float unit[],float world[]) /* convert from unit cube coordinates to world coordinates */ { Matrix mat,minv; Coord homo[4]; /* following three statements equivalent to "inverse xfpt" */ if (getmmode() == MVIEWING) { Matrix v,p; mmode(MPROJECTION); getmatrix(p); mmode(MVIEWING); getmatrix(v); multmatrix4d(mat,v,p); } else if (getmmode() == MSINGLE) { getmatrix(mat); } else { fprintf(stderr,"Unknown mmode\n"); } invert4d (minv,mat); transform4d(homo,unit,minv); /* now we have the point in the "homogeneous" coordinate system */ /* do so-called perspective division */ world[0] = homo[0]/homo[3]; world[1] = homo[1]/homo[3]; world[2] = homo[2]/homo[3]; } void mymapw(Screencoord sx,Screencoord sy,float unitz,float world[]) /* * convert from screen coords to world coords * "unitz" is an arbitrary value in the unit cube coord sys */ { Coord unit[4]; scr2unit(sx,sy,unit); unit[2] = unitz; unit[3] = 1.0; /* now we have the point in the "unit cube" coordinate system */ unit2world(unit,world); /* now we have the point in the "world" coordinate system */ } @//E*O*F mymapw.c// chmod u=rw,g=r,o=r mymapw.c exit 0