当 z <= 0 时 glm::lookAt 垂直相机翻转

Posted

技术标签:

【中文标题】当 z <= 0 时 glm::lookAt 垂直相机翻转【英文标题】:glm::lookAt vertical camera flips when z <= 0 【发布时间】:2013-07-23 09:53:01 【问题描述】:

我正在开发 FPS 风格的相机,以使用 OpenGL 在我的 3D 场景中飞行。我将 GLM 用于数学,并使用鼠标移动在 x 轴和 y 轴上使用 glm::rotate 计算方向向量。我有一个静态的向上向量,因为我可以在水平轴上扫射并且不需要任何滚动。

但是,当我朝负 z 方向前进并最终到达场景的中心点 (z=0) 时,垂直相机会翻转(y 方向)。向下移动鼠标现在将导致向上运动。方向向量的计算方式应该如此,所以我猜这与 glm::lookAt 如何计算其视图矩阵有关?

以下是相关代码:

// Player movement
glm::vec3 position(0.0f, 0.0f, 5.0f);
glm::vec3 direction(0.0f, 0.0f, -1.0f);
glm::vec3 up(0.0f, 1.0f, 0.0f);
float speed = 0.05f;
bool warped = false;
...

void render()

    ...
    view = glm::lookAt(position, position + direction, up); 
    glUniformMatrix4fv(glGetUniformLocation(basicShader.shaderProgram, "view"), 1, GL_FALSE, glm::value_ptr(view));
    ...    



void handleKeyboard()

    float speed = 0.05f;
    if(keys['w'])
        position += speed * direction;
    if(keys['s'])
        position -= speed * direction;
    if(keys['a'])
        position -= speed * glm::cross(direction, up);
    if(keys['d'])
        position += speed * glm::cross(direction, up); 
    if(keys['q'])
        exit(1);


// Set with following callbacks:
// glutMotionFunc(mouse);
// glutPassiveMotionFunc(mouse);
void mouse(int x, int y)
  
    if(!warped)
    
        float mouseSensitivity = 15.0f;

        float horizontal = (width / 2) - x;
        float vertical = (height / 2) - y;

        horizontal /= mouseSensitivity;
        vertical /= mouseSensitivity;

        direction = glm::rotate(direction, horizontal, glm::vec3(0.0f, 1.0f, 0.0f));
        direction = glm::rotate(direction, vertical, glm::vec3(1.0f, 0.0f, 0.0f));

        warped = true;
        glutWarpPointer((width / 2), (height / 2));
    
    else
        warped = false;

【问题讨论】:

【参考方案1】:

我不完全确定问题出在哪里,但是当我将 LookAt 用于 FPS cam 时,我还包含了一个前向单位向量。

例如(从我拥有的一些代码中复制相关段)- 使用四元数(方向),但我确信矩阵将具有相同的结果)

static glm::vec3 defaultUpVector()  return glm::vec3(0, 1, 0); 
static glm::vec3 defaultForwardVector()  return glm::vec3(0, 0, -1); 

pUpVector = defaultUpVector() * orientation;
pLookAt = position + (defaultForwardVector() * orientation);
pView = glm::lookAt(position, pLookAt, pUpVector);

upvector和lookat都是vec3,view是mat4

希望这会有所帮助。

编辑:我注意到你正在使用一个方向,所以我可能会看看你在哪里使用旋转。

这将为无滚动的 FPS cam 设置 quat

pLocalOrientation = 
    glm::angleAxis(pLocalEularAngles.x, glm::vec3(1, 0, 0)) *
    glm::angleAxis(pLocalEularAngles.y, glm::vec3(0, 1, 0));

pLocalOrientation == 方向(例如)

如果你决定使用quats。

【讨论】:

我喜欢这个想法,并试图看看前向向量是否能解决我的问题,但没有不幸的是,据我所知,我的旋转没问题。除了翻转之外,一切都完美无缺。即使在翻转之后,方向向量也是相同的。我还没有开始研究四元数,所以现在不行:) 我推荐 quats 用于这些目的。 (pLocalOrientation = glm::quat(glm::radians(pRotationIncr)) * pLocalOrientation;) - 如果你需要它会做 6dof。 pRotationIncr = 在框架中旋转的量 (vec3)。 我知道,据我所知,四元数似乎消除了矩阵和 eular 角度的所有问题,并且代码更少(AFAIK),我最终会开始学习这些,但目前我学习 OpenGL,我会一步一步地学习 :) Quats 是为了以后 ;) 并不是不可能得到一个像样的 FPS 相机,我只是有一个奇怪的错误 :) 如果您只使用两个轴,那么您是否尝试过使用正弦和余弦方法?它可以帮助您在不依赖 glm 数学的情况下了解正在发生的事情。这并不难,而且我认为 Nehe 有一个旧教程。 是的,我知道正弦和余弦方法:)

以上是关于当 z <= 0 时 glm::lookAt 垂直相机翻转的主要内容,如果未能解决你的问题,请参考以下文章

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

相机 旋转

相机 旋转

相机 旋转

相机 旋转

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