我像这样设置场景(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);


场景渲染良好,在z = -10处包含四边形,在z = -30处包含一个巨型背景四边形。我现在正在尝试实现光线拾取,像这样(取自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;
}


然后按以下方式测试屏幕上的水龙头:

unproject(tapX, mDisplayHeight - tapY, BACKGROUND_Z);


预期的行为:返回的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)


投影矩阵:

[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]


模型矩阵:

[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()输出:

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


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

最佳答案

让我们看看-我无法复制您获得的值,但是我认为这没有关系。

不得使用不在unproject内的z值调用[-1;+1]unproject必须做的第一件事是逆向窗口变换,然后坐标必须在NDC空间中。在OpenGL中,这是立方体[-1;+1]^3songho包含一些漂亮的图形)。用unproject调用-30意味着该点必须位于近平面之前。用z=-1.0f进行调用会在近平面中进行,而z=+1.0f会在远平面中进行。

如何选择z s.t.在所有矩阵求逆之后,z=-30成立-我不知道。

10-07 23:55