Problems with mapw() in GL on Personal Iris
Kenneth Harris
kj at thor.corp.sgi.com
Fri Nov 30 17:04:27 AEST 1990
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 <gl.h>
#include <device.h>
#include <stdio.h>
# 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 <gl.h>
#include <device.h>
#include <stdio.h>
/*---------------------------------------------------------------------*/
/* 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
More information about the Comp.sys.sgi
mailing list