prongs
prongs

Reputation: 9606

opengl mouse coordinate to world coordinate

I need to detect mouse motion and draw a ball at the mouse's position. I need the ball to be in world coordinate. So I'm trying to use glUnProject for this task and seems I'm not succeeding till now. This is my motionFunc:

void motionFunc( int x, int y)
{


    GLint viewport[4];
    GLdouble modelview[16];
    GLdouble projection[16];
    GLfloat winX, winY, winZ;
    GLdouble posX, posY, posZ;

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

    winX = (float)x;
    winY = (float)viewport[3] - (float)y;
    glReadPixels( x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );

    gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);      //printf("winz: %f posz: %f\n",winZ,posZ);
    Ball.x=posX;
    Ball.y=posY;
    Ball.z=posZ;
    //printf("%f %f %f\n",Ball.x,Ball.y,posZ);
    glutPostRedisplay();
}

now, I added a breakpoint on glutPostRedisplay. Turns out when I click-drag mouse, the Ball's coordinates(Ball.x,Ball.y,Ball.z) are something like:

(Ball).x -727.175354
(Ball).y 407.310242
(Ball).z -865.000610

why is the z coordinate so far? My camera is at z=+135. And other objects in my model are like, at z= -3 to +3. I need the ball's z coordinate to be in the same range.

now, what exactly is winZ? Here, I checked it always turns out to be 1.00. I tried to hardcode winZ and I found at winZ=0.85, the ball seems like to be always under the mouse(I can drag the ball with my mouse and the ball is always under the pointer). But then the Ball's coordinates are like:

(Ball).x -4.67813921
(Ball).y 2.57806134
(Ball).z 128.370895

which is so close to the camera but x and y coordinates are not good for me. they always come out to be near the origin. which is not what I want. My other objects' x and y coordinates have a wider range.

Finally, my question is, what is the correct way to do glUnproject or something of the same sort?

Upvotes: 0

Views: 4120

Answers (1)

Eelke
Eelke

Reputation: 22033

A 2D mouse coordinate cannot unambiguously unmapped to a 3D world coordinate. The 2D coordinate corresponds with a line in 3D space. The winz influences which point on this line is returned. When you use 0.0 for winz you will get the point at the near clipping plane. When you use 1.0 you will get the point at the far clipping plane.

If you are using a depth buffer you could retrieve the value from the depth buffer using the glReadPixels function and use that as winz. Here a piece of code from a toy project of mine in Java

    FloatBuffer depth = BufferUtils.createFloatBuffer(1);
    glReadPixels(mouse_x, mouse_y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, depth);

    depth.rewind();
    FloatBuffer farPos = BufferUtils.createFloatBuffer(3);
    GLU.gluUnProject(mouse_x, mouse_y, depth.get(), 
            mainContext.getModelviewMatrix(), 
            mainContext.getProjectionMatrix(), viewport, farPos);

Most is the same in C/C++ except for the weird NIO buffers.

Upvotes: 1

Related Questions