Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL: projecting mouse click onto geometry

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?

like image 535
Mark Harrison Avatar asked Sep 22 '08 05:09

Mark Harrison


People also ask

What is OpenGL and how to use it?

OpenGL: OpenGL is a cross-language, cross-platform API for rendering 2D and 3D Vector Graphics. It will make a lot of design as well as animations using this. Create a circle anywhere on the console using a single left mouse click and the coordinates of the center of the circle created depends on the position of your click.

How to draw a circle using single click in OpenGL?

Approach: The idea is to use the below inbuilt function to draw the circle using single click in OpenGL: glMatrixMode (GL_PROJECTION): This function sets the current matrix to projection.

How do I project a 3D ray from the mouse?

Overview It can be useful to click on, or "pick" a 3d object in our scene using the mouse cursor. One way of doing thisis to project a 3d ray from the mouse, through the camera, into the scene, and then check if that ray intersects with any objects. This is usually called ray casting.

What is ray casting in OpenGL?

This is usually called ray casting. This is an entirely mathematical exercise - we don't use any OpenGL code or draw any graphics- this means that it will apply to any 3d application the same way. The mathematical subject is usually called geometric intersection testing.


2 Answers

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;
like image 91
Jesse Beder Avatar answered Oct 21 '22 20:10

Jesse Beder


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

like image 20
Alec Thomas Avatar answered Oct 21 '22 22:10

Alec Thomas