glm::lookAt returns 具有 nan 元素的矩阵
glm::lookAt returns matrix with nan elements
我想为垂直观察地面的相机创建一个视图矩阵:
glm::mat4 matrix = glm::lookAt(glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
最后一个参数是全局向上向量,所以一切似乎都是正确的,但我得到了以下 matirx:
-nan -nan -0 0
-nan -nan 1 0
-nan -nan -0 0
nan nan -1 1
我想我得到 nan 是因为观察向量与向上向量平行,但是如何使用 glm::lookAt 函数构建正确的视图矩阵。
在lookAt
中不可能让观察方向和向上矢量看向同一方向。如果您想要一个沿负 y 轴观察的相机,则必须调整向上矢量,例如 [0,0,1]
。在向上向量中指定的方向控制相机如何围绕视图轴旋转。
问题出在相机的位置或向上矢量上。
您的相机向上 1 个单位 (0,1,0),向下看原点 (0,0,0)。向上向量表示相机的向上方向,而不是世界space。例如,如果您向前看,向上矢量将为 +Y。如果您向下看,头顶朝向 +X,那么向上矢量对您来说就是 +X。它必须与相机的位置矢量完全不平行。
解决方案:
- 将向上矢量更改为沿 XZ 平面的任何方向
- 或者当投影到 XZ 平面上时不是 (0,0,0) 的东西
- 移动您的相机,使其位于 Y 轴以外的任何位置
我 运行 昨天在 return 由 glm::lookAt() 编辑的矩阵中遇到了同样的 NaN 问题,并提出了我认为是解决方法的方法。对于 UP 向量是 vec3(0.0f, 1.0f, 0.0f) 的特殊问题,这似乎对我有用,这似乎是一个常见的用例。
我的 Vulkan 代码如下所示:
struct UniformBufferObject {
alignas(16) glm::mat4 model;
alignas(16) glm::mat4 view;
alignas(16) glm::mat4 proj;
};
...
UniformBufferObject ubo{};
...
glm::vec3 cameraPos = glm::vec3(0.0f, 2.0f, 0.0f);
ubo.view = glm::lookAt(cameraPos, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
// if the direction vector from the camera to the point being observed ends up being parallel to the UP vector
// glm::lookAt() returns a mat4 with NaNs in it. to workaround this, look for NaNs in ubo.view
int view_contains_nan = 0;
for (int col = 0; (col < 4) && !view_contains_nan; ++col) {
for (int row = 0; (row < 4) && !view_contains_nan; ++row) {
if (std::fpclassify(ubo.view[col][row]) == FP_NAN) {
view_contains_nan = 1;
}
}
}
// if we ended up with NaNs, the workaround ubo.view that seems to work depends on the sign of the camera position Y
if (view_contains_nan) {
std::cout << "view contains NaN" << std::endl;
if (cameraPos.y >= 0.0f) {
ubo.view = glm::mat4( -0.0f, -1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 0.0f, -0.0f, 0.0f,
-0.0f, -0.0f, -cameraPos.y, 1.0f);
} else {
ubo.view = glm::mat4( 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, -1.0f, 0.0f,
-1.0f, 0.0f, -0.0f, 0.0f,
-0.0f, -0.0f, cameraPos.y, 1.0f);
}
}
希望它也对你有用,不过我想如果 glm::lookAt() 可以固定为不包含 NaN 的 return 矩阵会更好。
我想为垂直观察地面的相机创建一个视图矩阵:
glm::mat4 matrix = glm::lookAt(glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
最后一个参数是全局向上向量,所以一切似乎都是正确的,但我得到了以下 matirx:
-nan -nan -0 0
-nan -nan 1 0
-nan -nan -0 0
nan nan -1 1
我想我得到 nan 是因为观察向量与向上向量平行,但是如何使用 glm::lookAt 函数构建正确的视图矩阵。
在lookAt
中不可能让观察方向和向上矢量看向同一方向。如果您想要一个沿负 y 轴观察的相机,则必须调整向上矢量,例如 [0,0,1]
。在向上向量中指定的方向控制相机如何围绕视图轴旋转。
问题出在相机的位置或向上矢量上。
您的相机向上 1 个单位 (0,1,0),向下看原点 (0,0,0)。向上向量表示相机的向上方向,而不是世界space。例如,如果您向前看,向上矢量将为 +Y。如果您向下看,头顶朝向 +X,那么向上矢量对您来说就是 +X。它必须与相机的位置矢量完全不平行。
解决方案:
- 将向上矢量更改为沿 XZ 平面的任何方向
- 或者当投影到 XZ 平面上时不是 (0,0,0) 的东西
- 移动您的相机,使其位于 Y 轴以外的任何位置
我 运行 昨天在 return 由 glm::lookAt() 编辑的矩阵中遇到了同样的 NaN 问题,并提出了我认为是解决方法的方法。对于 UP 向量是 vec3(0.0f, 1.0f, 0.0f) 的特殊问题,这似乎对我有用,这似乎是一个常见的用例。
我的 Vulkan 代码如下所示:
struct UniformBufferObject {
alignas(16) glm::mat4 model;
alignas(16) glm::mat4 view;
alignas(16) glm::mat4 proj;
};
...
UniformBufferObject ubo{};
...
glm::vec3 cameraPos = glm::vec3(0.0f, 2.0f, 0.0f);
ubo.view = glm::lookAt(cameraPos, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
// if the direction vector from the camera to the point being observed ends up being parallel to the UP vector
// glm::lookAt() returns a mat4 with NaNs in it. to workaround this, look for NaNs in ubo.view
int view_contains_nan = 0;
for (int col = 0; (col < 4) && !view_contains_nan; ++col) {
for (int row = 0; (row < 4) && !view_contains_nan; ++row) {
if (std::fpclassify(ubo.view[col][row]) == FP_NAN) {
view_contains_nan = 1;
}
}
}
// if we ended up with NaNs, the workaround ubo.view that seems to work depends on the sign of the camera position Y
if (view_contains_nan) {
std::cout << "view contains NaN" << std::endl;
if (cameraPos.y >= 0.0f) {
ubo.view = glm::mat4( -0.0f, -1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 0.0f, -0.0f, 0.0f,
-0.0f, -0.0f, -cameraPos.y, 1.0f);
} else {
ubo.view = glm::mat4( 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, -1.0f, 0.0f,
-1.0f, 0.0f, -0.0f, 0.0f,
-0.0f, -0.0f, cameraPos.y, 1.0f);
}
}
希望它也对你有用,不过我想如果 glm::lookAt() 可以固定为不包含 NaN 的 return 矩阵会更好。