首页 > 解决方案 > 使用 glm::unproject() 获取 Z = 0 平面上的光标位置?

问题描述

我正在尝试仅使用光标坐标来获取网格(z = 0)的坐标(x,y)。经过长时间的搜索,我发现使用glm::unproject.

首先,我使用回调获取光标坐标:

void cursorCallback(GLFWwindow *window, double x, double y)
{
    this->cursorCoordinate = glm::vec3(x, (this->windowHeight - y - 1.0f), 0.0f);
}

然后转换这些坐标:

glm::vec3 cursorCoordinatesToWorldCoordinates()
{
            glm::vec3 pointInitial = glm::unProject(
                                              glm::vec3(this->cursorCoordinate.x, this->cursorCoordinate.y, 0.0),
                                              this->modelMatrix * this->viewMatrix,
                                              this->projectionMatrix,
                                              this->viewPort
                                              );

            glm::vec3 pointFinal = glm::unProject(
                                              glm::vec3(this->cursorCoordinate.x, this->cursorCoordinate.y, 1.0),
                                              this->modelMatrix * this->viewMatrix,
                                              this->projectionMatrix,
                                              this->viewPort
                                              );

            glm::vec3 vectorDirector = pointFinal - pointInitial;

            double lambda = (-pointInitial.y) / vectorDirector.y;

            double x = pointInitial.x + lambda * vectorDirector.x;
            double y = pointInitial.z + lambda * vectorDirector.z;

            return glm::vec3(x, y, 0.0f);
}

我使用 ArcBall 相机围绕指定轴旋转世界,这就是我生成 MVP 矩阵的方式:

this->position = glm::vec3(0.0f, 10.0f, 5.0f);
this->up = glm::vec3(0.0f, 1.0f, 0.0f);
this->lookAt = glm::vec3(0.0f, 0.0f, 0.0f);

this->fieldView = 99.0f;
this->farDistance = 100.0f;
this->nearDistance = 0.1f;

this->modelMatrix      = glm::mat4(1.0f);
this->viewMatrix       = glm::lookAt(this->position, this->lookAt, this->up) * glm::rotate(glm::degrees(this->rotationAngle) * this->dragSpeed, this->rotationAxis);
this->projectionMatrix = glm::perspective(glm::radians(this->fieldView), 1.0f, this->nearDistance, this->farDistance);

但是出了点问题,因为我没有得到正确的结果。看看这个应用程序的打印:

在此处输入图像描述

每个正方形为 1 个单位,立方体在位置 (0, 0, 0) 处渲染。当rotationAngle = 0将光标放在 (0,0), (1,1), (2,2), (3,3), (4,4), (5,5) 我得到 (0, 5.7), (0.8, 6.4), (1.6, 6.9), (2.4, 7.6), (3.2, 8.2), (4.2, 8.8)。这不是预期的。

--

我已经这样做了:

标签: c++openglcursorglfwglm-math

解决方案


您希望将来自glm::vec3(this->cursorCoordinate.x, this->cursorCoordinate.y, 0.0)to的光线glm::vec3(this->cursorCoordinate.x, this->cursorCoordinate.y, 1.0)与世界空间中的网格相交,而不是(长方体的)模型空间。你必须跳过this.modelMatrix

glm::vec3 pointInitial = glm::unProject(
    glm::vec3(this->cursorCoordinate.x, this->cursorCoordinate.y, 0.0),
    this->viewMatrix,
    this->projectionMatrix,
    this->viewPort);

glm::vec3 pointFinal = glm::unProject(
    glm::vec3(this->cursorCoordinate.x, this->cursorCoordinate.y, 1.0),
    this->viewMatrix,
    this->projectionMatrix,
    this->viewPort);

无论如何this->modelMatrix * this->viewMatrix都是不正确的。如果您想将光线与模型空间中的对象相交,那么它必须是this->viewMatrix * this->modelMatrix. 矩阵乘法不是可交换的。


推荐阅读