gluProject Converting 3D coordinates to 2D coordinates does not convert the 2D Y Coordinate correctly
Asked Answered
I

2

8

After two hours of googling (here, here, here, here, and here, and a ton others which I am not bothered to find), I thought I had finally learnt the theory of turning 3D coordinates to 2D coordinates. But it isn't working. The idea is to translate the 3D coordinates of a ship to 2D coordinates on the screen to render the username of the player controlling that ship.

However, the text is rendering in the wrong location: enter image description here

The text is "Test || 2DXCoordinate || 2DZCoordinate".

Here is my getScreenCoords() - Which converts the 3D coordinates to 2D.

public static int[] getScreenCoords(double x, double y, double z) {
    FloatBuffer screenCoords = BufferUtils.createFloatBuffer(4);
    IntBuffer viewport = BufferUtils.createIntBuffer(16);
    FloatBuffer modelView = BufferUtils.createFloatBuffer(16);
    FloatBuffer projection = BufferUtils.createFloatBuffer(16);
    GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelView);
    GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);
    GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);
    boolean result = GLU.gluProject((float) x, (float) y, (float) z, modelView, projection, viewport, screenCoords);
    if (result) {
        return new int[] { (int) screenCoords.get(0), (int) screenCoords.get(1) };
    }
    return null;
}

screenCoords.get(0) is returning a perfect X coordinate. However, screenCoords.get(1) is going higher or lower depending on how far away I am from the ship. After many hours of debugging, I have narrowed it down to this line being incorrect:

GLU.gluProject((float) x, (float) y, (float) z, modelView, projection, viewport, screenCoords);

However, I have no idea what is wrong. The X coordinate of the ship is fine.... Why not the Y?

According to BDL's answer, I am supplying the "wrong matrix" to gluProject(). But I don't see how that is possible, since I call the method right after I render my ship (Which is obviously in whatever matrix draws the ship).

I just can't fathom what is wrong.

Note: BDL's answer is perfectly adequate except that it does not explain why the Y coordinates are incorrect.

Note: This question used to be much longer and much more vague. I have posted my narrowed-down question above after hours of debugging.

Inverson answered 5/11, 2014 at 10:22 Comment(4)
1. Are you setting your GL_MODELVIEW-matrix somewhere in your code? For me it looks as if it is a identity matrix. 2. Does orthographicProjectionMatrix contain the perspective projection you are using to render your ship?Moriahmoriarty
@Moriahmoriarty orthographicProjectionMatrix contains the projection I am using to render the text. Not the ship.Inverson
In the second codeblock you posted you are loading orthographicProjectionMatrix to your projection matrix. what is the content of this matrix? And for me it looks like as if you never set the modelview matrix. Do you never call glTranslatef/glRotatef when drawing the ship?Moriahmoriarty
@Moriahmoriarty Added more code. I could add the entire classes, but I don't think people want to sift through 2000 lines of code.Inverson
M
7

You have to use the same projection matrix in gluProject that you use for rendering your ship. In your case the ship is rendered using a perspective projection, but when you call gluProject a orthographic projection is used.

General theory about coordinate systems in OpenGL

In most cases geometry of a model in your scene (e.g. the ship) is given in a model-coordinate system. This is the space where your vertex coordinates exist. When now placing the model in your scene we apply the model-matrix to each vertex to get the coordinates the ship has in the scene. This coordinate system is called world space. When viewing the scene from a given viewpoint and a viewing direction, again a transformation is needed that transforms the scene such that the viewpoint is located in the origin (0,0,0) and view-direction is along the negativ z-axis. This is the view coordinate system. The last step is to transform view-coordinates into ndc, which is done via a projection matrix.

In total we get the transformation of a vertex to the screen as:

 v_screen = Projection * View * Model * v_model

In ancient OpenGL (as you use it) View and Model are stored together in the ModelView matrix.

(I skipped here some problems as perspective divide, but it should be sufficient to understand the problem.)

Your problem

You already have a position in world space (x,y,z) of your ship. Thus the transformation with Model has already happend. What is left is

v_screen = Projection * View * v_worldspace

For this we see, that in our case the ModelView matrix that gets entered to gluProject has to be exactly the View matrix.

I can't tell you where you get the view matrix in your code, since I don't know this part of your code.

Moriahmoriarty answered 5/11, 2014 at 11:28 Comment(9)
I updated the OP with the new code. It has definitely made it better, so many thanks for your suggestion, but for some reason the code still is not perfect and does not work.Inverson
Most probably because you have the same problem with the MODELVIEW matrix. If (x,y,z) are in world coordinates, your MODELVIEW matrix should only contain the view matrix, but not the model matrix.Moriahmoriarty
What? I don't understand that, sorry. I set the 2D coordinates on the exact line after the ship is rendered. Is that not correct? And how do I not make it have the model matrix but only the view matrix?Inverson
Gets too much text. I will update the answer in a few seconds.Moriahmoriarty
I believe I am now putting the 2D converting coordinates right after I set the modelview matrix. Please check the update in my original post.Inverson
Meh. No more answers. Looks like you'll be getting the bounty atm :/.Inverson
The reason why nobody helps you is that this is simply impossible without checking your whole project step-by-step. So giving bounty for the second time will also not give you better answers.Moriahmoriarty
Why would that be? gluProject() is just returning the wrong results. I don't understand why someone can't tell me why it tells me the wrong results for the x, y, and z coordinates of a object.Inverson
gluProject is returning exactly what it should. The problem will most probably be the matrix you supply to it. And finding out what exactly is in this matrix will only work when someone checks your full code.Moriahmoriarty
I
0

I found an answer to my issue!

I used

font.drawString(drawx - offset, drawy, (sh.username + " || " + drawx + " | " + drawy), Color.orange);

When it should have been

font.drawString(drawx - offset, Display.getHeight() - drawy, (sh.username + " || " + drawx + " | " + drawy), Color.orange);
Inverson answered 4/12, 2014 at 0:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.