Detremining the window z from glReadPixels()

Hi

I coded up the examples at:

http://nehe.gamedev.net/article/using_gluunproject/16013/
http://www.java-tips.org/other-api-tips/jogl/how-to-use-gluunproject-in-jogl.html

to find the world coordinates of a mouse point; see code below which I simply called in display() to display the results each refresh.

The NeHe example uses glReadPixels() to determine the z-coordinate. However, it always a value of 1 for me.

The Java Tips example explicitly sets z to either 0 or 1.

But I’d like to obtain the complete window (x,y,z) to then pass to gluUnProject() to obtain the world (x,z,y).

What am I doing wrong?

Thanks

Graham

===

public Point3D worldCoordinates(GLAutoDrawable drawable)
{
    // [http://www.java-tips.org/other-api-tips/jogl/how-to-use-gluunproject-in-jogl.html](http://www.java-tips.org/other-api-tips/jogl/how-to-use-gluunproject-in-jogl.html)
    GL gl = drawable.getGL();
    
    int viewport[] = new int[4];
    float mvmatrix[] = new float[16];
    float projmatrix[] = new float[16];
    int realy = 0;// GL y coord pos
    float wcoord[] = new float[4];// wx, wy, wz;// returned xyz coords
    
    int x = xCoord;
    int y = yCoord;
    gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
   
    gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
    gl.glGetFloatv(GL2.GL_MODELVIEW_MATRIX, mvmatrix, 0);
    gl.glGetFloatv(GL2.GL_PROJECTION_MATRIX, projmatrix, 0);
    realy = viewport[3] - (int)y; /* note viewport[3] is height of window in pixels */
    
    FloatBuffer floatBuffer = FloatBuffer.allocate(1);
    gl.glReadPixels( x, (int)realy, 1, 1, GL2.GL_DEPTH_COMPONENT, GL2.GL_FLOAT,floatBuffer);
    float z = floatBuffer.get(0);
    System.out.println("z: " + z);
    
    System.out.println("Coordinates at cursor are (" + x + ", " + realy);
    boolean ok = glu.gluUnProject((float) x, (float)realy, 0.0f, //
        mvmatrix, 0,
        projmatrix, 0, 
        viewport, 0, 
        wcoord, 0);
    System.out.println("World coords at z=0.0 are ( " //
                       + wcoord[0] + ", " + wcoord[1] + ", " + wcoord[2]
                       + "); ok: " + ok);
    ok = glu.gluUnProject((float) x, (float) realy, 1.0f, //
        mvmatrix, 0,
        projmatrix, 0,
        viewport, 0, 
        wcoord, 0);
    System.out.println("World coords at z=1.0 are (" //
                       + wcoord[0] + ", " + wcoord[1] + ", " + wcoord[2]
                       + "); ok: " + ok);
    return new Point3D(wcoord[0],wcoord[1],wcoord[2]);
}

===

Here’s the steps:

p0 = Unproject window point at (sx0, sy0, 0)
p1 = Unproject window point at (sx1, sy1, 1)

ray = [p0, p1]

Intersect ray with objects (use ray-triangle intersection)

Let q be a point of intersection with an object

sq = Project q

sq has the window coordinates of (sx, sy, sz) where sz is the depth value

Hope this helped.

Hi

Thanks for your reply.

I’ve coded up my method that returns a pick-ray. also, I’ve got a test method for drawing a ray but what you’re saying is that inside my drawRay() I need to use gluProject() to draw the ray on the screen.

Graham

public Ray3D mouseRayWorldCoordinates()
{
    GL2 gl2 = gl;
    
    int   viewport[]   = new int[4];
    float mvMatrix[]   = new float[16];
    float projMatrix[] = new float[16];
    float wcoordNear[] = new float[4];
    float wcoordFar[]  = new float[4];
    
    // mouse coordinates
    int mouseX = xCoord;
    int mouseY = yCoord;
   
    gl2.glGetIntegerv(GL2.GL_VIEWPORT, viewport, 0);
    gl2.glGetFloatv(GL2.GL_MODELVIEW_MATRIX, mvMatrix, 0);
    gl2.glGetFloatv(GL2.GL_PROJECTION_MATRIX, projMatrix, 0);
    int glY = viewport[3] - (int)mouseY - 1; // GL y coord pos - note viewport[3] is height of window in pixels
    
    // world near - the gluUnProject z value is the screen depth value which goes from 0.0 -> 1.0
    System.out.println("Coordinates at cursor are (" + mouseX + ", " + mouseY);
    boolean ok = glu.gluUnProject((float) mouseX, (float)glY, 0.0f,mvMatrix, 0,projMatrix, 0,viewport, 0,wcoordNear, 0);
    System.out.println("World coords at z=0.0 are ( " //
                       + wcoordNear[0] + ", " + wcoordNear[1] + ", " + wcoordNear[2]
                       + "); ok: " + ok);
    // world far
    ok = glu.gluUnProject((float) mouseX, (float) glY, 1.0f,mvMatrix, 0,projMatrix, 0,viewport, 0,wcoordFar, 0);
    System.out.println("World coords at z=1.0 are (" //
                       + wcoordFar[0] + ", " + wcoordFar[1] + ", " + wcoordFar[2]
                       + "); ok: " + ok);
    
    // direction vector is far point - near point
    Vector3D dirVector = new Vector3D(wcoordFar[0]-wcoordNear[0],wcoordFar[1]-wcoordNear[1],wcoordFar[2]-wcoordNear[2]);
    dirVector.normalise();
    Point3D viewerLocation = GLUtilities.cameraLocation(gl2);
    Ray3D mouseRay = new Ray3D(viewerLocation,dirVector);
    
    return mouseRay;
}

private void drawRay(Ray3D ray)
{
    GL2 gl2 = gl;
    Vector3D rayDirection   = ray.getDirection();
    Point3D  rayStart       = ray.getOrigin();
    Point3D  rayEnd         = rayStart.pointAlongVector(rayDirection,100,1e-06);
    
    gl2.glColor3f( 1.0f, 0.0f, 0.0f );
    
    gl2.glBegin(GL2.GL_LINES);   // start drawing the line
    gl2.glVertex3d(rayStart.getX(),rayStart.getY(),rayStart.getZ());
    gl2.glVertex3d(rayEnd.getX(),rayEnd.getY(),rayEnd.getZ());
    gl2.glEnd();                 // finished drawing the line

}

To draw the ray from the view position to the intersection point with an object, you just need to draw the line [p0, q].

To draw only the intersection of the ray with object, draw the point (q).