将 2D 屏幕坐标取消投影到 3D 世界坐标

Unprojecting 2D screen coordinates to 3D world coordinates

我正在做一些投影,投影到 2D 后我想进行反向操作,取消投影到 3D。我唯一感到困惑的步骤是从 NDC 到 HDC 时,更具体地说,如何进行透视分割的反转?目前,当我做相反的事情时,我最终得到一个 -1 w 值,这在除法或乘法时不会做太多,或者我可能正在监督其他事情。这是我目前拥有的代码:

    private Vector3f projectTo3D(Matrix4f projection, Matrix4f view, Matrix4f world, Vector3f vertex) {

    Matrix4f.invert(projection, projection);
    Matrix4f.invert(view, view);
    Matrix4f.invert(world, world);

    System.out.println("projectTo3D - Screen Coordinate: " + vertex.toString());

    ....

    System.out.println("NDC: " + x + ", " + y + ", " + z);
    final Vector4f HDC = new Vector4f(x, y, z, -1f);
    HDC.x = HDC.x / HDC.w;
    HDC.y = HDC.y / HDC.w;
    HDC.z = HDC.z / HDC.w;

    System.out.println("HDC before transform: " + HDC.toString());
    Matrix4f.transform(worldProjectionView, HDC, HDC);
    System.out.println("HDC after transform: " + HDC.toString());

    final Vector3f worldCoordinates = new Vector3f(HDC.x, HDC.y, HDC.z);
    System.out.println("World coordinate: " + worldCoordinates.toString());
    return worldCoordinates;
}

projectTo2D - World Coordinate: Vector3f[-50.0, -50.0, 0.0]

HDC: Vector4f: -195.05373 -44.30973 -529.6105 -529.6105

NDC: Vector3f[0.3682966, 0.08366475, 0.0]

Screen coordinate: 547.31866, 325.09943, 0.0


projectTo3D - Screen Coordinate: Vector3f[547.31866, 325.09943, 0.0]

NDC: 0.36829662, 0.083664775, -1.0

HDC before transform: Vector4f: -0.36829662 -0.083664775 1.0 -1.0

HDC after transform: Vector4f: -292.38623 405.26837 -291.50772 1.0

World coordinate: Vector3f[-292.38623, 405.26837, -291.50772]

我正在关注这个图表:

你这里实际上有一个线性代数问题,不幸的是无法解决。当您将 3D 坐标 space 投影到 2D space 上时,这是模型-> 视口变换的工作,您会在此过程中丢失一个维度,而逆向问题变为 under-constrained.

我的意思是,如果你只有一个 2D 向量 space(比如屏幕上的一个点),那么就有无限多的 3D 向量可以投射到同一个向量上二维向量,形成一个新的一维向量space。由于投影不是仿射(线性)运算,这意味着您的 1D space 不是直线;而是 3D 中的曲线 space.

我好像自己解决了这个问题。我的错误是将投影矩阵的近平面设置为 0,这应该是最小值 0.1