我试图确定一个对象(球体(是否在视锥体内。我的策略是首先获取视图矩阵:
glm::lookAt(cameraPosition, lookAtPosition, cameraUp);
其中cameraPosition
是相机的位置,lookAtPosition
是按cameraPosition + cameraDirection
计算的,cameraUp
几乎是不言自明的。
得到视图矩阵后,我计算相机视图中视锥体的 8 个顶点,然后将视图矩阵的逆乘以每个点,得到它们在世界空间中的坐标。
使用世界空间中的这 8 个点,我可以使用叉积构造 6 个平面(因此它们的法线将指向内部(。然后我取对象向量的点积(我通过减去该平面上的任意点的对象位置来获得向量(与每个平面的法线向量,如果它对所有 6 个都是正数,我知道它在视锥体内。
所以我的问题是:
- 相机视图是否始终设置为 (0,0,0( 并查看正 z 方向? 视图矩阵将世界观转换为相机视图,
- 如果我使用它的反转将相机视图转换为世界视图,是否正确?
我的视锥体与我的cameraDirection
相反,这导致屏幕上看不到任何东西(但它仍然在我的相机背面画东西(。
相机视图是否始终设置为 (0,0,0( 并查看正 z 方向?
视图空间是定义场景外观的空间.
哪个部分是"可见"的(投影到视口上(取决于投影矩阵。通常(在 OpenGL 中(原点为 (0,0,0(,视图空间z轴指向视口之外。但是,投影矩阵会反转z轴。它从视图空间的右手系统转向规范化设备空间的左手系统。
将相机视图转换为世界视图的反之
则
是的。
视图矩阵从世界空间转换为视图空间。投影矩阵将视图空间的笛卡尔坐标转换为剪辑空间的齐次坐标。通过将xyz分量除以w分量(透视除法(,将剪辑空间坐标转换为规范化设备空间。
规范化设备空间是最小值为 (-1, -1, -1( 和最大值为 (1, 1, 1( 的多维数据集。因此,立方体的 8 个角点是归一化设备空间中观看体积的角。
(-1, -1, -1) ( 1, -1, -1) ( 1, 1, -1) (-1, 1, -1) // near plane
(-1, -1, 1) ( 1, -1, 1) ( 1, 1, 1) (-1, 1, 1) // far plane
如果要将点从规范化设备空间转换为视图空间,则必须:
- 通过逆投影矩阵进行变换
- 通过逆视图矩阵进行变换 将
- 结果的XYZ分量除以其w分量
glm::mat4 view; // view matrix
glm::mat4 projetion; // projection matrix
glm::vec3 p_ndc; // a point in normalized device space
glm::mat4 inv_projetion = glm::inverse( projetion );
glm::mat4 inv_view = glm::inverse( view );
glm::vec4 pth = inv_view * inv_projetion * glm::vec4( p_ndc, 1.0f );
glm::vec3 pt_world = glm::vec3( pth ) / pth.w;