c++ QT opengl鼠标控制平移、缩放、绕点旋转

目的:实现鼠标控制正方形的平移、缩放、以及围绕自身某个点旋转。

要求:

  1. 坐标系固定在左下角
  2. 坐标系和正方形一起旋转,但不平移与缩放
  3. 鼠标左键平移正方形,右键旋转,滚轮缩放(放大与缩小)

步骤

  1. 编写绘制正方形与坐标系函数
  2. 在OpenGL窗口界面绘制
  3. 实现鼠标左键平移移动,右键旋转,滚轮缩放(放大与缩小)
  4. 设置正方形的旋转点,以及坐标系位置
  5. 将对应的鼠标事件应用到正方形与坐标系

实现:

  • 步骤1:编写绘制正方形与坐标系函数(比较简单,就不贴代码了)
	drawObjects();
	drawaxis();
  • 步骤2:在OpenGL窗口界面绘制
  • 步骤5:将对应的鼠标事件应用到正方形与坐标系

void paintGL();
绘制OpenGL窗口界面。在这里绘制图形,并对图形设置了不同的变换。

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    int renderMode;
    glGetIntegerv(GL_RENDER_MODE, &renderMode);

    if (renderMode != GL_SELECT) {
        // Matrix setting
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        const float aspect = static_cast<float>(width()) / height();
        gluPerspective(45.0, aspect, 1.0, 1000.0);
    }
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

    glPushMatrix();
    glMultMatrixf(m_transform.constData());//对drawObjects()的图形进行平移,旋转
    glScalef(zscale,zscale,zscale);//缩放
    drawObjects();
    glPopMatrix();

    glPushMatrix();
    glTranslatef(-4, -3, 0);
    glMultMatrixf(axis_transform.constData());//对drawaxis()的图形进行旋转
    drawaxis();
    glPopMatrix();
  • 步骤3:设置鼠标左键平移移动,右键旋转

mouseMoveEvent(QMouseEvent* ev);

    int dx = ev->x() - m_lastPos.x();
    int dy = ev->y() - m_lastPos.y();

    if(ev->buttons() & Qt::LeftButton)
    {
        translate(dx, dy);
    }
    else if(ev->buttons() & Qt::RightButton)
    {
        objects_rotate(dx, dy);
        axis_rotate(dx, dy);
    }
    m_lastPos = ev->pos();
    update();
  • 步骤3:正方形的平移移动
    translate(int dx, int dy);
	m_translation.setX(m_translation.x() + dx * 0.01);
    m_translation.setY(m_translation.y() - dy * 0.01);
    m_transform.setToIdentity();                       //将变换矩阵重置为单位矩阵
    m_transform.translate(m_translation);              //平移到正确的位置
    m_transform.rotate(QQuaternion::fromAxisAndAngle(1, 0, 0, m_rotation.x()/* + 1*/));//将旋转状态应用到平移中
    m_transform.rotate(QQuaternion::fromAxisAndAngle(0, 1, 0, m_rotation.y()/* + 1*/));
  • 步骤3:坐标系的旋转
    axis_rotate(int dx, int dy);
// 四元数: new_rotation = q * m_rotation * q逆          // q = xRot * yRot * zRot, 即 rotate()的参数
    axis_rotation.setX(axis_rotation.x() - dy);
    axis_rotation.setY(axis_rotation.y() - dx);
    QQuaternion xRot = QQuaternion::fromAxisAndAngle(1, 0, 0, axis_rotation.x());//绕(0,0,0)点与(1,0,0)点连线,即x轴,旋转角度m_rotation.x()
    QQuaternion yRot = QQuaternion::fromAxisAndAngle(0, 1, 0, axis_rotation.y());

    axis_transform.setToIdentity();
    axis_transform.rotate(xRot * yRot);
  • 步骤3:正方形的旋转
    objects_rotate(int dx, int dy);
	m_rotation.setX(m_rotation.x() - dy);
    m_rotation.setY(m_rotation.y() - dx);
    QQuaternion xRot = QQuaternion::fromAxisAndAngle(1, 0, 0, m_rotation.x());//绕(0,0,0)点与(1,0,0)点连线,即x轴,旋转角度m_rotation.x()
    QQuaternion yRot = QQuaternion::fromAxisAndAngle(0, 1, 0, m_rotation.y());
    m_transform.setToIdentity();
    m_transform.translate(m_translation); //将平移状态应用到旋转
    m_transform.rotate(xRot * yRot);//四元数相乘,表示两次旋转
  • 步骤3:正方形的滚轮缩放(放大与缩小)
    wheelEvent(QWheelEvent *ev);
	int delta = ev->delta();  // positive when wheel up, delta +/- 120 when wheel +/- 1
    if(zscale-delta*2.0*1e-3>0)
        zscale += delta*2.0*1e-3;
    update();
  • 步骤4:设置正方形的旋转点,以及坐标系位置
    qt opengl中想要绕着某个点旋转,主要思维是将图形平移到该点位置,进行旋转操作后,再对图形做逆平移
    //*******设置坐标轴的旋转中心********
    float centre_x, centre_y;
    centre_x = -4;
    centre_y = -3;
    axis_translation.setX(centre_x);
    axis_translation.setY(centre_y);
    //******设置坐标轴的旋转中心*********
    axis_transform.translate(axis_translation);//平移到centre点的位置
    
    axis_transform.rotate(xRot * yRot);//旋转
    
    axis_translation.setX(-centre_x);
    axis_translation.setY(-centre_y);
    axis_transform.translate(axis_translation);//逆平移

