views:

2060

answers:

4

I have this view set:

glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
glLoadIdentity(); //Reset the drawing perspective

and I get a screen position (sx, sy) from a mouse click.

Given a value of z, how can I calculate x and y in 3d-space from sx and sy?

A: 

libqglviewer has a good selection framework if that's what you're looking for

shoosh
+1  A: 

This is actually dependent on the projection matrix, not the model-view matrix. http://www.toymaker.info/Games/html/picking.html should help you out -- it's D3D-centric but the theory is the same.

If you're looking to do mouse-based picking, though, I suggest using the selection rendering mode.

Edit: Mind you, the model-view matrix does come into play, but since yours is identity it's a nonissue.

Cody Brocious
+2  A: 

This is best answered by the most authoritative source, OpenGL's web site.

Alec Thomas
Putting the name of the source in your answer would be helpful rather than having to click on the link to find out.
danio
+5  A: 

You should use gluUnProject:

First, compute the "unprojection" to the near plane:

GLdouble modelMatrix[16];
GLdouble projMatrix[16];
GLint viewport[4];

glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);

GLdouble x, y, z;
gluUnProject(sx, viewport[1] + viewport[3] - sy, 0, modelMatrix, projMatrix, viewport, &x, &y, &z);

and then to the far plane:

// replace the above gluUnProject call with
gluUnProject(sx, viewport[1] + viewport[3] - sy, 1, modelMatrix, projMatrix, viewport, &x, &y, &z);

Now you've got a line in world coordinates that traces out all possible points you could have been clicking on. So now you just need to interpolate: suppose you're given the z-coordinate:

GLfloat nearv[3], farv[3];  // already computed as above

if(nearv[2] == farv[2])     // this means we have no solutions
   return;

GLfloat t = (nearv[2] - z) / (nearv[2] - farv[2]);

// so here are the desired (x, y) coordinates
GLfloat x = nearv[0] + (farv[0] - nearv[0]) * t,
        y = nearv[1] + (farv[1] - nearv[1]) * t;
Jesse Beder