Picking issue with gluUnproject()

Hi there. I’m trying to debug an issue with opengl ES.

What’s happening is that I’m doing a ray-picking algorithm to try and figure out where a point is on an NxM plane that spans -10,+10 in the X-Z plane, with a constant Y, using gluUnproject() to find the vector running from near to far and iterating along it. (Given the constancy of the Y coordinate, there are much more efficient ways to do this, but I want to get it to work first.

It’s essentially working with one teensy little enormous issue - if there is a translational component, at least in the Y direction, it fails. I’ve verified that the issue is that when calling gluUnproject(), the coordinates returned are not actually on the correct line. Since I’m using an “imported” gluUnproject() due to the ES nature of the openGL, it’s possible this function isn’t written correctly ; I scarfed one off the net somewhere and adapted it to my purpose.

Has anyone seen this issue? I’ve posted the unproject source I’m using in case there are any obvious issues. My knowledge of linear algebra and the model->projection->viewport process is not sufficient to debug the math.

Thanks.

int gluUnProject2(GLfloat winx, GLfloat winy , GLfloat winz,
const GLfloat modelMatrix[16],
const GLfloat projMatrix[16],
const GLint viewport[4],
GLfloat *objx, GLfloat *objy, GLfloat *objz)
{
GLfloat finalMatrix[16];
GLfloat in[4];
GLfloat out[4];

__gluMultMatricesd(modelMatrix, projMatrix, finalMatrix);
if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return(GL_FALSE);

in[0]=winx;
in[1]=winy;
in[2]=winz;
in[3]=1.0f;

/* Map x and y from window coordinates */
in[0] = (in[0] - viewport[0]) / viewport[2];
in[1] = (in[1] - viewport[1]) / viewport[3];

/* Map to range -1 to 1 */
in[0] = in[0] * 2 - 1;
in[1] = in[1] * 2 - 1;
in[2] = in[2] * 2 - 1;

__gluMultMatrixVecd(finalMatrix, in, out);
if (out[3] == 0.0f) return(GL_FALSE);
out[0] /= out[3];
out[1] /= out[3];
out[2] /= out[3];
*objx = out[0];
*objy = out[1];
*objz = out[2];
return(GL_TRUE);

}

static void __gluMultMatricesd(const GLfloat a[16], const GLfloat b[16],
GLfloat r[16])
{
int i, j;

for (i = 0; i < 4; i++) {
	for (j = 0; j < 4; j++) {
		r[i*4+j] = 
		a[i*4+0]*b[0*4+j] +
		a[i*4+1]*b[1*4+j] +
		a[i*4+2]*b[2*4+j] +
		a[i*4+3]*b[3*4+j];
	}
}

}

static void __gluMultMatrixVecd(const GLfloat matrix[16], const GLfloat in[4],
GLfloat out[4])
{
int i;

for (i=0; i<4; i++) {
	out[i] = 
    in[0] * matrix[0*4+i] +
    in[1] * matrix[1*4+i] +
    in[2] * matrix[2*4+i] +
    in[3] * matrix[3*4+i];
}

}

static int __gluInvertMatrixd(const GLfloat src[16], GLfloat inverse[16])
{
int i, j, k, swap;
GLfloat t;
GLfloat temp[4][4];

for (i=0; i<4; i++) {
	for (j=0; j<4; j++) {
		temp[i][j] = src[i*4+j];
	}
}
__gluMakeIdentityd(inverse);

for (i = 0; i < 4; i++) {
	/*
	 ** Look for largest element in column
	 */
	swap = i;
	for (j = i + 1; j < 4; j++) {
		if (fabs(temp[j][i]) > fabs(temp[i][i])) {
			swap = j;
		}
	}
	
	if (swap != i) {
		/*
		 ** Swap rows.
		 */
		for (k = 0; k < 4; k++) {
			t = temp[i][k];
			temp[i][k] = temp[swap][k];
			temp[swap][k] = t;
			
			t = inverse[i*4+k];
			inverse[i*4+k] = inverse[swap*4+k];
			inverse[swap*4+k] = t;
		}
	}
	
	if (temp[i][i] == 0) {
		/*
		 ** No non-zero pivot.  The matrix is singular, which shouldn't
		 ** happen.  This means the user gave us a bad matrix.
		 */
		return GL_FALSE;
	}
	
	t = temp[i][i];
	for (k = 0; k < 4; k++) {
		temp[i][k] /= t;
		inverse[i*4+k] /= t;
	}
	for (j = 0; j < 4; j++) {
		if (j != i) {
			t = temp[j][i];
			for (k = 0; k < 4; k++) {
				temp[j][k] -= temp[i][k]*t;
				inverse[j*4+k] -= inverse[i*4+k]*t;
			}
		}
	}
}
return GL_TRUE;

}

static void __gluMakeIdentityd(GLfloat m[16])
{
m[0+40] = 1; m[0+41] = 0; m[0+42] = 0; m[0+43] = 0;
m[1+40] = 0; m[1+41] = 1; m[1+42] = 0; m[1+43] = 0;
m[2+40] = 0; m[2+41] = 0; m[2+42] = 1; m[2+43] = 0;
m[3+40] = 0; m[3+41] = 0; m[3+42] = 0; m[3+43] = 1;
}

That should be “If there is a translational component, at least in the Z direction”.

Hi,
The method looks correct to me. The only thing I can say is are u sure your inverse is ok. Could u try and use some existing math library like glm for matrix stuff and see if u still get the error.

Regards,
Mobeen