首先,您的代码表明您的窗口大小始终为 width=650, height=650。
那么当 z=0 时你就得到了这个位置。但是这个 z 在屏幕空间中,因此它会随着您更改相机位置和方向而改变。通常,您使用 glReadPixel 从深度缓冲区中获取此信息。在这种情况下你应该这样做。
但是,还有另一种方法可以做到这一点。在我将分享的代码中,我正在寻找射线(从鼠标位置生成)和平面(0,0,0)与法线(0,1,0)之间的交点,我希望这会有所帮助。
/*Given the inverse PV (projection*view) matrix, the position of the mouse on screen and the size of the screen, transforms the screen coordinates to world coordinates*/
glm::vec3 Picking::OnWorld(glm::mat4 const& m_inv, glm::vec2 const & spos,size_t width, size_t height) {
float x = spos.x;
float y = spos.y;
y = height - y;
//InputOrigin, start of the ray for intersection with plane
glm::vec4 inputO = glm::vec4(x / width*2.0f - 1.0f, y / height*2.0f - 1.0f, -1.0f, 1.0f); //transforms screen position to the unit cube range
glm::vec4 resO = m_inv*inputO; //transforms to world space
if (resO.w == 0.0f)
return glm::vec3(-1); //return an invalid value to show a problem during a calculation, normally this means that the m_inv matrix was incorrect
resO /= resO.w; //homogeneous division
glm::vec4 inputE = inputO; //inputEnd, the end of the ray
inputE.z = 1.0;
//End of ray to world space
glm::vec4 resE = m_inv*inputE;
//checks that the coordinates are correct
if (resE.w == 0.0f)
return glm::vec3(-1); //return an invalid value to show a problem during a calculation, normally this means that the m_inv matrix was incorrect
resE /= resE.w;
//ray for intersection
glm::vec3 ray = glm::vec3(resE - resO); //vector between z=-1 and z=1
glm::vec3 normalRay = glm::normalize(ray);
glm::vec3 normalPlane = glm::vec3(0, 1, 0); //detects collision with plane 0, normal 1
float denominator = glm::dot(normalRay, normalPlane);
if (denominator == 0)
return glm::vec3(-1); //return an invalid value to show a problem during a calculation, normally this means that the m_inv matrix was incorrect
float numerator = glm::dot(glm::vec3(resO), normalPlane);
//intersection between ray and plane
glm::vec3 result = glm::vec3(resO) - normalRay*(numerator / denominator);
return result;
}
可以从此链接读取交叉点的数学运算:
https://www.cs.princeton.edu/courses/archive/fall00/cs426/lectures/raycast/sld017.htm