## OpenGL Perspective Screen to Obj Coordinates Mapping Question

Member
Posts: 321
Joined: 2004.10
Post: #1
I was (still am) having trouble getting my head wrapped around the gluUnproject() so I wrote a simple openGL program which the user could move a pixel in the x and y directions. I had a simple openGL object - a solid circle acturally - drawn behind the pixel in world cooridinates. I kept the fovy, Near, and Far constant, but allowed the user to change z or the object coordinates. Anyway, I was expecting the circle to track (stay behind) the pixel perfectly at least for one value of z. Kinda of like this schematic:

I realize that I could just use right angle trig functions to keep the circle in perfect alignment with the pixel. But I thought at least one value of z (between Near and Far) would exhibit this same behavior.

Is pespective projection more complicated than I have made it out to be?

Hope this post even makes sense I thought a drawing was mandatory.
Sage
Posts: 1,482
Joined: 2002.09
Post: #2
gluUnproject() is your friend here. You give it the relevant OpenGL matrices, viewport, and depth info and it can give you an absolute coordinate based on a screen coordinate.

The math isn't terribly difficult to explain. It just inverts the matrix that transforms world to screen coordinates, that makes it perform the transform backwards. The implementation of it is pretty tedious if you don't have a nice matrix library to use though.

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Member
Posts: 321
Joined: 2004.10
Post: #3
But it is not my friend here

I start with the pixel and the circle at the center of the screen. Initially, both are in perfect alignment: one right behind the other. Let's say I just move the pixel to the left one pixel at a time. As I'm moving the pixel I'm moving the circle object as well with gluUnproject() and some value of Z. No matter what values of Z I use, the circle either moves slower or faster than the pixel across the screen. Some values of Z can track the circle to the pixel better than others, but there appears to be no perfect mapping. Like in my (impossible?) drawing.
Member
Posts: 353
Joined: 2002.04
Post: #4
I don't know if this is much help but from my reading of your diagram the blue lines would always need to be the center of the viewport in order to get the effect you're after. So the camera would need to be rotating as the pixel and black circle move.
Member
Posts: 321
Joined: 2004.10
Post: #5
I appreciate the post, but I want to keep the camera and the viewport constant. If I rotate the camera I'm in effect resetting the perspective projection each time. And I'm trying to better understand the relationship between screen and world/object coordinates with a constant Z as x and y changes. Or specifically, is there a Z value which will create "perfect" mapping: like in the drawing.
Member
Posts: 142
Joined: 2002.11
Post: #6
(Feb 13, 2011 11:56 AM)WhatMeWorry Wrote:  But it is not my friend here

I start with the pixel and the circle at the center of the screen. Initially, both are in perfect alignment: one right behind the other. Let's say I just move the pixel to the left one pixel at a time. As I'm moving the pixel I'm moving the circle object as well with gluUnproject() and some value of Z. No matter what values of Z I use, the circle either moves slower or faster than the pixel across the screen. Some values of Z can track the circle to the pixel better than others, but there appears to be no perfect mapping. Like in my (impossible?) drawing.

Note that when you use gluUnproject you need to specify the window z coordinate in view coordinates. This means that if you want the circle to be at the distance zFar pass 1.0, and if you want the circle to be at zNear pas 0.0.

The "perfect mapping" you speak of is given by the worldZ position of the sphere times the projection matrix then converted from normalized device coordinates to view coordinates. Under normal conditions this is:

0.5 * (-C - D / z) + 0.5
where C = -(zFar + zNear) / (zFar - zNear)
and D = -(2.0 * zFar * zNear) / (zFar - zNear)

I came up with this equation by looking at how the typical projection matrix (formed by glFrustum or gluPerspective) projects a world z coordinate into normalized device coordinates and then how that coordinate is mapped to view coordinates (by mapping the range -1, 1 to 0,1).

The best way to understand gluUnproject is to understand the various coordinate systems that OpenGL uses.