Questions about gluProject

I have a question (or so) about gluProject. Everywhere I’ve read, it says that it gives me screen coordinates based on the object coordinates passed in, but I don’t get the results I want.

For a slightly simplified case…

My projection matrix will always be the identity matrix, for now.

The viewport will be (0, 0, 640, 640).

The current modelview matrix is:
[ 0.0008787 0.0 0.0 0.0 ]
[ 0.0 0.0008787 0.0 0.0 ]
[ 0.0 0.0 -0.0004393 0.0 ]
[ 0.0 0.0 0.0 1.0 ]

Now, if I have a cube of “known space” which goes from (0, 0, 0) to (1315, 1280, 980), I want to find the screen coordinates of another cube that goes from (630, 630, 660) to (680, 650, 670).

In my program right now, I can see a square representing the dimensions of the known space as seen from the top, and a small cube in the middle being the object I’m interested in. The small cube is more or less visually centered both horizontally and vertically.

When I use gluProject on all of the eight points of the small cube, and find the minimum and maximum X and Y values, I get (497, 497) and (511,502). These are clearly not in the middle of the screen.

I became even more confused when I worked through the math myself. According to the documentation, for my given matrices and viewport, I should end up with the following equations for the window coordinates:

winX = 0 + 640 * (0.0008787 * X + 1) / 2
winY = 0 + 640 * (0.0008787 * Y + 1) / 2

Running the points for the small cube by hand obtains the same results as the function. However, these end formulas made me slightly suspicious. If I put (0,0,0) in these formulas, which should result in a point up near the corner, if not exactly on it, I end up with winX = 320 and winY = 320 - right in the middle of the screen.

Because of this, I’m pretty sure I’ve been making an unfounded assumption somewhere about what is going on. Any help pointing me in the right direction would be very much appreciated.

Hello,

I haven’t gone through your maths properly (since I am impatiently waiting to see the matrix reloaded), but I noticed this:

your modelview matrix has [0 0 0 1]’ as the fourth column. This means you’re not translating at all, so when you plug in a vertex (0, 0, 0, 1) then you will get back a vertex in the middle of the screen, not “up near the corner, if not exactly on it”.

Actually, i think your expanded maths IS wrong. If P=I and M=

[ sx 0   0  0 ]
[ 0  sy  0  0 ]
[ 0  0   sz 0 ]
[ 0  0   0  1 ][\CODE]

then all you're doing is scaling the coordinate system.  Effectively, v' becomes

v'=PMv

ie. 

x’=(P’)sx
x’=sx (since P is the identity)

I don’t know where you get the +1 from. I’ve ommited the scaling to device coordinates for clarity, but that will just be x’<-x’*320+320;

In conclusion, I think you need to reexamine your modelview matrix to see if it is doing what you really think it is doing. The modelview you provude only scales, not translates. thus, v=[0 0 0 1] will always map to [0 0 0 1], ie. to the middle of the screen

cheers
John

[This message has been edited by john (edited 05-16-2003).]

Maybe I wasn’t entirely clear when I provided the example matrix M. According to the blue book (OpenGL Reference Manual, 3rd Ed.) gluProject takes objX, objY, objZ, model, proj, view, winX, winY, winZ. objX, objY, and objZ are the coordinates to be projected, model is the modelview matrix, proj is the projection matrix, view is the viewport, and winX, winY, and winZ are the returned computed window coordinates.

It says to let v = (objX, objY, objZ, 1.0), and then compute v’ as P x M x v. If P is the identity matrix, and M is represented by this:
[ M1 M2 M3 M4 ]
[ M5 M6 M7 M8 ]
[ M9 M10 M11 M12 ]
[ M13 M14 M15 M16 ]

then v’ is:
[ M1X + M2X + M3X + M4X ]
[ M5Y + M6Y + M7Y + M8Y ]
[ M9Z + M10Z + M11Z + M12Z ]
[ M13 + M14 + M15 + M16 ]

or:
[ (M1 + M2 + M3 + M4)*X ]
[ (M5 + M6 + M7 + M8)*Y ]
[ (M9 + M10 + M11 + M12)*Z ]
[ (M13 + M14 + M15 + M16) ]

as a 1 column, 4 row matrix. The book then states that the window coordinates are computed as follows:
winX = view(0) + view(2) * (v’(0) + 1)/2
winY = view(1) + view(3) * (v’(1) + 1)/2
winZ = (v’(2) + 1)/2

If the viewport is as I specified earlier (view = (0, 0, 640, 640)), we can then substitute values in for the window coordinate equations as such:
winX = 0 + 640 * ( (M1 + M2 + M3 + M4)*X + 1)/2
winY = 0 + 640 * ( (M5 + M6 + M7 + M8)*Y + 1)/2
winZ = ( (M9 + M10 + M11 + M12)*Z + 1)/2

With these equations, it is easy to see that no matter what the matrix M is, if X is zero, then winX will always be 320. According to my understanding of this, it doesn’t matter what the rotation, translation, or zoom factors are in getting 320 as a result for X=0. At the very least, this seems counter-intuitive to me, and I would imagine I’ve made a mistake somewhere. However, I can’t seem to find it.

For what it’s worth, here is the relevant bit of code from my program:

double dbl3Orig1[3], dbl16Model[16], dbl16Proj[16], dbl3Result[3];
int int4View[4];

dbl3Orig1[0] = 0.0;
dbl3Orig1[1] = 0.0;
dbl3Orig1[2] = 0.0;

PrepareRedraw(); // A local function that does, among other things, a make_current.

glGetDoublev( GL_PROJECTION_MATRIX, dbl16Proj );
glGetDoublev( GL_MODELVIEW_MATRIX, dbl16Model );
glGetIntegerv( GL_VIEWPORT, int4View );

if( gluProject( dlb3Orig[0], dbl3Orig[1], dbl3Orig[2],
dbl16Model, dbl16Proj,
int4View, &( dbl3Result[0] ),
&( dbl3Result[1] ), &dbl3Result[2] ) ) == GL_FALSE )
{
cerr << “gluProject on Orig1 failed.” << endl;
}

At the end of this snippet, dbl3Result always equals (320, 320, 0.5).

I just discussed this with a coworker, and he quite quickly pointed out my problem with the above. Instead of v’ being this:
[ M1X + M2X + M3X + M4X ]
[ M5Y + M6Y + M7Y + M8Y ]
[ M9Z + M10Z + M11Z + M12Z ]
[ M13 + M14 + M15 + M16 ]

it should be this:
[ M1X + M2Y + M3Z + M4 ]
[ M5
X + M6Y + M7Z + M8 ]
[ M9X + M10Y + M11Z + M12 ]
[ M13
X + M14Y + M15Z + M16 ]

which gives me the same results with the M matrix from my first question, and my results from the previous (incorrect) v’ matrix were matching only by a fluke.

Additionally, I found out that in another part of our code, the points for the objects were translated (the points themselves, not the GL area) so that point (0,0,0) showed up in the upper left corner, instead of in the center. That being the case, I now realize why the result from gluProject was incompatible with what I was seeing on the screen - there was a translation going on, but it wasn’t reflected in the GL matrices.

Thank you for your help - it gave me the correct questions to ask, once my matrix multiplication error was out of the way, to find out why things weren’t working as expected.