1

I set up my scene (Android app, OpenGL ES) like this:

GLU.gluPerspective(gl, 60, viewRatio, 0.1f, 1000.0f);
// ...
GLU.gluLookAt(gl, cameraX, cameraY, cameraZ, cameraX, cameraY, cameraZ - 1f, 0f, 1f, 0f);
// Scene scaled down because object positions are in [-10000..10000] for x & y
gl.glScalef(0.001f, 0.001f, 1.0f);

The scene is rendered well, it contains quads at z=-10 and one giant background quad at z=-30. I am now trying to implement ray picking, like this (taken from this thread:

public float[] unproject(float rx, float ry, float rz) {
    float[] xyzw = {0, 0, 0, 0};
    int[] viewport = {0, 0, mDisplayWidth, mDisplayHeight};
    android.opengl.GLU.gluUnProject(rx, ry, rz, mMatrixGrabber.mModelView, 0, mMatrixGrabber.mProjection, 0, viewport, 0, xyzw, 0);
    xyzw[0] /= xyzw[3];
    xyzw[1] /= xyzw[3];
    xyzw[2] /= xyzw[3];
    xyzw[3] = 1;
    return xyzw;
}

Taps onto the screen are then tested this way:

unproject(tapX, mDisplayHeight - tapY, BACKGROUND_Z);

Expected behaviour: Returned X,Y coordinates resemble the tapped point at depth = -30 (BACKGROUND_Z)

What it actually does: Returns correct X,Y coordinates when tapped at the screen center; But the distance between screen center and tapped-point is not interpreted correctly - it seems to be scaled down by some factor. E.g. tap on screen center gives [0,0], tap on left screen edge should give ~[-3600,0], but instead gives [-1.13,0]. Panning the view such that the previously touched point is in the screen center gives ~[-3600,0], as it should.

Can this be due to the scaling of the scene by 0.001? I have tested various configurations (moving scaling before gluLookAt, or entirely removing it), but the problem persists :(


Sample data output for touch at left screen edge:

Touch point passed to unproject():

x=3, y = 554 (0,0 at bottom left; w=720, h=1280)

Projection matrix:

[2.8482616, 0.0,       0.0,         0.0, 
 0.0,       1.7320509, 0.0,         0.0, 
 0.0,       0.0,      -1.0001999,  -1.0, 
 0.0,       0.0,      -0.20001999,  0.0]

Model matrix:

[0.0010, 0.0,    0.0, 0.0, 
 0.0,    0.0010, 0.0, 0.0, 
 0.0,    0.0,    1.0, 0.0, 
 0.0,    0.0,    1.0, 1.0]

unproject() output:

[-1.1232367, -0.11801138, -1.0032262, 1.0]

What comes to my mind here is that the returned z value seems to be wrong - the z value passed into unproject() is -30 (as mentioned above).

Community
  • 1
  • 1
manmal
  • 3,900
  • 2
  • 30
  • 42
  • Does the [MatrixGrabber](http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/MatrixGrabber.html) contain the correct matrices? Viewport correct? It looks weird though that homogeneous coordinates are used down to model coordinates. – Stefan Hanke Mar 28 '12 at 16:06
  • My MatrixGrabber has valid matrices - don't know if they are ok. Viewport is always [0,0,w,h]. Can you give me a tip regarding homogeneous -> model coordinates? – manmal Mar 28 '12 at 18:06
  • No this is OK. Projective parts come from projection matrices, and all other affine matrices are built s.t. these parts are passed-through. My guess is that the scale somehow is not present in the grabbers's `mModelView`. For the matrix manipulation calls given in your example, can you show the two grabber matrices, and the `xyzw` output directly after `gluUnProject`? – Stefan Hanke Mar 29 '12 at 00:26
  • updated the question with the sample values you requested :) – manmal Mar 29 '12 at 08:03

1 Answers1

5

Let's see -- I wasn't able to reproduce the values you got, however I think this does not matter.

You must not call unproject with z-values not within [-1;+1]. The first thing unproject must do is reverse the windowing transform, and after that, the coordinates must be in NDC-space. In OpenGL, this is the cube [-1;+1]^3 (songho contains some nice graphics). Calling unproject with -30 means that the point must have been before the near plane. Calling it with z=-1.0f results in the near plane, and z=+1.0f in the far plane.

How to choose z s.t. after all matrix inversions, z=-30 holds -- I don't know.

Stefan Hanke
  • 3,458
  • 2
  • 30
  • 34
  • man, you are my hero, totally saved my day/week! setting winz to -1 gives a z-value of -1.05, and a winz of 1 gives a z-value of -1001.5 (with corresponding x,y values). given both points, I can calculate a ray and intersect it with my quads. thanks so much! – manmal Mar 29 '12 at 19:00
  • 1
    Glad to hear that! I (used to) love this type of math, even waded through [Jim Blinn's](http://en.wikipedia.org/wiki/Jim_Blinn) articles and books. If you think you know stuff, he _will_ twist it ;) – Stefan Hanke Mar 30 '12 at 03:30