QT + Opengl 三维视图变换
原本是导师的项目,要求像paraview一样实现三维网格的可视化以及三键操作,从qt 和opengl零基础开始动手鼓捣了大半个月的才完成
QT +Opengl环境搭建
- 网上有很多教程,这里就简单介绍一下主要流程
- 在pro文件中添加QT+=opengl添加Opengl模块,这里会把gl.h和glu.h也include进来
- 添加了opengl模块以后,在ui设计界面添加openglwidget,然后在新建一个glwidget类,这个类构造函数如下:
GLWidget::GLWidget(QWidget *parent) :
QOpenGLWidget(parent)
{}
- 将这个类实例化一个对象到一个openglwidget中去,这样就实现了opengl到qt的接口。这时候重载
void resizeGL(int w, int h);
void initializeGL();
void paintGL();
这三个函数即可以在qt中使用gl和glu函数了。
三维视图转换
一般情况下使用球坐标系转换法,具体通过glulookat函数实现
鼠标滑动时间与球坐标的角度值成线性关系,所以也就不存在不同视角下对鼠标操作的敏感度差距较大的问题,但是这种算法存在的问题是不能很好的还原商业软件的三维视图操作。,每次计算的时候以cen点为中心,当发生鼠标点击事件后,计算cen与eye的角度,然后鼠标点击事件发生时,通过重计算eye与cen的夹角实现这个功能。球坐标系中,将模型置于原点,相机置于观察点,基本原则就是让φ和θ的值与鼠标横向滑动的距离与纵向滑动的距离成线性关系,这样在滑动鼠标的时候显示效果会更平滑,并且相机只会在距离模型中心点r球面上移动。需要注意的是,由于球坐标的特殊性,θ的取值范围为[-90,90],鼠标移动过小和过大也均需处理,因此处理鼠标事件的时候需要对角度做处理
/*基于球坐标的三位视角可视化控制 */
·_eye.setX(_zscale*cos(PAI*_verticalAngle/180.0)*cos(PAI*_horizonAngle/180.0)+_center.x());
_eye.setY(_zscale*sin(PAI*_verticalAngle/180.0)+_center.y());
_eye.setZ(_zscale*cos(PAI*_verticalAngle/180.0)*sin(PAI*_horizonAngle/180.0)+_center.z());//相机位置控制
gluLookAt(_eye.x(), _eye.y(), _eye.z(),
_center.x(),_center.y(),_center.z(),
0.0, 1.0, 0.0);//视角控制函数
其中verticalAngle和horizonAngle与鼠标的竖直和水平方向相对位移成正比即可实现,这个函数相当于将相机模型置于球坐标系的一个球表面,物体放在中心,其中相机模型角度与鼠标左键事件相关(转动),球半径与滚轮事件相关(放大缩小),右键与中心位置相关(平移)。
qt中,鼠标事件可用重载下列三个函数
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
实现,event->pos中有鼠标的当前点的信息,具体代码参考给出的链接中,有一个简单的三维可视化鼠标三键操作的demo。
demo在qt5.11.1msvc201764bit release中编译通过,附有exe供测试,主要包括实现了对相机模型的旋转(左键),放大缩小(滚轮),平移(右键)操作
https://download.csdn.net/download/yhf_naive/10633459