【问题标题】:OpenGL project mouse coordinate point to ground plane pointOpenGL投影鼠标坐标点到地平面点
【发布时间】:2020-10-07 11:18:55
【问题描述】:

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

这是一个代码sn-p:

    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

这是我想要实现的图片:

【问题讨论】:

  • 您已将射线上点的视空间 z 坐标设置为常数值 -1.0。将其更改为i_tmp = QtGui.QVector4D((tmp * self.camera.projectionMatrix.inverted()[0]).toVector3D(), 0.0)
  • @Artem cam_posdirection 和 t` 的值是什么?他们都是0吗?如果射线在世界的 x-z 平面中,则没有交点。
  • @Artem 见公式result = cam_pos + direction * t。如果tdirection 为0,那么result 也为0。如果direction 的 x any z 分量为 0,则光线在世界的地平面中(平行于地平面)。您不能将平面与平面中的射线相交。
  • @Artem 不,公式是正确的,但是如果相机位置在地面上,那么光线在地平面上。你的眼睛在地面上,你沿着地面看。所以你找不到交点。
  • @Artem 相机位置必须有一个 y 分量。

标签: python qt math opengl pyside2


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多