图形渲染+事件处理最终版
基于之前做的项目图形移动处理-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);//初始化为000m_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);
我这里就把他后移了三个单位,十分简陋,因为设置了和没设置没区别,就懒得设置他了,我这是不是有些敷衍哈哈。
就这样,程序大功告成,展示最终效果