简体   繁体   English

Glm四元数查找功能

[英]Glm Quaternion lookat function

I am trying to write a lookat function that uses glm::quat to represent rotations, based of off this answer . 我正在尝试基于此答案编写使用glm :: quat表示旋转的lookat函数。 I am running into trouble getting a correct angle however. 但是,我在获取正确角度时遇到了麻烦。 This is my lookat function: 这是我的查阅功能:

void Camera::LookAt(float x, float y, float z) {
    glm::vec3 lookVector = glm::vec3(x, y, z);
    assert(lookVector != position);

    glm::vec3 direction = glm::normalize(lookVector-position);
    float dot = glm::dot(glm::vec3(0, 0, -1), direction);
    if (fabs(dot - (-1.0f)) < 0.000001f)
        rotation = glm::quat(RadiansToDegrees(M_PI), 0.0f, 1.0f, 0.0f);
    if (fabs(dot - (1.0f)) < 0.000001f)
        rotation = glm::quat();

    float angle = RadiansToDegrees(acosf(dot));

    glm::vec3 cross = (glm::cross(glm::vec3(0, 0, -1), direction));
    rotation = glm::normalize(glm::angleAxis(angle, cross));

    std::cout << glm::eulerAngles(rotation).x  << " " << glm::eulerAngles(rotation).y << " " << glm::eulerAngles(rotation).z << "\n";
}

When I call LookAt(0.0f, 0.0f, 0.0f) when my camera is at (0.0f, 0.0f, -10.0f), this outputs a correct rotation of 0,0,0. 当我的相机位于(0.0f,0.0f,-10.0f)时调用LookAt(0.0f,0.0f,0.0f)时,这将输出正确的旋转0,0,0。 However if I translate my camera to (0.0f, -0.01f, -10.0f) or more I get a rotation of about 124,0,0. 但是,如果将摄影机平移为(0.0f,-0.01f,-10.0f)或更大,则旋转量约为124,0,0。 This goes down if I continue to translate y by -0.01f. 如果我继续将y转换-0.01f,则此值会下降。 If I do not normalize the quaternion I do not get this problem. 如果我不对四元数进行归一化,那么我不会遇到这个问题。 The rotation is still 124 about the x axis, but the appearance is fine. 围绕x轴的旋转仍然是124,但是外观很好。 If however I normalize the quaternion later it once again appears to rotate to about 124. I can not normalize cross , because doing so throws an assert. 但是,如果稍后我将四元数归一化,它似乎又会旋转到约124。我无法将cross归一化,因为这样做会引发断言。 What would cause me to get euler angles of 124 about x from my lookat function, and how can I fix it? 是什么导致我从我的查阅函数获得关于x的124欧拉角,以及如何解决该问题?

Since version 0.9.9.0 there is a function in <glm/gtx/quaternion.hpp> doing mostly what you want: 从0.9.9.0版开始, <glm/gtx/quaternion.hpp>了一个函数,主要用于执行您想要的操作:

template<typename T, qualifier Q>
tquat<T, Q> quatLookAt(vec<3, T, Q> const& direction, vec<3, T, Q> const& up);

It was added by this pull request and has been merged into master July 24, 2017. 此请求请求已将其添加,并已合并到2017年7月24日的主服务器中。

But : 但是

  1. direction has to be a normalized vector! 方向必须是归一化向量!
  2. direction can't be parallel to up! 方向不能平行!

So you may want to write a safer wrapper around the function: 因此,您可能想为该函数编写一个更安全的包装器:

glm::quat safeQuatLookAt(
    glm::vec3 const& lookFrom,
    glm::vec3 const& lookTo,
    glm::vec3 const& up,
    glm::vec3 const& alternativeUp)
{
    glm::vec3  direction       = lookTo - lookFrom;
    float      directionLength = glm::length(direction);

    // Check if the direction is valid; Also deals with NaN
    if(!(directionLength > 0.0001))
        return glm::quat(1, 0, 0, 0); // Just return identity

    // Normalize direction
    direction /= directionLength;

    // Is the normal up (nearly) parallel to direction?
    if(glm::abs(glm::dot(direction, up)) > .9999f) {
        // Use alternative up
        return glm::quatLookAt(direction, alternativeUp);
    }
    else {
        return glm::quatLookAt(direction, up);
    }
}

I have fixed the problem with the following code: 我已使用以下代码解决了该问题:

void Camera::LookAt(float x, float y, float z) {
    glm::vec3 lookVector = glm::vec3(x, y, z);
    assert(lookVector != position);

    glm::vec3 direction = glm::normalize(lookVector-position);
    float dot = glm::dot(glm::vec3(0, 0, 1), direction);
    if (fabs(dot - (-1.0f)) < 0.000001f) {
        rotation = glm::angleAxis(RadiansToDegrees(M_PI), glm::vec3(0, 1, 0));
        return;
    }
    else if (fabs(dot - (1.0f)) < 0.000001f) {
        rotation = glm::quat();
        return;
    }

    float angle = -RadiansToDegrees(acosf(dot));

    glm::vec3 cross = glm::normalize(glm::cross(glm::vec3(0, 0, 1), direction));
    rotation = glm::normalize(glm::angleAxis(angle, cross));
}

I do not however understand the necessity of the negative on angle . 但是,我不理解否定angle的必要性。 It fixed the last of my problems, and an explanation of the math of why would be helpful. 它解决了我的最后一个问题,并解释了为什么会有所帮助的数学方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM