前言
近日,需要实现鼠标拖动模型的功能,没有在网上找到合适的源代码,就算要也是要收钱,不想承担风险浪费钱财下载下来一堆废代码,故自己尝试实现这一功能,源代码在文章里,喜欢的点个赞就行,感谢~
实现思路
本文需要一定OpenGL基础,想学习OpenGL的同学可以参考我之前的博客。
OpenGL中有变换矩阵可以实现模型绕某个轴进行旋转,这是基础。
具体步骤:
- 获取到鼠标点击控件的坐标,设定在区域内的点击事件才有效,将点击的坐标存下来,这里涉及到将QT界面的坐标转化为OpenGL的坐标。
void OpenGLWidget::mousePressEvent(QMouseEvent *event)
{//单击
QPoint p_ab = event->pos();
if (p_ab.x()<0 || p_ab.x()>window_size.height() || p_ab.y()<0 || p_ab.y()>window_size.width())
return;
// 如果是鼠标左键按下
if (event->button() == Qt::LeftButton){
projection_use = projection_save;
setPressPosition(p_ab);
}
}
void OpenGLWidget::setPressPosition(QPoint p_ab)
{
translate_point(p_ab);
press_position = p_ab;
}
void OpenGLWidget::translate_point(QPoint &p_ab)
{
int x = p_ab.x() - window_size.width() / 2;
int y = -(p_ab.y() - window_size.width() / 2);
p_ab.setX(x);
p_ab.setY(y);
}
- 设置变换矩阵
- 先计算鼠标移动的向量(将现在的坐标和之前按下鼠标存下来的坐标相减)QPoint sub_point = p_ab - press_position; ,向量的方向是鼠标移动的方向,向量的长度是移动的长度。
- 再绕垂直于移动向量的轴旋转,旋转轴向量求法为假设轴向量为(x,y),(x,y)·(sub_point.x(),sub_point.y())=0,即可求得垂直于移动向量的旋转轴向量x/y=(–sub_point.y())/sub_point.x();。
- 再以移动向量的长度为角度,垂直方向的向量为轴,就可以旋转整个模型了projection.rotate(angle_now, -sub_point.y(), sub_point.x(), 0.0);。
void OpenGLWidget::mouseMoveEvent(QMouseEvent *event)
{
QPoint p_ab = event->pos();
translate_point(p_ab);
QPoint sub_point = p_ab - press_position;
if (event->buttons() & Qt::LeftButton){
projection.setToIdentity();
float rate=(float)window_size.height()/(float)window_size.width();
projection.ortho(-1.0, 1.0, -1.0*rate, 1.0*rate, 1.0f, 100.0f);
// 增加了模型矩阵,需要做一定偏移量,保证物体刚开始渲染出来时可以被看到!
projection.translate(0.0f, 0.0f, -2.0f);
GLfloat angle_now = qSqrt(qPow(sub_point.x(), 2) + qPow(sub_point.y(), 2)) / 5;
projection.rotate(angle_now, -sub_point.y(), sub_point.x(), 0.0);
projection = projection*projection_use;
projection_save.setToIdentity();
projection_save.rotate(angle_now, -sub_point.y(), sub_point.x(), 0.0);
projection_save = projection_save*projection_use;
}
}
TIPS:
每次旋转最后(即将鼠标松开的时候)将变换矩阵存下来,下次在最开始旋转的时候旋转一个上次最后的旋转角度,以达到连续旋转的效果。