图形渲染+事件处理最终版

基于之前做的项目图形移动处理-CSDN博客添加了相机,透视投影,鼠标控制图形旋转。虽然个人感觉这个项目用的是一个二维的三角形,给他加透视投影和相机意义不大,因为透视投影是近大远小,我这个程序设置了放大缩小的限制,说实话,理论上加没加看不出去别来,只是为了实践一下,并且是通过鼠标让三角形旋转,也不需要再设置相机绕着三角形看不同角度,视觉上是一样的。后面改用三维度图形才会有区别。这里就讲讲相对于之前的项目新添加到功能吧。

三角形旋转事件

我设计的这个是根据鼠标横向/纵向移动,使得三角形绕y轴/x轴旋转。

添加的成员变量
复制代码
//旋转参数
    QVector3D m_rotationangles;//三维向量,存放x,y,z轴旋转角度
    bool m_isrotating;
    QPoint m_lastmousepos;

|------------------|----------------------------|
| m_rotationangles | 是一个三维向量,里面存放着绕x,y,z轴旋转的角度。 |
| m_isrotating | 旋转状态 |
| m_lastmousepos | 记录上一次鼠标停留的坐标 |

在构造函数中初始化m_rotationangles为一个{0,0,0}的向量矩阵,m_isrotating为false

复制代码
myWediget::myWediget(QWidget *parent) : QOpenGLWidget(parent) {
    setFocusPolicy(Qt::StrongFocus);
    m_rotationangles=QVector3D(0,0,0);//初始化为000
    m_isrotating=false;//初始化旋转状态
}
鼠标事件加入

我们设计他的逻辑是鼠标左键按下以后,m_lastmousepos会记录鼠标的当前位置,然后鼠标拖动,用现在鼠标的位置-上次鼠标的位置得到的是一个移动路径的向量,注意这里操作角度用的数据都是向量,然后更新旋转矩阵{x,y,z},绕x轴正向旋转就是m_rotationangles.x()+delta.y()*0.5f,为什么加的是delta的y,可以试着想一下,想让三角形绕x轴旋转不就是用鼠标向上向下移动。

复制代码
//鼠标按下事件
void myWediget::mousePressEvent(QMouseEvent *event)
{
    if(event->button()==Qt::LeftButton){
        m_isrotating=true;//开始旋转
        m_lastmousepos=event->pos();//获取鼠标位置
        event->accept();
    }
}

//鼠标松开事件
void myWediget::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button()==Qt::LeftButton){
        m_isrotating=false;
        event->accept();
    }
}

//鼠标移动事件
void myWediget::mouseMoveEvent(QMouseEvent *event)
{
    if(m_isrotating){
        QPoint delta=event->pos()-m_lastmousepos;
        m_rotationangles.setX(m_rotationangles.x()+delta.y()*0.5f);//绕x轴旋转
        m_rotationangles.setY(m_rotationangles.y()+delta.x()*0.5f);//绕y轴旋转
        m_lastmousepos=event->pos();
        update();
        event->accept();
    }
}

把旋转矩阵传入绘制函数逐帧绘制,在原有基础上加几句就行了

复制代码
transform.rotate(m_rotationangles.x(),1,0,0);
transform.rotate(m_rotationangles.y(),0,1,0);
transform.rotate(m_rotationangles.z(),0,0,1);

前面第一个参数是旋转矩阵的对应轴的参数,后面是要绕哪个轴旋转就把他设置为1,到这里功能就完成了,为啥没设置shader,我之前的项目中transform就是专门用来处理三角形运动的uniform,之前是只有移动和缩放,缩放建议最后处理,不然有些问题。

透视投影和相机

另外两个带一嘴吧,透视投影是近大远小的效果,绘画让三位图形比较立体

复制代码
//设置透视投影
     QMatrix4x4 projection;
     projection.perspective(45.0f,(float)w/h,0.1,100.0f);
     sdprogram.bind();
     sdprogram.setUniformValue("projection",projection);
     sdprogram.release();

projection.perspective(45.0f,(float)w/h,0.1,100.0f);第一个参数是视角,可以理解为你眼睛张多大,第二个参数就是宽高比,推荐和屏幕或者视口一致,第三个最近离你多近,超过了就看不见了,第四个就是最远离你有多远,超出了就看不见了,就是模拟你眼睛。

再就是相机,相机 是有一个自己的坐标系的,镜头指向的方向是自己坐标系z轴的正方向

复制代码
// 视图矩阵(相机后移3单位)
    QMatrix4x4 view;
    view.translate(0, 0, -3.0f);

我这里就把他后移了三个单位,十分简陋,因为设置了和没设置没区别,就懒得设置他了,我这是不是有些敷衍哈哈。

就这样,程序大功告成,展示最终效果

相关推荐
斗转星移7726 分钟前
MFC中使用CRichEditCtrl控件让文本框中的内容部分加粗
c++·mfc·cricheditctrl·richedit2
景彡先生1 小时前
C++ 性能分析工具:Valgrind 与 perf
开发语言·c++
范纹杉想快点毕业2 小时前
解析Qt文件保存功能实现
java·开发语言·c++·算法·命令模式
C++ 老炮儿的技术栈2 小时前
C++实现手写strlen函数
大数据·c语言·c++·编辑器
2301_799084673 小时前
Codeforces Round 1032 (Div. 3)
数据结构·c++·算法
岁忧3 小时前
(LeetCode 每日一题) 2016. 增量元素之间的最大差值 (数组)
java·c++·算法·leetcode·职场和发展·go
AI+程序员在路上4 小时前
ABI与API定义及区别
c语言·开发语言·c++
charlie1145141914 小时前
从C++编程入手设计模式——装饰器模式
c++·设计模式·装饰器模式
不太聪明的样子6 小时前
c++ 项目使用 prometheus + grafana 进行实时监控
c++·grafana·prometheus
滴滴滴嘟嘟嘟.6 小时前
FreeRTOS 任务管理学习笔记
c++·嵌入式硬件·freertos