通过鼠标获取模型上某个点的世界坐标
- 之前做的的,现在反过来。退到第二部分(通过乘以逆矩阵)
过程
坐标
先得出屏幕踩点空间的坐标,注意每一个像素对应坐标的长度比例,设备坐标等等。以下是X和Y的转化。
- z(W)的值与深度值之间的关系,由线面这个公式可以知道深度值反推出W值然后用到
- 这里边F就是代码中的winZ,z就是w
代码
都在main函数中
- 参数
//世界坐标要用到的
float near = 10.6f, far = 100.0f, winZ;
bool pickingModelWorldPosition = false;
double winX, winY;
- while循环中的判断函数放在while循环的末尾
- 添加W值转化为标准化之前的坐标。(去标准化)
- 反投影inverse函数:让xyz1先乘以w去标准化然后再乘以逆投影矩阵,然后再乘以逆函数矩阵
if (pickingModelWorldPosition == true)
{
glReadPixels((int)winX, 600 - (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ); //要取Z就要用到
float x = (2.0f * winX) / 800.0f - 1.0f;//求到像素的X
float y = 1.0f - (2.0f * winY) / 600.0f;//求到像素的Y
float z = winZ * 2.0 - 1.0f; //z的标准化
pickingModelWorldPosition = false;
if (winZ < 1.0f)
{
//float w = (2.0 * near * far) / (far + near - z * (far - near));
float w = near * far / (near * winZ - far * winZ + far); //w 值
glm::vec4 wolrdPostion = glm::inverse(view) * glm::inverse(projection) * w * glm::vec4(x, y, z, 1);
cout << " x:" << wolrdPostion.r << " y:" << wolrdPostion.g << " z:" << wolrdPostion.b << " w:" << w << endl;
}
else
cout << "没有点中模型...." << endl;
}
- 判断是否点击,给Input函数添加代码
void processInput(GLFWwindow* window) {
glfwSetMouseButtonCallback(window, mouse_button_callback); //触发鼠标点击事件触发回调函数
- 上一个函数的回调函数,注意回调函数要在文件上边先声明一下
//鼠标点击触发的回调函数,注意四个参数
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
if (action == GLFW_PRESS) switch (button) //触发事件switch
{
case GLFW_MOUSE_BUTTON_LEFT: //左键
glfwGetCursorPos(window, &winX, &winY);
pickingModelWorldPosition = true;
break;
default:
return;
}
return;
}
- 注意要去掉的函数 ,否则窗口就不会拦截鼠标,就看不见鼠标
//glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); //防止窗口对鼠标进行拦截