OpenGL投影鼠标坐标点到地平面点

OpenGL project mouse coordinate point to ground plane point

我正在尝试编写一个函数,将鼠标位置转换为 XOZ(地平面)上的坐标点以在那里绘制几何图形。 问题是:公式似乎不对。有一个相机点 (0, 0, 0, 1) 乘以 viewmatrix,结果是 (0, 0, 0) 点。我已经尝试使用 lookAt() 矩阵中的 camEye 作为一个点,但它不起作用。我该如何实施?

这是一个代码片段:

    def screenToWorld(self, mouse_pos: QtGui.QVector2D):
        tmp = QtGui.QVector4D(
            2.0 * mouse_pos.x() / self.width() - 1.0,
            -2.0 * mouse_pos.y() / self.height() + 1.0,
            -1.0, 1.0
        )
        i_tmp = QtGui.QVector4D(
            (tmp * self.camera.projectionMatrix.inverted()[0]).toVector2D(), -1.0, 0.0
        )
        direction = QtGui.QVector3D(
            (i_tmp * self.camera.viewMatrix.inverted()[0]).toVector3D().normalized()
        )
        cam_pos = QtGui.QVector3D(
            (QtGui.QVector4D(0.0, 0.0, 0.0, 1.0) * self.camera.viewMatrix.inverted()[0]).toVector3D()
        )

        normal = QtGui.QVector3D(0.0, 1.0, 0.0)
        t = -QtGui.QVector3D.dotProduct(cam_pos, normal) / QtGui.QVector3D.dotProduct(direction, normal)
        result = cam_pos + direction * t

        return result

这是我想要实现的图片:

好的,我终于明白了!问题出在不正确的相机位置。 正如我所读到的,我们可以从倒 view matrix 中得到它。索引为 41, 42, 43 的元素将是我们的相机位置,所以我写了一个 class 变量,每次相机移动时都会更新:

self.__camPos = self.__viewMatrix.inverted()[0].column(3).toVector3D()

在那之后,一切都很顺利:

    def createRayDir(self, mouse_pos: QVector2D):
        # Normalized Coordinate Space
        x = 2.0 * mouse_pos.x() / self.__viewportSize.x() - 1
        y = 2.0 * mouse_pos.y() / self.__viewportSize.y() - 1

        clip = QVector4D(x, -y, -1.0, 1.0)
        proj = QVector4D((clip * self.__projectionMatrix.inverted()[0]).toVector2D(), -1.0, 0.0)

        return (proj * self.__viewMatrix).toVector3D().normalized()

    def getRayGridIntersecton(self, mouse_pos: QVector2D):
        ray_dir = self.createRayDir(mouse_pos)

        n = QVector3D(0.0, 1.0, 0.0)
        t = -QVector3D.dotProduct(self.__camPos, n) / QVector3D.dotProduct(ray_dir, n)

        return self.__camPos + ray_dir * t