使用glm :: unproject()获取Z = 0平面上的光标位置?

时间:2019-11-11 16:42:14

标签: c++ opengl cursor glfw glm-math

我试图仅使用光标坐标来获取网格(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);

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

enter image description here

每个正方形为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)。没想到的。

  • 为什么y延迟了6个单位?
  • 有必要基于cursorCoordinatesToWorldCoordinates旋转结果rotationAngle吗?

-

我已经做了:

  • 检查视口是否与glViewport相匹配-确定
  • 检查了opengl坐标(Y向上,而不是Z)-确定

1 个答案:

答案 0 :(得分:1)

您想使光线从glm::vec3(this->cursorCoordinate.x, this->cursorCoordinate.y, 0.0)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。矩阵乘法不是Commutative