将鼠标坐标转换为世界空间坐标

Posted

技术标签:

【中文标题】将鼠标坐标转换为世界空间坐标【英文标题】:Translating mouse coordinates to world space coordinates 【发布时间】:2017-04-23 12:50:56 【问题描述】:

我正在使用 GLFW,我想在单击选定位置时通过窗口上的鼠标坐标获取世界空间坐标以绘制对象。首先,我试图仅使用矩阵变换来获得这个坐标,但结果我没有得到任何有意义的东西。

glfwGetCursorPos(window, &xPos, &yPos);
mat4 inverse_projection = glm::inverse(projection);
mat4 inverse_view = glm::inverse(view);

GLdouble normalized_coord2D_x = (2.0 * xPos / -1.0),
    normalized_coord2D_y = (2.0 * yPos / -1.0);

vec4 worldCoordNear;
vec4 worldCoordFar;

vec4 normalizedCoordNear = vec4(normalized_coord2D_x, normalized_coord2D_y, -1.0, 1.0);
vec4 clipCoordNear = normalizedCoordNear;
vec4 eyeCoordNear = inverse_projection * clipCoordNear;
worldCoordNear /= worldCoordNear.w;

vec4 normalizedCoordFar = vec4(normalized_coord2D_x, normalized_coord2D_y, 1.0, 1.0);
vec4 clipCoordFar = normalizedCoordFar;
vec4 eyeCoordFar = inverse_projection * clipCoordFar;
worldCoordFar = inverse_view * eyeCoordFar;
worldCoordFar /= worldCoordFar.w;

现在我放弃了该解决方案并尝试在简单的 2D 场景中使用 gluUnProject 解决问题,我的功能如下所示:

void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods)

    if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) 
    std::cout << "Left button pressed" << std::endl;

    GLdouble xPos, yPos;
    glfwGetCursorPos(window, &xPos, &yPos);

    GLint viewport[4];
    GLdouble modelview[16];
    GLdouble projection[16];
    GLfloat winX, winY, winZ;
    GLdouble posX, posY, posZ;

    glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
    glGetDoublev(GL_PROJECTION_MATRIX, projection);
    glGetIntegerv(GL_VIEWPORT, viewport);

    winX = (float)xPos;
    winY = (float)viewport[3] - (float)yPos;
    glReadPixels(xPos, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);

    gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
    

我收到错误:

LNK2019 未解析的外部符号 _gluUnProject@48 在中引用 函数“无效__cdecl mouseButtonCallback(结构 GLFWwindow*,int,int,int)" (?mouseButtonCallback@@YAXPAUGFWwindow@@HHH@Z)

我正在开发 VS2015,这就是我的内容:

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <math.h>
#include <iostream>
#include <GL/GLU.h>
#include <Windows.h>

值得指出的是,我用 NuGet Packages 下载的 glu 库

我将非常感谢所有帮助和关于如何解决问题的解释。

【问题讨论】:

只是指出显而易见的。但是由于这是一个链接器问题,你确定你正在链接并提供 lib 文件的正确路径吗? 那么我在哪里可以找到 glu32.lib?因为我找不到它,我看到 gluUnProject 需要 Glu32.lib,我只链接了 opengl32.lib、glew32.lib、glfw3.lib 好的,我解决了问题,但现在的问题是如果我使用透视,gluUnProject 会返回好的值吗? 【参考方案1】:

基本上,您的投影矩阵会将顶点从相机/眼睛空间带到剪辑空间,然后它会进行透视划分以获得标准化的设备坐标。然后,您使用该窗口变换提到的任何视口都将应用于它以获得屏幕坐标。 gluUnProject 正在以相反的顺序为您执行此操作。所以请放心,它将赋予良好的价值。

【讨论】:

以上是关于将鼠标坐标转换为世界空间坐标的主要内容,如果未能解决你的问题,请参考以下文章

窗口调整大小后将鼠标位置转换为 2D openGL 中的世界坐标

在 CUDA 中,如何在内核函数中将屏幕空间坐标转换为世界空间坐标

使用 glut 函数 glutMouseFunc() 将窗口坐标转换为 3D 世界坐标

世界坐标空间与观察坐标系之间的转换

Cesium 获取鼠标点击坐标及世界坐标与弧度(经纬度)转换

Unity坐标转换