You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenGL 3实现鼠标拾取时获取的方向向量与世界坐标异常

错误1:三角形参数传递错误

你调用glm::intersectLineTriangle()时三个顶点都传入了m_vertices_world[0],构成了面积为0的退化三角形,永远不会触发相交判定,这是最明显的笔误,应该修改为三个不同的三角形顶点:

// 错误写法
if(glm::intersectLineTriangle(..., m_vertices_world[0], m_vertices_world[0], m_vertices_world[0], intersect))
// 正确写法示例
if(glm::intersectLineTriangle(..., m_vertices_world[0], m_vertices_world[1], m_vertices_world[2], intersect))

错误2:齐次坐标未做透视除法

你用逆VP矩阵变换裁剪空间坐标后,没有执行齐次除法除以w分量,直接取xyz分量计算方向会引入误差,需要补充该步骤:

glm::vec4 worldPos = invVP * screenPos;
worldPos /= worldPos.w; // 补充齐次除法

错误3:射线方向计算逻辑错误

你当前直接将远平面的世界坐标归一化作为方向向量,没有考虑射线起点的位置:

  • 透视投影下的拾取射线应该从近平面指向远平面,你需要分别计算裁剪空间z=-1(近平面)和z=1(远平面)的两个世界坐标点,再计算方向
  • 射线起点不是默认的(0,0,0),除非你的相机固定在世界空间原点,正确的射线起点是相机的世界坐标,或者你用近平面的世界坐标作为起点
    正确的方向计算示例:
// 计算近平面、远平面的世界坐标
glm::vec4 nearScreenPos = glm::vec4(mouseX, -mouseY, -1.0f, 1.0f);
glm::vec4 farScreenPos = glm::vec4(mouseX, -mouseY, 1.0f, 1.0f);
glm::vec4 nearWorld = invVP * nearScreenPos;
glm::vec4 farWorld = invVP * farScreenPos;
nearWorld /= nearWorld.w;
farWorld /= farWorld.w;

glm::vec3 rayOrigin = glm::vec3(nearWorld);
glm::vec3 rayDir = glm::normalize(glm::vec3(farWorld - nearWorld));

错误4:GLFW鼠标Y轴适配问题

GLFW返回的鼠标Y坐标左上角为原点,OpenGL的NDC坐标左下角为原点,部分设备可能存在帧缓冲区尺寸和窗口尺寸不匹配的情况(比如高DPI屏),如果转换后Y方向仍然反向,可以调整-mouseY的符号。

内容的提问来源于stack exchange,提问作者rial

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 18:15:01