GLU UnProject for 2d objects gives incorrect coordinates on rotation

Started by Shnagenburg, July 04, 2014, 04:13:00

Previous topic - Next topic

Shnagenburg

I am using GLU.gluUnProject() (from lwjgl-2.8.5) to find a 2D object's screen coordinates. The object is part of a tree of many transformations (i.e., it is the finger of a hand of an arm of a body, etc). I am not sure if there is a better term for it, but I just call it a "DrawTree".

The technique appears to work until things start rotating. All rotations are performed around the Z axis (As it is a 2D scene). What is stranger still, is that as it rotations, it produces correct values at 0/180 degrees, and then produces correct values at 90/270, but in the 90/270 case, the x and y coordinates are flipped. Flipped as in:

0/180 degrees: x = 400, y = 300
90/270 degrees: x = 300, y = 400
Other values appear to not produce nearly correct results.

I've noticed that GLU.gluUnProject() seems primarily used for Picking, but I feel like it would work in this case too. For my GLU.gluUnProject() parameters, I've given 0, the window height, and 0. I've played with these numbers a bit but fiddling hasn't yielded correct results. It very well could be I just have fundamental misunderstanding of how this works.

Here is the relevant code:

Set up
        GL11.glLoadIdentity();
        GL11.glOrtho(0.0f, 800, 600, 0.0f, 0.0f, 1.0f);
        game.draw();


Draw Tree
public void draw() {
GL11.glPushMatrix();
        GL11.glTranslatef(position.x, position.y, z);
        GL11.glTranslatef(centerOfRotation.x, centerOfRotation.y, 0);
        GL11.glRotatef(rotation, 0, 0, 1.0f);
        GL11.glTranslatef(-centerOfRotation.x, -centerOfRotation.y, 0);
        GL11.glScalef(scaleX * flipped, scaleY * inverted, 1.0f);

        Vector2f vec = CoreUtility.vectorScreenCoords();
        Debugger.print(vec.toString());

        draw.draw();
        for (Draw child : children) {
            child.draw();
        }
GL11.glPopMatrix();


And the GLU.gluUnProject wrapper.
        float winX, winY;
        IntBuffer viewport = BufferUtils.createIntBuffer(16);
        FloatBuffer modelview = BufferUtils.createFloatBuffer(16);
        FloatBuffer projection = BufferUtils.createFloatBuffer(16);
        FloatBuffer position = BufferUtils.createFloatBuffer(3);
        GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelview);
        GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);
        GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);        
        
        winX = (float) 0;
        winY = (float) viewport.get(3);
        winZ = (float) 0;
        GLU.gluUnProject(winX, winY, winZ, modelview, projection, viewport, position);

        return position;


Reading around, some of the gotcha's I've seen are:
Messing with your projection matrix before unProjecting. There aren't any extraneous glLoadIdentity()s in the code that would do that, it should be the full transformation matrix getting passed to gluUnProject()
Using an incorrect winZ. Everything is in 2D so I feel like 0 should be an okay value.
I don't ever set up a viewport. I haven't had to so far, so I'm not sure why that would make the rotation do these weird things.

Any assistance or tips would be greatly appreciated. Thanks!

quew8

(It's called a scene graph)

You say that you are finding the objects screen coordinates, but that isn't what gluUnProject() does. gluUnProject() takes screen coordinates and "undoes" the transforms done during rendering to give the object coordinates. It sounds like you want gluProject(), which takes object coordinates and gives you screen coordinates.

Also just as a side note, is the third code snippet run inside the "CoreUtility.vectorScreenCoords()" methods? Because if it isn't then this definitely won't work since glPopMatrix() restores the matrix to the state it was in on the previous glPushMatrix() call.

Shnagenburg

Well that would explain just about everything. Thanks for the tip, I appreciate it.