参考文章:https://blog.csdn.net/ziyuanxiazai123/article/details/51586007

想写个相机就先要对MVP矩阵有一定了解,相机本质上其实就是一个view矩阵和一个projection矩阵。对相机的操作全都体现在

这两个矩阵上,projection矩阵可以通过QMatrix4x4的perspective函数得到

:projectionMatrix.perspective(viewAngle, aspect, Near, Far);

参数意义为:视角,宽高比例,近平面,远平面。

projection矩阵只需要进行一次计算,若之后又需要可以再进行更改。

相机的重点是view矩阵的计算。

此时可以使用QMatrix4x4的lookat函数进行计算。

viewMatrix.lookAt(location, location + forward, up);

其意义为:相机位置,目标位置,上矢量。

有个坑是 每次使用都要把view矩阵初始化,不然看到的内容就是模型在脸上飞来飞去。。

能显示了之后就要对相机的动态进行处理了。

作为一个fps相机,鼠标和键盘的协作是不可少的。鼠标能控制相机的朝向,也就是改变相机的forward前向量,而且由于fps是不会进行翻转(滚转角旋转)的所以up向量始终为(0,1,0)。

所以最终目的就是通过鼠标的移动计算新的forward向量并改变view矩阵。

鼠标的移动:

采用Qt的void mouseMoveEvent(QMouseEvent *event)函数可以轻松做到这一点。首先将鼠标锁在界面中心即:

QCursor::setPos(QPoint(width / 2, height / 2));

每次移动鼠标计算移动距离

 float dx = event->x() - width/2;float dy = event->y() - height/2;

在相机中设置两个数:Yaw和Pitch,分别为俯仰角和偏航角,由于fps不用滚转角,这里先不做考虑。

        camera->SetPitch(camera->GetPitch() - dy);if (camera->GetPitch() > 89.0)camera->SetPitch(89.0);if (camera->GetPitch() < -89.0)camera->SetPitch(-89.0);
 camera->SetYaw(camera->GetYaw()- dx );if (camera->GetYaw() < 0.0f)camera->SetYaw(camera->GetYaw() + 360.0f);if (camera->GetYaw() > 360.0f)camera->SetYaw(camera->GetYaw() - 360.0f);

并对Yaw和Pitch进行限制Pitch的范围是(-89,89)以防产生万向锁问题,Yaw的范围为(0,360)

每一帧相机的Yaw和Pitch角都会产生变化,再要做的就是对这两个数据进行操作了。

通过这两个数据就可以计算出forward向量了:

 forward.setX(-sin(qDegreesToRadians(yawAngle))*cos(qDegreesToRadians(pitchAngle)));forward.setY(sin(qDegreesToRadians(pitchAngle)));forward.setZ(-cos(qDegreesToRadians(yawAngle))*cos(qDegreesToRadians(pitchAngle)));forward.normalize();

qDegreesToRadians将角度转为弧度。并将向量归一化。

此时,viewMatrix.lookAt(location, location + forward, up);中的三个参数都已知晓,将产生的view矩阵传入shader

即可产生效果。最后隐藏鼠标    setMouseTracking(true) 如果觉得太快可以加入灵敏度设定改变dx,dy的大小实现转动的快慢。

鼠标搞定后是键盘。

采用void keyPressEvent(QKeyEvent *e)和void keyReleaseEvent(QKeyEvent *e)。

每次按下按键,改变相机的location,即可达成目标。

需要注意的是如果是单纯的在按下(keyPressEvent)改变相机位置,在开始按下的时候会出现一次卡顿然后才会一直移动。

这时采用一个bool数组bool keyAry[100]

按下时使对应的keyAry元素置为true,放开按键时 keyReleaseEvent中将对应元素置为false。

然后在paintGL函数中放入函数Translation即可。

void Translation(float speed)
{if (keyArr[Direction::up])location += up * speed;if (keyArr[Direction::down])location -= up * speed;if (keyArr[Direction::left])location -= side * speed;if (keyArr[Direction::right])location += side * speed;if (keyArr[Direction::forward])location += forward * speed;if (keyArr[Direction::back])location -= forward * speed;}

side变量可以通过公式求得:

 side.setX(cos(qDegreesToRadians(yawAngle)));side.setY(0);side.setZ(-sin(qDegreesToRadians(yawAngle)));side.normalize();

