如何解决使用 glm 的飞行相机表现得很奇怪
我正在开发一个 Vulkan 应用程序,想要实现一个“飞行相机”,它可以在任何地方自由移动。
我在场景中间放了一个立方体,我可以四处飞行。 相机位置完美无缺,但是一旦我在立方体周围移动,旋转就会变得奇怪。 当我在立方体的另一侧时,我通过鼠标给出的向上和向下方向会反转,而当我在立方体的任一侧时,它们根本不起作用。在这两者之间的任何地方,它只会做奇怪的圈子。请注意,这只影响上下移动,而不影响左右移动。
这里是它如何寻找我的演示,我只在立方体的每一侧按这个顺序上下移动鼠标(除了在它周围移动时)我为糟糕的帧速率道歉,我不得不转换它转为 gif 并降低质量: https://imgur.com/HxknkQV
视频快速说明: 首先,虽然看起来我左右移动了鼠标而没有移动看侧面,但我没有。除了我进入位置时,我每次都只上下移动。另一件事是,虽然对于立方体的相反位置,它可能看起来旋转有效,但实际上是倒置的。
这是我的相机代码:
#pragma once
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/rotate_vector.hpp>
class Camera {
private:
glm::mat4 _model;
glm::mat4 _view;
glm::mat4 _projection;
glm::vec3 _position;
glm::vec3 _up;
glm::vec3 _moveSpeed = glm::vec3(0.08f);
float _mouseSens = 0.005f;
public:
glm::vec3 _direction;
enum MovementType { FORWARD,BACKWARD,LEFT,RIGHT,UP,DOWN };
Camera(uint32_t width,uint32_t height){
_model = glm::mat4(1.0f);
_projection = glm::perspective(glm::radians(90.0f),width / (float)height,0.01f,100.0f);
_direction = glm::vec3(-2,0);
_up = glm::vec3(0.0f,0.0f,1.0f);
_position = glm::vec3(2.0f,0.0f);
_projection[1][1] *= -1; //Because Vulkan uses different axis,hence the up Vector being different to an OpenGL application for example
}
void rotate(float amount,glm::vec3 axis){
_direction = glm::rotate(_direction,amount * _mouseSens,axis);
}
void move(MovementType movement) {
switch (movement)
{
case FORWARD:
_position += _direction * _moveSpeed;
break;
case BACKWARD:
_position -= _direction * _moveSpeed;
break;
case LEFT:
_position -= glm::normalize(glm::cross(_direction,_up)) * _moveSpeed;
break;
case RIGHT:
_position += glm::normalize(glm::cross(_direction,_up)) * _moveSpeed;
break;
case UP:
_position += _up * _moveSpeed;
break;
case DOWN:
_position -= _up * _moveSpeed;
break;
}
}
glm::mat4 getMVP() {
_view = glm::lookAt(_position,_position + _direction,_up);
return _projection * _view * _model;
}
};
我们很乐意提供任何帮助,因为我在向量和矩阵计算方面并不是那么擅长,而且真的不知道如何解决这个问题。谢谢。
解决方法
在我看来,就像您在世界空间中旋转相机一样(但我不能确定,因为调用 Camera::rotate
的代码未包含在您的问题中)。
如果我的假设是正确的,在相机空间中旋转应该可以解决问题。 IE。假设 Camera::rotate
相对于当前相机空间的轴执行旋转,您必须将其转换回世界空间,这可以通过 _view
的逆来完成:
void rotate(float amount,glm::vec3 axis){
auto directionCamSpace = glm::rotate(_direction,amount * _mouseSens,axis);
_directionWorldSpace = glm::mat3(glm::inverse(_view)) * _direction;
}
然后将 _directionWorldSpace
与 glm::lookAt
一起使用:
glm::mat4 getMVP() {
_view = glm::lookAt(_position,_position + _directionWorldSpace,_up);
return _projection * _view * _model;
}
我担心这可能还没有引导您找到问题的最终解决方案,并且会出现进一步/其他人工制品,但至少应该让您更进一步。
实现此类相机的最佳方法可能是使用四元数来跟踪相机的旋转,使用累积的四元数旋转旋转相机的坐标系,然后使用 glm::inverse
从旋转相机的坐标系。 (使用这种方法您根本不需要 glm::lookAt
。)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。