OpenGL模型控制(旋转、平移)

news/2025/3/12 12:59:55/

1.效果图

2.平移

首先做一个鼠标双击事件,表示平移模型对象,当然,我们需要遍历当前哪个模型对象被选中,才能进行该对象的平移操作。

void AXBOpemglWidget::mouseDoubleClickEvent(QMouseEvent *event)
{Q_UNUSED(event);if(m_modelMoving){//再次双击取消移动m_modelMoving=false;}elseforeach(auto modelInfo,m_Models){//双击启动移动if(modelInfo.isSelected==true)m_modelMoving=true;qDebug()<<modelInfo.name<<modelInfo.isSelected;}
}

开启平移后,重写鼠标移动事件,将物体的需要移动到的像素坐标转化为世界坐标。

void AXBOpemglWidget::mouseMoveEvent(QMouseEvent *event)
{makeCurrent();if(m_modelMoving){for(auto iter=m_Models.begin();iter!=m_Models.end();iter++){ModelInfo *modelInfo=&iter.value();if(!modelInfo->isSelected) continue;modelInfo->worldPos=QVector3D(worldPosFromViewPort(event->pos().x(),event->pos().y()));}}doneCurrent();
}

然后再绘制的时候, 使用model.translate(modelInfo.worldPos)即可。

    foreach(auto modelInfo,m_Models){model.setToIdentity();model.translate(modelInfo.worldPos);model.rotate(modelInfo.pitch,QVector3D(1.0,0.0,0.0));model.rotate(modelInfo.yaw,QVector3D(0.0,1.0,0.0));model.rotate(modelInfo.roll,QVector3D(0.0,0.0,1.0));m_ShaderProgram.setUniformValue("model", model);modelInfo.model->Draw(m_ShaderProgram);}

3.旋转

首先判断当前的模型是否被选中。重写鼠标左键单击事件。

void AXBOpemglWidget::mousePressEvent(QMouseEvent *event)
{bool hasSelected=false;makeCurrent();lastPos=event->pos();if(event->buttons()&Qt::LeftButton){QVector4D wolrdPostion=worldPosFromViewPort(event->pos().x(),event->pos().y());mousePickingPos(QVector3D(wolrdPostion));for(QMap<QString, ModelInfo>::iterator iter=m_Models.begin();iter!=m_Models.end();iter++){ModelInfo *modelInfo=&iter.value();float r=(modelInfo->model->m_maxY-modelInfo->model->m_minY)/2;if(modelInfo->worldPos.distanceToPoint(QVector3D(wolrdPostion))<r&&!hasSelected){modelInfo->isSelected=true;hasSelected=true;}elsemodelInfo->isSelected=false;//            qDebug()<<modelInfo->worldPos.distanceToPoint(QVector3D(wolrdPostion))//             <<"<"<<r<<"="<<modelInfo->isSelected;}}doneCurrent();
}

重写鼠标移动事件,改变其欧拉角。

void AXBOpemglWidget::mouseMoveEvent(QMouseEvent *event)
{makeCurrent();if(m_modelMoving){for(auto iter=m_Models.begin();iter!=m_Models.end();iter++){ModelInfo *modelInfo=&iter.value();if(!modelInfo->isSelected) continue;modelInfo->worldPos=QVector3D(worldPosFromViewPort(event->pos().x(),event->pos().y()));}}elseif(event->buttons() & Qt::RightButton|| event->buttons() & Qt::LeftButton|| event->buttons() & Qt::MiddleButton){auto currentPos=event->pos();QPoint deltaPos=currentPos-lastPos;lastPos=currentPos;if(event->buttons() & Qt::RightButton)m_camera.ProcessMouseMovement(deltaPos.x(),-deltaPos.y());elsefor(auto iter=m_Models.begin();iter!=m_Models.end();iter++){ModelInfo *modelInfo=&iter.value();if(!modelInfo->isSelected) continue;if(event->buttons() & Qt::MiddleButton){modelInfo->roll+=deltaPos.x();}else if(event->buttons() & Qt::LeftButton){modelInfo->yaw+=deltaPos.x();modelInfo->pitch+=deltaPos.y();}}}doneCurrent();
}

4.完整工程

https://download.csdn.net/download/wzz953200463/87941666icon-default.png?t=N5K3https://download.csdn.net/download/wzz953200463/87941666

5.相关参考

OpenGL 齐次坐标_Mr.codeee的博客-CSDN博客

OpenGL 坐标系统_Mr.codeee的博客-CSDN博客

OpenGL模型加载_Mr.codeee的博客-CSDN博客

OpenGL 鼠标拾取模型_Mr.codeee的博客-CSDN博客


http://www.ppmy.cn/news/535936.html

相关文章

06- c语言指针 (C语言)

一 指针的引入 1、一般把内存中的一个字节称为一个内存单元。 2、为了正确地访问这些内存单元&#xff0c;必须为每个内存单元编上号。根据一个内存单元的编号即可准确地找到该内存单元。内存单元的编号也叫做地址&#xff0c;通常也把这个地址称为指针。 3、如果在程序中定义…

kubernetes入门案例

kubernetes入门案例 本文我们通过一个 Java Web 应用例子来介绍 kubernetes 的使用&#xff0c;可以让新手快速上手和实践。 此 Java Web 应用的结构比较简单&#xff0c;是一个运行在 Tomcat 里的 Web App&#xff0c;JSP 页面通过 JDBC 直接访问 MySQL 数据库并展示数据。…

975-操作系统内存管理课件(2)

基本分页存储管理 基本地址变换结构 具有快表的地址变换结构 两级页表

输入一个三位整数,输出由其个位、十位、百位反序而成的三位整数(例如:579反序为975)。

/*------------------------------------------------------- 程序功能&#xff1a;输入一个三位整数&#xff0c;输出由其个位、十位、百位反序而成的三位整数&#xff08;例如&#xff1a;579反序为975&#xff09;。 -----------------------------------------------------…

975: 统计利用先序遍历创建的二叉树的度为2的结点个数

题目描述 利用先序递归遍历算法创建二叉树并计算该二叉树度为2结点的个数。先序递归遍历建立二叉树的方法为&#xff1a;按照先序递归遍历的思想将对二叉树结点的抽象访问具体化为根据接收的数据决定是否产生该结点从而实现创建该二叉树的二叉链表存储结构。约定二叉树结点数据…

975. 只有2个按键的键盘

/* 初始时在记事本上只有一个字符 ‘A’。你可以在此记事本上每一步可以进行两种操作&#xff1a; Copy All: 你可以复制记事本上所有的字符&#xff08;不允许部分复制&#xff09;Paste: 你可以粘贴上一次复制的字符。给出一个数字 n。你需要在记事本上得到恰好 n 个 A&#…

南阳理工---题目975关于521

关于521 时间限制&#xff1a; 1000 ms | 内存限制&#xff1a; 65535 KB 难度&#xff1a; 2 描述 Acm队的流年对数学的研究不是很透彻&#xff0c;但是固执的他还是想一头扎进去。 浏览网页的流年忽然看到了网上有人用玫瑰花瓣拼成了521三个数字&#xff0c;顿时觉得好浪漫…

Leetcode_二分 975.奇偶跳

975.奇偶跳 //二分搜索 O(nlogn) O(n) int oddEvenJumps(vector<int>& A) {const int nA.size();vector<vector<int> > dp(n,vector<int>(2));dp[n-1][0]dp[n-1][1]1;map<int,int> mp; //<value,index> BSTmp[A[n-1]]n-1;int ans…