PDA

View Full Version : Detremining the window z from glReadPixels()



gmseed
11-07-2011, 03:20 AM
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
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]);
}

===

glfreak
11-07-2011, 08:16 AM
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.

gmseed
11-07-2011, 08:53 AM
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(),ray Start.getZ());
gl2.glVertex3d(rayEnd.getX(),rayEnd.getY(),rayEnd. getZ());
gl2.glEnd(); // finished drawing the line
}

glfreak
11-07-2011, 10:31 AM
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).