使用 glm 的飞行相机表现得很奇怪

如何解决使用 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;
}

然后将 _directionWorldSpaceglm::lookAt 一起使用:

glm::mat4 getMVP() {
    _view = glm::lookAt(_position,_position + _directionWorldSpace,_up);
    return _projection * _view * _model;
}

我担心这可能还没有引导您找到问题的最终解决方案,并且会出现进一步/其他人工制品,但至少应该让您更进一步。

实现此类相机的最佳方法可能是使用四元数来跟踪相机的旋转,使用累积的四元数旋转旋转相机的坐标系,然后使用 glm::inverse 从旋转相机的坐标系。 (使用这种方法您根本不需要 glm::lookAt。)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-