Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gluUnProject Android OpenGL ES 1.1 Usage

I'm trying to use gluUnProject to convert windows coords to world coords. I'm not trying to get working sample in emulator or older Android systems (with OpenGL ES v1.0) and this is not question about GL function availability. I'm trying to work on the real device with OpenGL ES 1.1 and glGet functions return non-zero results.

There is sample:

public Vector3 translateScreenCoordsToWorld(Vector2 screenCoords) {
gl.glLoadIdentity();

final Matrix4x4 modelViewMatrix = new Matrix4x4();
final Matrix4x4 projectMatrix = new Matrix4x4();

int[] viewVectorParams = new int[4];
gl.glGetIntegerv(GL11.GL_VIEWPORT,viewVectorParams,0);
gl.glGetFloatv(GL11.GL_MODELVIEW_MATRIX,modelViewMatrix.buffer,0);
gl.glGetFloatv(GL11.GL_PROJECTION_MATRIX,projectMatrix.buffer,0);

float[] output = new float[4];
GLU.gluUnProject(
    screenCoords.x, screenCoords.y, 0, 
    modelViewMatrix.buffer, 0, 
    projectMatrix.buffer, 0, 
    viewVectorParams, 0, 
    output, 0);             

return new Vector3(output[0],output[1],output[2]);

}

Matrix4x4 is just a wrapper for float[] buffer;

With this function I'm trying to create a plane to fill all screen or detect maximum world coords for current projection matrix, but it's not working at all because I not really sure that I'm using these functions correctly.

For example when I'm trying run translateScreenCoordsToWorld(new Vector2(480,800)) it returns very small coordinates values Vector3(0.27f, 0.42f, -1.0f).

Could anyone provide good sample usage gluUnProject for GL_PROJECTION mode with one positioned camera.

Updated Thanks for good links. But it' still not working for me :( Now my function looks like:

public Vector3 translateScreenCoordsToWorld(Vector2 screenCoords) {

float winX = screenCoords.x, winY = screenCoords.y, winZ = 0;
winY = (float)currentViewVectorParams[3] - winY;

float[] output = new float[4];
GLU.gluUnProject(
    winX, winY, winZ, 
    currentModelViewMatrix.buffer, 0, 
    currentProjectMatrix.buffer, 0, 
    currentViewVectorParams, 0, 
    output, 0
);              

Vector3 nearPlane = new Vector3(output[0],output[1],output[2]);
winZ = 1.0f;        
GLU.gluUnProject(
    winX, winY, winZ, 
    currentModelViewMatrix.buffer, 0, 
    currentProjectMatrix.buffer, 0, 
    currentViewVectorParams, 0, 
    output, 0
);              
Vector3 farPlane = new Vector3(output[0],output[1],output[2]);

farPlane.sub(nearPlane);
farPlane.div( nearPlane.length());

float dot1, dot2;

Vector3 pointInPlane = new Vector3(), pointPlaneNormal = new Vector3(0,0,-1);
pointInPlane.sub( nearPlane );

dot1 = (pointPlaneNormal.x * pointInPlane.x) + (pointPlaneNormal.y * pointInPlane.y) + (pointPlaneNormal.z * pointInPlane.z);
dot2 = (pointPlaneNormal.x * farPlane.x) + (pointPlaneNormal.y * farPlane.y ) +(pointPlaneNormal.z * farPlane.z);

float t = dot1/dot2;
farPlane.mul(t);

return farPlane.add(nearPlane);
}

and this is where my camera configuring:

public void updateCamera() {
Camera camera = scene.getCamera();
GLU.gluLookAt(gl, 
    camera.position.x, camera.position.y, camera.position.z,
    camera.target.x, camera.target.y, camera.target.z,
    camera.upAxis.x, camera.upAxis.y, camera.upAxis.z
);

    gl.glGetIntegerv(GL11.GL_VIEWPORT,currentViewVectorParams,0);       
    gl.glGetFloatv(GL11.GL_MODELVIEW_MATRIX, currentModelViewMatrix.buffer,0);
    gl.glGetFloatv(GL11.GL_PROJECTION_MATRIX,currentProjectMatrix.buffer,0);
}

The camera configured with the following coords:

camera.position = { 0, 0, 65 };     
camera.target = { 0, 0, 0 }
camera.upAxis = { 0, 1, 0 }
like image 475
abdolence Avatar asked Sep 15 '11 21:09

abdolence


1 Answers

Okay, normally when using gluUnProject you are trying to get the world space coordinate of a pixel on screen. You need three pieces of information,(other than the matrices) to put into glUnProject, a screen x coordinate , a screen y coordinate, and the depth buffer value corresponding to that pixel. The process normally goes like this:

  1. Draw a frame, so all the depth buffer information is ready.
  2. Grab viewport/matrices/screen coords
  3. Invert the screen y coordinate.
  4. Read the depth value at a given pixel. This is effectively a normalised z coordinate.
  5. Input the x,y and z into glUnProject.

This ends up giving the world space coordinate of the given fragment of a pixel. A much more detailed guide can be found here. Anyway, I can see two possible mistakes in your code. The first is that normally you have to invert the y screen coord,(the tutorial on the link details why), the second is that you are always passing in 0 as the z value to gluUnProject. Doing this un-projects the vertex as if it was on the near plane. Is this what you want?

Anyway, forgive me if I misread your question.

like image 83
Darcy Rayner Avatar answered Nov 03 '22 10:11

Darcy Rayner