我尝试遵循this tutorial的有关OpenGL中鼠标拾取的信息,但是我无法使其正常工作。
根据我的基本理解,要从鼠标坐标中获取世界空间坐标,我需要乘以一堆逆矩阵。然后,要从局部空间获取世界空间坐标,可以将局部空间坐标与模型矩阵相乘。但是我得到的坐标彼此不一致。
我试图归一化模型的世界坐标,因为鼠标坐标也被归一化了,但是我不确定是否是这种情况。
if (instance && button == GLFW_MOUSE_BUTTON_LEFT
&& action == GLFW_PRESS) {
glfwGetCursorPos(window, &x, &y);
pMat = instance->graphics->getPMat();
cameraPos = instance->graphics->getCameraPos();
//View matrix
vMat = glm::translate(glm::mat4(1.0f), glm::vec3(cameraPos.x, cameraPos.y, -cameraPos.z));
//vMat = glm::rotate(vMat, 0.6f, glm::vec3(1.0f, 0.0f, 0.0f));
//normalized mouse coordinates
x = (2.0f * x) / width - 1.0f;
y = 1.0 - (2.0f * y) / height;
glm::vec3 ray_nds = glm::vec3(x, y, 1.0f);
glm::vec4 ray_clip = glm::vec4(ray_nds.x, ray_nds.y, -1.0, 1.0);
glm::vec4 ray_eye = glm::inverse(pMat) * ray_clip;
ray_eye = glm::vec4(ray_eye.x, ray_eye.y, -1.0, 0.0f);
glm::vec3 ray_wor = glm::vec4(glm::inverse(vMat) * ray_eye);
ray_wor = glm::normalize(ray_wor);
Entity* e = instance->getCurrentScene().getEntities()[0];
sMat = glm::scale(glm::mat4(1.0f), glm::vec3(e->getScaleX(), e->getScaleY(), e->getScaleZ()));
tMat = glm::translate(glm::mat4(1.0f), glm::vec3(e->getX(), e->getY(), e->getZ()));
rMat = glm::rotate(glm::mat4(1.0f), e->getRotY(), glm::vec3(0.0f, 1.0f, 0.0f));
rMat = glm::rotate(rMat, e->getRotX(), glm::vec3(1.0f, 0.0f, 0.0f));
rMat = glm::rotate(rMat, e->getRotZ(), glm::vec3(0.0f, 0.0f, 1.0f));
mMat = tMat * rMat * sMat;
mvMat = vMat * mMat;
startCoords = mMat * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
startCoords = glm::normalize(startCoords);
endCoords = mMat * glm::vec4(1.0f, -1.0f, 1.0f, 1.0f);
endCoords = glm::normalize(endCoords);
if (ray_wor.x >= startCoords.x
&& ray_wor.y <= startCoords.y
&& ray_wor.x <= endCoords.x
&& ray_wor.y >= endCoords.y) {
std::cout << "\nFound!\n";
}
std::cout << "x: " << ray_wor.x << "\n"
<< "y: " << ray_wor.y << "\n"
<< "z: " << ray_wor.z << "\n\n";
std::cout << "x: " << endCoords.x << "\n"
<< "y: " << endCoords.y << "\n"
<< "z: " << endCoords.z << "\n\n";
std::cout << "x: " << startCoords.x << "\n"
<< "y: " << startCoords.y << "\n"
<< "z: " << startCoords.z << "\n\n";
}
答案 0 :(得分:0)
投影矩阵从视图空间转换为剪辑空间。在透视投影时,剪辑空间坐标为Homogeneous coordinates。从剪辑空间到规范化的设备空间的转换是通过Perspective divide完成的。
要从规范化的设备空间转换为视图空间,您需要做相反的事情:
// normalized device coordiantes
glm::vec3 nds_near = glm::vec4(x, y, -1.0f, 1.0f);
// view coordiantes
glm::vec4 eye_h = glm::inverse(pMat) * nds_near;
glm::vec4 ray_eye = glm::vec4(eye_h.x/eye_h.w, eye_h.y/eye_h.w, eye_h.z/eye_h.w, 1.0f);
// world coordinates
glm::vec3 ray_wor = glm::vec4(glm::inverse(vMat) * ray_eye);
ray_wor = glm::normalize(ray_wor);