OpenGL:gluUnProject返回错误的坐标

man*_*mal 1 android opengl-es ray-picking

我设置了我的场景(Android应用程序,OpenGL ES),如下所示:

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);
Run Code Online (Sandbox Code Playgroud)

场景渲染得很好,它包含z = -10处的四边形和z = -30处的一个巨型背景四边形.我现在正在尝试实现光线拾取,就像这样(取自这个线程:

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;
}
Run Code Online (Sandbox Code Playgroud)

然后以这种方式测试屏幕上的点击:

unproject(tapX, mDisplayHeight - tapY, BACKGROUND_Z);
Run Code Online (Sandbox Code Playgroud)

预期行为:返回的X,Y坐标类似于深度= -30处的抽头点(BACKGROUND_Z)

它的实际作用:在屏幕中心点击时返回正确的X,Y坐标; 但是屏幕中心和分接点之间的距离没有被正确解释 - 它似乎被一些因素缩小了.例如,点击屏幕中心给出[0,0],点击左侧屏幕边缘应该给出〜[ - 3600,0],而是给出[-1.13,0].平移视图使得先前触摸的点在屏幕中心给出〜[-3600,0],就像它应该的那样.

这可能是由于场景缩放0.001?我测试了各种配置(在gluLookAt之前移动缩放,或者完全删除它),但问题依然存在:(


左屏幕边缘触摸的样本数据输出:

传递给unproject()的接触点:

x=3, y = 554 (0,0 at bottom left; w=720, h=1280)
Run Code Online (Sandbox Code Playgroud)

投影矩阵:

[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]
Run Code Online (Sandbox Code Playgroud)

模型矩阵:

[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]
Run Code Online (Sandbox Code Playgroud)

unproject()输出:

[-1.1232367, -0.11801138, -1.0032262, 1.0]
Run Code Online (Sandbox Code Playgroud)

我想到的是返回的z值似乎是错误的 - 传递给unproject()的z值是-30(如上所述).

Ste*_*nke 5

让我们看看 - 我无法重现你所获得的价值观,但我认为这无关紧要.

您不得使用不在unproject其中的z值进行调用[-1;+1].首先unproject必须做的是反转窗口变换,然后坐标必须在NDC空间中.在OpenGL中,这是立方体[-1;+1]^3(songho包含一些漂亮的图形).调用unproject-30手段的点一定是近平面之前.使用z=-1.0f近平面和z=+1.0f远平面中的结果调用它.

z所有矩阵反演后如何选择st,z=-30持有 - 我不知道.