[comp.sys.sgi] Problems with mapw

boehmk@zgdvda.zgdvda.uucp (Klaus Boehm) (11/07/90)

I have a problem with the 'mapw()'-Function of the GL of the Personal
IRIS machine.
Problem is, that the function is executed, but the two points in the
3 dimensional wolrd surely do not fit to the mouse position given. In
fact they biuld up a 3D-line, which dosn't really differ from the 3D-
line, which can be build using the eyepoint and the viewpoint of the
'lookat()'-Function. Additionally, the two Points delivered from mapw()
are always the same, they are independent of the mouse position, which,
of course, they should not be.
In my program I only use the perspective()- and the lookat()-Functions.
The viewing object, which has to be passed to the mapw()-Function, gets
the same perspective() and lookat() calls which I also use to render my
data.
The question is, if anybody out there has experience with using mapw().
Maybe there are certain circumstances under which mapw() works properly
or could never work.
It would also be great, if anybody could send a part of a sample Program
to me. I am not able to use the pick()-Function.

Hope to hear anything
Klaus

" ratcliffe) (11/10/90)

In article <3238@zgdvda.zgdvda.uucp> boehmk@zgdvda.uucp writes:
>
>
>I have a problem with the 'mapw()'-Function of the GL of the Personal
>IRIS machine.
>It would also be great, if anybody could send a part of a sample Program
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>to me. I am not able to use the pick()-Function.
>
>Hope to hear anything
>Klaus

perhaps the below example will be useful:

/*
 *   mapw:
 *
 *    Bare-bones example demonstrates use of MAPW(3G) for determining a line
 *  in 3-space given a 2-D screen space point.  Note that the "line" drawn
 *  after the call to MAPW(3G) simply looks like a green point.  This is
 *  exactly as it should be--i.e. drawing a line from the first to the
 *  second point returned by mapw *should* appear to the viewer's eye as if
 *  it is simply a point in space
 *
 *                                      ratman - 1987
 */

#include <gl/gl.h>
#include <gl/device.h>

#define VOBJ 6

main()
{
    Screencoord scrx, scry;
    Coord wx1, wy1, wz1, wx2, wy2, wz2;
    short screenx, screeny, val;
    long xorig, yorig;
    Device dev;


    prefsize(512,512);
    winopen("mapw_test");
    qdevice(LEFTMOUSE);
    qdevice(ESCKEY);
    color(BLACK);
    clear();
    perspective(440,1.0,1.0,1500.0);

    makeobj(VOBJ);
        perspective(440,1.0,1.0,1500.0);
    closeobj();

    getorigin(&xorig, &yorig);

    while (TRUE) {
        dev = qread(&val);
        switch(dev) {
            case LEFTMOUSE:
                if (val) {
                    scrx = (short) getvaluator(MOUSEX) - xorig;   
                    scry = (short) getvaluator(MOUSEY) - yorig;  
                    callobj(VOBJ);
                    mapw(VOBJ,scrx,scry,&wx1,&wy1,&wz1,&wx2,&wy2,&wz2);

                    /* only get values +/- 1.0 for wz1 */
                    printf("wx1=%.2f  wy1=%.2f  wz1=%.2f  ", wx1, wy1, wz1);
                    printf("wx2=%.2f  wy2=%.2f  wz2=%.2f\n", wx2, wy2, wz2);
		    color(BLACK);
		    clear();
		    color(GREEN);
		    move(wx1, wy1, wz1);
		    draw(wx2, wy2, wz2);
                }
                break;
            case REDRAW:
                getorigin(&xorig, &yorig);
		reshapeviewport();
                callobj(VOBJ);
		color(BLACK);
		clear();
                break;
            case ESCKEY:
                gexit();
                exit(0);
                break;

        }
    }
}

kj@thor.corp.sgi.com (Kenneth Harris) (11/30/90)

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