glm::quatLookAt 返回一个 NaN 四元数

Posted

技术标签:

【中文标题】glm::quatLookAt 返回一个 NaN 四元数【英文标题】:glm::quatLookAt Return a NaN quaternion [closed] 【发布时间】:2020-09-16 16:43:54 【问题描述】:

我有一个 LookAt 函数(取自 here),它计算一个四元数:

Camera& Camera::LookAt(const glm::vec3& lookat)noexcept
   glm::vec3  direction = lookat - transform.GetPosition();
   float directionLength = glm::length(direction);

   if(!(directionLength > 0.0001)) // Check if the direction is valid; Also deals with NaN
       transform.SetRotation(glm::quat(1, 0, 0, 0));
       return *this;
   
   direction /= directionLength; // Normalize direction

   if(glm::abs(glm::dot(direction, transform.GetWorldUp())) > .9999f) 
       transform.SetRotation(glm::inverse(glm::quatLookAt(direction, transform.GetUp())));// Use relative up
    else 
       transform.SetRotation(glm::inverse(glm::quatLookAt(direction, transform.GetWorldUp())));
   
   return *this;

由于某种原因,当相机的第一个位置是 0 0 20(四元数为 1 0 0 0)并且我将其更改为 0 20 0 并调用 LookAt() 时,我的四元数最终只有 NaN。如果相机第一个位置不是 0 0 20(或 20 0 0),它可以正常工作。

这是我的控制台(我在 LookAt 函数和转换之前添加了几个 std::cout):

我不知道发生了什么,有人可以帮助我吗?

编辑:

这是我写的新函数,它检查两个方向是否平行。如果是,它会稍微改变方向以防止平行:

Camera& Camera::LookAt(const glm::vec3& lookat)noexcept
    glm::vec3 direction = glm::normalize( lookat - transform.GetPosition());
    if(!(glm::length(direction) > 0.0001)) // Check if the direction is valid; Also deals with NaN
        transform.SetRotation(glm::quat(1, 0, 0, 0));
        return *this;
    
    //Check if We must use relative Up
    glm::vec3 upToUse = transform.GetWorldUp();
    if(glm::abs(glm::dot(direction, transform.GetWorldUp())) > .9999f) upToUse = transform.GetUp();
    //Check if parallel
    if(glm::vec3(0.0f) == glm::cross(transform.GetUp(),direction) ) direction = glm::normalize(lookat - (transform.GetPosition() + glm::vec3(0.001f,0.0f,0.001f))); //Change position and recalculate direction
    //Calcul new quaternion
    transform.SetRotation(glm::inverse(glm::quatLookAt(direction, upToUse)));
    return *this;
 

【问题讨论】:

什么是向上向量?你没有打印出来 @user253751 在 LookAt 调用之前:0 1 0 @Rabbid76 实际上第二个是“向上向量”,而不是旋转轴。 【参考方案1】:

您要求 GLM 创建一个四元数,该四元数将使 Z 方向 (0, -1, 0)(方向向量)和 Y 方向也 (0, 1, 0)(向上向量)。

这是不可能的。任何旋转都不会使 Y 轴和 Z 轴指向彼此相反的方向。您需要指定一个不同的向上向量。

请注意,向上向量不必垂直于方向向量,因为 GLM 会忽略不垂直的部分。但它必须至少有一点垂直。

【讨论】:

我明白了,谢谢!

以上是关于glm::quatLookAt 返回一个 NaN 四元数的主要内容,如果未能解决你的问题,请参考以下文章

NaN 是不是等于 NaN?

无效的 LngLat 对象:(NaN, NaN) - getElementById 不返回值

为啥 Math.round() 为 NaN 参数返回 0?

为啥 [NaN].includes(NaN) 在 JavaScript 中返回 true?

为啥“valueAsNumber”返回 NaN 作为值?

如果参数是数字,为啥函数返回 NaN?