glReadPixels/gluUnproject problem

I am trying to determine the location on a sphere where the mouse is clicked (in world coordinates).

I am able to get the mouse X and Y (of course), but I am having a lot of trouble getting the screen Z value.

I am trying to determine the z-value of a pixel using glReadPixels(…GL_DEPTH_COMPONENT…), but the only return value I get (for ANY x,y) is 1.0.

Here is my code (MFC):

GLdouble modelView[16];
GLdouble projection[16];
GLint viewport[4];

GLdouble sx, sy, sz;

glGetDoublev (GL_MODELVIEW_MATRIX,	modelView);
glGetDoublev (GL_PROJECTION_MATRIX,	projection);
glGetIntegerv(GL_VIEWPORT,			viewport);

CRect rect;
CMapView: [img]http://www.opengl.org/discussion_boards/ubb/tongue.gif[/img]MapView->GetClientRect(&rect);
GLdouble x = mouse_x;
GLdouble y = rect.Height() - mouse_y;

GLfloat pixel = 0;

glReadPixels(x,y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT, &pixel);
gluUnProject(x, y, z, modelView, projection, viewport, &sx, &sy, &sz);

Thanks for any help!

Hey,

hmm… firstly are you sure you have something there that isn’t on the far plane? ya, silly question… you would have checked that already. The only other thing I can think of is to make sure your read buffer is set up to GL_BACK. Perhaps you’re trying to read the front buffer, or something weird???

cheers,
John

Well here’s a crazy thought, you have the x and y values (or values proportional to them at least) and since the sphere is a 2-D surface with a well known equation (R^2=X^2+Y^2+Z^2), you only need the x and y components (as well as R, Xo, Yo, and Zo) to calculate the depth of the point on the sphere (facing hemisphere actually, or you could also get the point on the backside but why? ) Although a better way that is perspective correct is to shoot a line from the mouse position on the near plane to the mouse position on the far plane. Find the near point where that line intersects the sphere, (again you will be able to find the other point but it can be ignored). And these points are in 3-D world space of course, not the 2-D projection space.

[This message has been edited by DFrey (edited 06-22-2000).]

For some reason, I seem to be getting complete garbage from unproject and readpixels. Even if I plug in my own screen values (x,y,z) into unproject, I’m getting object coordinates that are around 10^-9. These are many, many orders of magnitude off from the original values I plugged in. So, it’s like something isn’t set up properly. Is there some initialization I am missing? My pixel depth value is set to 32 bits, I’ve glEnable’d GL_DEPTH_TEST, and glReadBuffer is GL_BACK.

If I don’t know the world coordinates, I won’t be able to even draw a line from the near plane to the far plane to determine the collision point.

How come you don’t know the world coordinates? You know what projection you are using yes? You know where the near plane and far plane are right? You had to set those explicitly. So just rotate and translate the near and far planes into position, map the mouse coordinates to both planes, shoot a ray (not necessarily draw) between those two points and see what it intersects. I guess I just don’t understand. Are you not talking about a 3D sphere you have drawn? If you are talking about a 3D sphere that you have drawn, then you had to know the coordinates of the sphere when you drew it. You may have used object coordinates and then used glRotate, glTranslate, and glScale to transform the coordinates. But that doesn’t stop you from doing those transformations yourself and intersecting the ray I speak of with the sphere in world coordinates.

[This message has been edited by DFrey (edited 06-22-2000).]

Hey Gleep,

hmm, so you reckon it’s gluUnproject that’s giving you grief?

Some ideas to help debug. This is what I’d do, btw, not necessarily what’s best.

  1. I’d make sure I had the right understanding of the projection matrix by printing it out (once I fetched it) and made sure it matches the projection matrix formula in the back of the Red Book. Who knows? Maybe tjat’s screwed up, or maybe it’s not being read properly.

  2. I’d set the modelview matrix to the identity while i]m playing with “toy” unprojects to see what’s going on

  3. remember, the z value in between 0.0 and 1.0 and the x&y are within the viewport.

  4. keeping in mind that a simple test to easily see how gluUnproject is working is to gluProject a world point you know is visible, gluUnprojecting it and comparing the results.

hmm. that’s pretty vague, but it’s all i can think of right now?
Incidentially, i’ve done what you’ve done too, for a 3D mouse that sits on the sceene. Hmm.

cheers
John

Noticed a wierd thing in your code above.

glReadPixels(x,y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT, &pixel);
gluUnProject(x, y, z, modelView, projection, viewport, &sx, &sy, &sz);

What’s the z-variable (third argument) doing in gluUnProject, shouldn’t it be pixel, since that is the variable holding z-value from glReadPixels?

Okay, a status report:

I discovered the problem was with the projection matrix (thanks john!). My projection matrix was initialized with 0.00001 as my near plane. This was causing a quite invalid value in my proj. matrix. I changed the near plane to 1.0 and I am now getting reasonable values from gluUnProject.

With gluUnProject working, I now have realistic world x/y/z values for z=0 and z=1. However, I’m not certain how to find the spherical intersection points. I’ve found a lot of formula on the net, but nothing that I can easily create a subroutine from. Do you have any suggestions?

Bob, the x/pixel mixup was just a typo during my many debugs that I’ve subsequently. Thanks for noticing it.

Thanks guys!

Hey,

hmm… weird bug about the small near plane. … quite perplexing.

Anyway, why don’t you just read the depth at the pixel of the mouse cursor and plug that in for your depth?

that would ve the easiest way, I reckon.

cheers
John

I can’t use ReadPixels because I have graphics that superimpose the sphere. I might get a Z on the near plane instead of a point on the sphere.

I wish it would work that way; it certainly would be easier. Is that how you implemented it in your program?

Thanks… l8r.