Qt opengl fps相机相关推荐

  1. QT + opengl 三维视图变换

    QT + Opengl 三维视图变换 原本是导师的项目,要求像paraview一样实现三维网格的可视化以及三键操作,从qt 和opengl零基础开始动手鼓捣了大半个月的才完成 QT +Opengl环境 ...

  2. linux上qt配置opengl,Ubuntu下配置Qt+OpenGL+OpenCV

    我的平台:Ubuntu 10.04+Qt+OpenGL+OpenCV OpenGL是Qt自带的,Windows下的版本OpenGL库已经随同Qt的Windows发行版一同安装,Linux版本则没有安装 ...

  3. QT+OpenGL中glTexImage2D不生效问题

    QT+opengl开发,生成texture并赋值如下 glGenTextures(1,&m_inputTexture); glBindTexture(GL_TEXTURE_2D, m_inpu ...

  4. OpenGL(十二)——Qt OpenGL绕着坐标轴旋转多边形

    OpenGL(十二)--Qt OpenGL绕着坐标轴旋转多边形 一.旋转多边形 前两篇介绍了如何绘制多边形,并且给多边形进行上色.本篇介绍如何旋转多边形. 多边形的旋转,在类中增加两个变量来控制这两个 ...

  5. Qt+大恒相机+OpenCV+MinGW界面开发

    Qt+大恒相机+OpenCV+MinGW界面开发 遇到的坑有哪些? 大恒相机接口的问题(C与C++选谁,傻傻分不清) OpenCV版本与MinGW编译平台适应性问题(编译通过,但是一运行就异常退出) ...

  6. OpenGL(十六)——Qt OpenGL融合(将两张图片叠合成一张图片)

    OpenGL(十六)--Qt OpenGL融合(将两张图片叠合成一张图片) 一.场景 在常用的项目场景中,我们经常会遇到将两个图片合在一起变成一张图片,这时候就会有前后之分,特别是两个物体合在一起的时 ...

  7. QT openGL环境光照

    先看上一篇文章:Qt Opengl 给两个立方体设置两中不同颜色 使用环境光非常的简单,我们只需要设置一个环境光强度,用这个强度值乘上光源的颜色得到环境光颜色.最后,用环境光颜色乘上物体的颜色,得到物 ...

  8. Qt OpenGL(08)通过递归细分正二十面体逼近球面

    文章目录 Qt OpenGL 使用递归细分正二十面体逼近球体 下面就是绘制的代码: Widget.cpp 顶点着色器 片段着色器 Qt OpenGL 使用递归细分正二十面体逼近球体 在上一章中,我们讨 ...

  9. OpenGL(十四)——Qt OpenGL纹理

    OpenGL(十四)--Qt OpenGL纹理 一.纹理 终于写到纹理的部分了: 纹理(Texture)的本质是一个2D图片(1D和3D),或者叫图形数据.只是在OpenGL中专业术语中称其为纹理. ...

最新文章

  1. “聚沙成塔”——用大数据思维理解生命的复杂体系,数据之眼看显微镜下的复杂生命【数据故事计划二等奖】...
  2. coco与voc相互转化
  3. jzoj3501-消息传递【换根法,树形dp】
  4. 控制台服务编写 Linux,一步步搭建ubuntu server console(控制台,字符模式)开发环境...
  5. libvirt热迁移报Connection refused错误解决办法
  6. 画面每秒传输帧数是什么意思
  7. 电脑tf卡检测不到_电脑不认TF卡,有什么方法
  8. Python+Django实现智慧校园考试比赛系统
  9. 三菱触摸屏通讯错误_一台威纶通触摸屏与多台三菱PLC通讯案例
  10. 库存管理 库存管理软件榜单 库存管理软件排名 库存管理提高效率的办法
  11. Kafka消费异常报Failing OffsetCommit request since the consumer
  12. Android java.lang.IllegalStateException: Underflow in restore - more restores than saves
  13. 音频直播,这里面到底有多少坑
  14. 物联网操作系统再思考-Hello China操作系统的运营商网络协同机制
  15. java考题_java考题 求助大神
  16. 发帖添加作者水印插件无法发帖问题-缺少GD库支持,php如何安装gd库-一颗优雅草科技伊凡
  17. linux服务脚本书写,编写一个服务脚本的示例
  18. quill——简单的富文本编辑器
  19. 计算机博弈大赛php,全国计算机博弈大赛
  20. java 10个随机数排序_java随机数排序的问题

热门文章

  1. html5 高度 满屏,HTML5 全屏特性
  2. java spel_Java spring SPEL表达式注入
  3. 基于matlab的通信系统仿真的本科论文,基于MATLAB的TDM通信系统仿真设计.docx
  4. T9键盘[用户通过数字键盘输入,手机将提供与这些数字相匹配的单词列表]
  5. 计算机少年宫活动计划,少年宫活动计划3篇
  6. 3dsmax快捷键大全
  7. Unity FairyGUI(十二)
  8. 宝塔linux面板ping网址找不到主机,云服务器安装宝塔面板后无法ping通ip地址问题的解决方法...
  9. 基于半车悬架的轴距预瞄与轴间预瞄仿真对比
  10. 找到office16\excel.exe