在最近研究这个问题的过程中,发现如果同时对图形做了平移与旋转,用上述方法难点在于对于旋转点的世界坐标的获取。目前只学习了将屏幕坐标转换为世界坐标,但是对于追踪某一点的世界坐标还有待学习(有懂的大佬希望可以教教我qwq)。然而眼前的问题还是要尽快解决的,后来发现了下面的方法。

	glTranslatef(1, 1, 0);

没错,就是平移!其实也就是将正方形想要围绕旋转的点平移到原点(0,0)的位置。
我的正方形边长为2,所以这个代码意思是将正方形向右上方平移(二维平面),结果就是正方形左下角到了原点的位置。也就是我的正方形设置是围绕左下角旋转,在一系列平移,缩放后,可以一直围绕左下角旋转。

效果展示

展示1
展示2

题外话

  1. 对于上图坐标系显示文字的绘制办法下次记录
  2. 鼠标点击,选择拾取glSelectBuffer整理之后再记录
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: Qt是一个跨平台的应用程序开发框架,其中包括了OpenGL的相关功能。在Qt中使用OpenGL可以进行图形绘制、图像处理和3D渲染等操作。 频谱是指信号在频域中的特征表现,包括信号的频率和幅度信息。在图像处理中,频谱可以用来表示图像中不同频率的成分。在Qt中使用OpenGL可以实现频谱的显示和分析。 要实现频谱的显示,首先需要将信号转化为频域表示。可以使用快速傅里叶变换(FFT)算法将信号从时域转换为频域。Qt提供了相关的库函数,可以方便地进行FFT计算。 处理完FFT后,得到的频谱数据可以通过OpenGL进行可视化。在Qt中,可以使用OpenGL的绘制函数来绘制频谱图形。可以根据频率和幅度的信息,将频谱数据表示为柱状图、曲线图或者其他形式的图形。 另外,在频谱分析中还可以进行一些进一步的处理。比如,可以对频谱数据进行平滑处理、滤波操作或者进行谱峰检测等。这些处理可以增强频谱的特征表示,使得频谱图更加清晰和易于分析。 总之,QtOpenGL结合使用可以实现频谱的显示和分析。通过FFT计算和OpenGL的绘制功能,可以方便地处理频谱数据,并进行可视化展示。这对于音频、图像处理等领域的应用具有重要意义。 ### 回答2: Qt是一个跨平台的C++应用程序开发框架,而OpenGL是一种图形编程接口,用于在计算机上生成和渲染2D、3D图形。频谱是指信号在不同频率上的能量分布情况。 在Qt中使用OpenGL可以实现对图形的高效渲染和处理。对于频谱,可以利用QtOpenGL模块绘制出频谱图。首先,需要获取音频信号的频率数据。可以使用Qt提供的音频处理库进行采样和变换,得到频谱数据。然后,利用OpenGL的绘图功能,在Qt的窗口上绘制出频谱图。 绘制频谱图的过程可以分为以下几步:首先,创建一个QtOpenGL窗口,设置好窗口的大小和背景颜色。然后,将获取到的频谱数据通过OpenGL的API绘制到窗口上。可以使用点、线或者面片的方式来表示频谱图。绘制完成后,可以对频谱图进行一些交互操作,比如缩放平移或者旋转。 使用QtOpenGL进行频谱绘制的好处是,可以充分利用OpenGL的硬件加速功能,提升绘图的性能和效率。同时,Qt提供的丰富的界面控件和事件处理机制可以方便地与OpenGL进行交互,并添加各种用户交互功能。 总结来说,Qt结合OpenGL可以方便地实现频谱的绘制和处理。通过Qt的音频处理库获取到频谱数据后,利用OpenGL的绘图功能将频谱图绘制到窗口上,同时可以进行交互操作。这样可以得到一个高性能、交互丰富的频谱显示界面。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值