我使用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);
}
}
我得到了错误:
LNK 2019函数“void __cdecl mouseButtonCallback(struct GLFWwindow*,int,int,int)”中引用的未解析外部符号_gluUnProject@48(?mouseButtonCallback@@YAXPAUGLFWwindow@@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库
我将非常感谢所有的帮助和解释如何解决这个问题。
2条答案
按热度按时间eqqqjvef1#
基本上,你的投影矩阵会将顶点从相机/眼睛空间带到剪辑空间,然后它会进行透视分割以获得标准化的设备坐标。然后你提到的任何视口都会使用该窗口变换来获得屏幕坐标。gluUnProject正在以相反的顺序为您做这件事。因此,请放心,它将给予良好的价值观。
oogrdqng2#
重要的是要确切地知道你要做什么和起作用的变量。因此,将鼠标坐标转换为可以与模型顶点交互的坐标,就像这样。
在屏幕空间中,坐标从左上角(0,0)开始,到右下角(屏幕宽度,屏幕高度)结束。
世界空间使用x轴和y轴上介于-1和1之间的栅格系统进行操作。所以你要做的是把基于宽度/高度的坐标转换成基于-1/1的坐标。
要做到这一点,请将坐标系和您当前的位置视为字符串上的距离。鼠标坐标的当前位置就是鼠标移动了这个字符串总距离的X%。
我发现最有效的转换方法使用以下变量:世界空间栅格的总大小,值为2。在特定轴上移动的距离的百分比,即x或y坐标分别除以宽度或高度。最后一个变量是偏移量1,这是必需的,因为世界空间中屏幕的左上角是(-1,1),而不是(0,0)。
转换当前x轴的公式如下所示:
y轴的方程几乎是一样的。其中,由于视口变换的工作方式,2和1常量值的符号被反转。Y轴方程看起来像这样:
重要的是要注意,系统的实际屏幕分辨率可能会阻止上述公式产生准确的结果。要确保正确的精度,请根据显示器的实际纵横比设置窗口的宽度和高度。如果你不这样做,你将不得不手动调整窗口大小,帧缓冲区大小回调将纠正这个问题。