Does glReadPixels behave dirrently in jsr231

I have been spending my spare time porting my old code to jsr231, most everything is going smooth, I am just having trouble getting exact 3D mouse coordinates with the new api.

With 1.0, I would call glReadPixels and get my z value, load that into gluUnproject, and have exact coordinates

I have tried two different jdk’s, several cvs versions of jsr231, and the dri hack on a recent post. They all return values that are too small. I have used BigDecimal to get some readable output, and the value returned are roughly “0.00001”. On manual z entry into gluUnproject, “z=0.4” and up to “z=0.9”, give perfect x,y,z coordinates when I find that spot in the scene with my mouse.

I am using the glReadPixels function that takes a buffer for an argument. Currently I am using a DoubleBuffer, I have also tried using a ByteBuffer at one point or another, which caused the value to vary without much logic. I have also updated my ModelView, etc, to buffers instead of arrays.

I am sure it is the z value retured by glReadPixels that is the problem, because I can manually enter it into gluUnproject and get reasonable results back (of couse, only where the z value is correct with the manual setting).

Thanks

Greg

A few points. Make 100% sure the byte ordering is correct on your Buffers. BufferUtil will take care of this for you. Make sure your buffers are properly rewound. Finally, when reading back the depth buffer, the Z value must be scaled; it isn’t an absolute value.

If you post the JOGL 1.0 and your current code snippets side-by-side it should be fairly obvious where the error is.

OK, I am still diggin through backup mountain over here.

I believe my code has met all the requirements you listed except for one.

the Z value must be scaled

I am going to look into this tonight. Maybe the original code working was just luck. I just copy pasted the c code from article 13 at nehe (before selling out to gamedev), and javatized it.

Ha, found it. Here is the old code.

    gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, modelview);
    gl.glGetDoublev(GL.GL_PROJECTION_MATRIX, projection);
    gl.glGetIntegerv(GL.GL_VIEWPORT, viewport);
    winX = (float)x;
    winY = (float)viewport[3] - (float)y;
    //winY = 0;
    gl.glReadPixels(x, (int)winY, 1, 1, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT, winZ);
    
    glu.gluUnProject(winX, winY, winZ[0], modelview, projection, viewport, posX, posY, posZ);[/font]

Here is the new code. I put a few extra rewinds just in case, I am still new to NIO. I love the BufferUtil by the way!

    gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, ModelView);
    gl.glGetDoublev(GL.GL_PROJECTION_MATRIX, Projection);
    gl.glGetIntegerv(GL.GL_VIEWPORT, ViewPort);
    
    winX = (float)x;
    winY = (float)ViewPort.get(3) - (float)y;
    
    XYZ = new double[3];
    
    DoubleBuffer Possition = BufferUtil.newDoubleBuffer(BufferUtil.SIZEOF_DOUBLE * 3);
    
    DoubleBuffer Z = BufferUtil.newDoubleBuffer(BufferUtil.SIZEOF_DOUBLE);
    
    gl.glReadPixels(x, (int)winY, 1, 1, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT, Z);

    Z.rewind();
    ModelView.rewind();
    Projection.rewind();
    ViewPort.rewind();
    Possition.rewind();
    
     glu.gluUnProject(winX, // winX
            winY, // winY
            Z.get(0),
            ModelView, // model
            Projection, // projection
            ViewPort, // view port
            Possition);

I want to post the original code form nehe article #13, but I don’t think I should. Here is a link to the article.

http://nehe.gamedev.net/data/articles/article.asp?article=13

Thanks for your patience with me. I have been digging through articles and game books here at the house, I must be reading over something.

Greg

Well, I am getting near perfect coordinates now.

I changed Z from a DoubleBuffer to a FloatBuffer.

I still am not sure what you mean by Scaling Z, is this a ray cast? I will keep digging.

Every now and then, the Y value is cast to deep into the scene, I believe it is getting its coordinates from the underlying polygons is what’s happening in this instance.

Thanks

Greg

Hi,
I think that what Ken means by scaling the value is that the returned value for z will be between 0 and 1 that should be scaled to near plane and far plane.

Yes, the DoubleBuffer / FloatBuffer issue was the problem in your original code. Additionally, you don’t have to use the SIZEOF_ constants unless you’re allocating a ByteBuffer and intend to use it as a FloatBuffer or similar; the BufferUtil arguments are in size of elements, not size of bytes. Also note that routines like glGetDoublev still have variants which take double[] in addition to DoubleBuffer; the only addition is the offset parameter which is usually 0.

turquoise3232 is right that the Z coordinates interpolate from the near plane to the far plane. This is described somewhere in the OpenGL Red Book – do a search for glReadPixels.

Thank you both for the help. I’ll pull up the redbook and do some searching. Thanks also, for the advise on using buffers. I had previously used the array versions of the functions, I changed them to buffers in an attempt to solve the problem early on.

I must say, this is the most helpful forum I have ever posted on.

Thanks again.

Greg