如何为 LookAt 转换获得正确的向上向量?

Posted

技术标签:

【中文标题】如何为 LookAt 转换获得正确的向上向量?【英文标题】:How to get right Up vector for LookAt transformation? 【发布时间】:2017-11-08 19:20:30 【问题描述】:

我确实了解 glm::LookAt 的工作原理以及它需要哪些参数。 我不明白如何提供正确的向上向量。

例如,这个:

glm::mat4x4 transformation = glm::lookAt(cameraPosition, targetPosition, glm::vec3(0.f, 1.f, 0.f));

如果我想让相机直下观看:

 mat4x4 transformation = glm::lookAt(vec3(0.f, 1.f, 0.f), vec3(0.f, 0.f, 0.f), vec3(0.f, 1.f, 0.f));

这行不通。矩阵将包含 NaNs(非数字)值! 那么如何为 Up 向量获取正确的值呢?

【问题讨论】:

【参考方案1】:

你得到 NaN 的原因是 除以零


引用this post:

向上向量基本上是定义世界“向上”的向量 方向。在几乎所有正常情况下,这将是向量 (0, 1, 0)即朝向正Y。眼睛是相机的位置 视点,中心是您正在查看的位置(位置)。

设置如何工作?下图说明:

u 是向上向量(第三个参数) p 是目标位置(第二个参数) c 是相机位置(第一个参数) d 是方向向量 (= p - c) r 是正确的向量

lookAt返回视图矩阵,其格式如下:

(“帽子”的意思是 标准化 - 长度为 1)

由于您只提供向上向量和(实际上,因为d = p - c)方向向量,我们必须使用叉积计算正确的向量:

(注意以上是归一化之前)


现在说明为什么您的示例无法按预期工作。论据如下:

u = (0, 1, 0) p = (0, 0, 0) c = (0, 1, 0) 因此d = (0, -1, 0)

以上给出r = d * u = (0, 0, 0)!这是因为方向和上向量是反平行的,而它们之间应该有一个角度才能使例程工作(理想情况下为 90 度)。当r 被归一化时,会被零除,因此矩阵的整个第一行都应该被 NaN 占据。

(作为一种可能的解决方法,请改用up = (0, 0, 1)。)

【讨论】:

非常感谢您部署的答案!但我正在寻找的是一种在任何情况下都能获得正确向上矢量的方法,如何自动确定相机的正确向上方向?也许有一种方法可以让它与 glm::vec3(1, 0, 0) (正确的方向)相乘?或者我应该使用四元数吗?如果通常我的相机位于 (0, 0, 0) 向前 (0, 0, 1) 并且我将相机放置在 cameraPosition 的某个位置并试图让它看起来到 targetPosition i> 如何获得不围绕相机 Z 轴旋转的旋转以转向目标? @overwriter 当然,您可以从 right 计算 up。但这提出了如何获得正确的问题。一般来说,没有自动的方法,因为有无限多的解决方案。没有什么可以使一种解决方案比另一种更好。因此,最终程序员或场景设计师必须做出决定。 这也让我感到困惑。我最终只是检查了它的特殊情况,并使其成为有条件的。感觉真的很不雅,像个 hack,但它适用于我的函数在实践中的使用方式。

以上是关于如何为 LookAt 转换获得正确的向上向量?的主要内容,如果未能解决你的问题,请参考以下文章

如何缩放使用 glm::lookat() 获得的矩阵?

如何为 IE11 转换不当行为正确应用 css hack

如何为 std::vector 复制或使用隐式缩小转换禁用 Visual Studio 警告 C4244

向上转换 const 向量

glm lookAt 和矩阵变换产生奇怪的行为

为啥我们需要 dequeueReusableCell func 获得的向上转换单元格?