Transform mouse coordinates to world XZ coordinates

Hi

I am currently working on a some sort of editor. The terrain of this editor is a map built out of tiles (squares).
When i click my GLJPanel i sent a mouseevent because I want to check if I click on a tile.

So basicly I want to convert my X and Y mouse coordinate to Coordinate in the XZ plane (since Y axis is the one pointing up).

So far I tried to do this using glu.gluUnProject but i have no success doing so

During init methode of GLEventListener


        this.viewport = IntBuffer.allocate(4);                                  // Where The Viewport Values Will Be Stored
        this.modelview = FloatBuffer.allocate(16);                              // Where The 16 Doubles Of The Modelview Matrix Are To Be Stored
        this.projectionview = FloatBuffer.allocate(16);                         // Where The 16 Doubles Of The Projection Matrix Are To Be Stored

Whenever I reshape my window I update the buffers


        gl.glGetIntegerv(GL2.GL_VIEWPORT, this.viewport);
        gl.glGetFloatv(GL2.GL_PROJECTION_MATRIX, this.projectionview);

Every time a frame is drawn i update modelview buffer in display method


        gl.glGetFloatv(GL2.GL_MODELVIEW_MATRIX, this.modelview);

This is the code i execute when i want to convert the mouse to XZ plane coordinates


        float winX, winY;                                                         // Holds Our X, Y and Z Coordinates
 
        winX = (float)this.pickX;                                               // Holds The Mouse X Coordinate
        winY = (float)this.pickY;                                               // Holds The Mouse Y Coordinate
        winY = (float)this.viewport.get(3) - winY - 1;                   // Subtract The Current Mouse Y Coordinate From The Screen Height.
                 
        FloatBuffer projectedPositions = FloatBuffer.allocate(3);

        boolean succes = new GLU().gluUnProject(winX, winY, 0.0f, this.modelview, this.projectionview, this.viewport, projectedPositions);
        
        System.out.println(projectedPositions.get(0)+" "+projectedPositions.get(1)+" "+projectedPositions.get(2)+" "+succes);

Am I using the wrong method or am I passing along the wrong arguments?

When i see at least 10 tiles on my screen, each tile = 1.0f x 1.0f the difference between most left and most right tile on my screen is maybe 0.1f so something is obviously going wrong

Thx for any help

If you’re doing this in 3D:

private FloatBuffer getMousePosition(int mouseX, int mouseY) {
    IntBuffer viewport = BufferUtils.createIntBuffer(16);
    FloatBuffer modelview = BufferUtils.createFloatBuffer(16);
    FloatBuffer projection = BufferUtils.createFloatBuffer(16);
    FloatBuffer winZ = BufferUtils.createFloatBuffer(1);
    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);

    GL11.glReadPixels(mouseX, mouseY, 1, 1, GL11.GL_DEPTH_COMPONENT, GL11.GL_FLOAT, winZ);

    if (winZ.get(0) == 1) {
        return null;
    }

    GLU.gluUnProject(mouseX, mouseY, winZ.get(), modelview, projection, viewport, position);

    return position;
}

but you’re using 2D, aren’t you? It’s easier to just do the math to find where your mouse is in the game world. This requires you to keep track of the transformations that you do, but it should still be faster than doing that many OpenGL calls.

I have enabled GL.GL_DETPH and changed converting code to


        winX = (float)this.pickX;                                               // Holds The Mouse X Coordinate
        winY = (float)this.pickY;                                               // Holds The Mouse Y Coordinate
        winY = (float)this.viewport.get(3) - winY;                              // Subtract The Current Mouse Y Coordinate From The Screen Height.
                         
        
        FloatBuffer fb = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        gl.glReadPixels((int)winX, (int)winY, 1, 1, GL2.GL_DEPTH_COMPONENT, GL2.GL_FLOAT, fb);
        fb.rewind();
        
        System.out.println("Coordinates at cursor are (" + winX + ", " + winY+")");
        
        FloatBuffer projectedPositions = FloatBuffer.allocate(3);
        new GLU().gluUnProject(winX, winY, fb.get(0), //
               this.modelview, this.projectionview, this.viewport, projectedPositions);
        
         System.out.println("World coords at z="+fb.get(0)+" are ( " //
                             + projectedPositions.get(0)+" "+projectedPositions.get(1)+" "+projectedPositions.get(2)
                             + ")");

The results are much realistic now, but the there is still deviation, except for points near the center of my screen.
Should i also update the projection matrix each from or is modelmatrix enough?

thx

Ah nevermind if found the solution :slight_smile:

I forgot to reset the camera to its place after drawing the scene before doing the picking

The coordinates are correct now when i click on a square i draw. Thx for any help

Great that you got it working. Remember that calling glReadPixels forces the processor to wait for the graphics card to render the scene. It’s a very good idea to read pixels of the last frame instead, or at least do the read at the beginning of the next frame before clearing it. You can also do it asynchronously, but I don’t know exactly how to do that though.