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