当前位置: 首页 > news >正文

17. OPenGL实现旋转移动物体

1. 说明:

整体思路:如果想实现动态,可以使用一个矩阵和我们给定的坐标值进行相乘,实时的改变坐标值
类似于坐标的齐次变换,然后使用一个定时器,在规定时间内触发重新绘制的函数。
实际效果:

OPenGL移动旋转图形

2. 实现步骤:

第一步:
在MyOpenGLWidget.h文件中添加一个定时器变量,用来实时的调用更新函数,让画布在规定的间隔时间内重绘:

#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H#include <QObject>
#include <QWidget>
#include <QTimer>
#include <QTime>#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>class MyOpenGLWidget : public QOpenGLWidget,QOpenGLFunctions_3_3_Core
{Q_OBJECT
public:enum Shape{None,Rect,Circle,Triangle};explicit MyOpenGLWidget(QWidget *parent = nullptr);void drawShape(Shape shape);void clearGraphic();void setWireFrame(bool wireFrame);protected:virtual void initializeGL() override;virtual void resizeGL(int w, int h) override;virtual void paintGL() override;signals:public slots:void on_timeout();private:Shape m_shape;QOpenGLShaderProgram shaderProgram;QOpenGLTexture *textureStar;QTimer timer;	//在之前的基础上再添加一个 定时器 变量
};
#endif // MYOPENGLWIDGET_H

第二步:
在MyOpenGLWidget.cpp文件中的paintGL()函数内部声明一个矩阵,使这个矩阵位移一段距离,然后随着时间不停的做旋转,最后将这个矩阵作用在顶点着色器的位置坐标上,即可实现物体的平移和旋转。
注意:矩阵要用左乘,且矩阵matrix在代码的体现上应该先平移,再旋转,否则会乱掉
paintGL()函数代码如下:

void MyOpenGLWidget::paintGL()
{QMatrix4x4 matrix;unsigned int time = QTime::currentTime().msec();matrix.translate(0.5,-0.5,0.0);//先写平移的代码matrix.rotate(time,0.0f,0.0f,1.0f);//再写旋转的代码glClearColor(0.5f,0.9f,0.4f,1.0f);glClear(GL_COLOR_BUFFER_BIT);shaderProgram.bind();textureStar->bind(0);//在渲染前只需开启对应的VAO即可glBindVertexArray(VAO);switch (m_shape) {case Rect://将变量matrix传输到顶点着色器中的变量theMatrix中shaderProgram.setUniformValue("theMatrix",matrix);glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,&indices);break;default:break;}}

第三步:
在顶点着色器文件中,定义变量theMatrix,用来接收来自外界数据的传入(matrix),并将变量theMatrix作用在顶点位置坐标上,注意是左乘,代码如下:

#version 330 corelayout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTexCord;out vec3 ourColor;
out vec2 texCord;uniform mat4 theMatrix;//定义变量,接收外界数据void main()
{//将矩阵变换作用在位置坐标上gl_Position = theMatrix * vec4(aPos.x,aPos.y,aPos.z,1.0f);ourColor = aColor;texCord = aTexCord;
}

MyOpenGLWidget.cpp整天代码:

#include "myopenglwidget.h"unsigned int VBO,VAO;//添加一个索引控制器
unsigned int EBO;float vertices[] = {-0.5f,-0.5f,0.0f,0.5f,-0.5f,0.0f,0.0f,0.5f,0.0f
};float verticesColorTexture[] = {	//每一行数据的前三个是位置坐标,后三个是颜色值0.5f,0.5f,0.5f,1.0f,0.0f,0.0f,1.0f,1.0f,0.5f,-0.5f,0.0f,0.0f,1.0f,0.0f,1.0f,0.0f,-0.5f,-0.5f,0.0f,0.0f,0.0f,1.0f,0.0f,0.0f,-0.5f,0.5f,0.0f,0.5f,0.5f,0.5f,0.0f,1.0f
};//添加索引数据
unsigned int indices[]={0,1,3,1,2,3
};MyOpenGLWidget::MyOpenGLWidget(QWidget *parent) :  QOpenGLWidget(parent)
{connect(&timer,SIGNAL(timeout()),this,SLOT(on_timeout()));//定时器触发连接槽函数timer.start(100);//启动定时器
}void MyOpenGLWidget::drawShape(MyOpenGLWidget::Shape shape)
{makeCurrent();m_shape = shape;update();doneCurrent();
}void MyOpenGLWidget::clearGraphic()
{makeCurrent();drawShape(MyOpenGLWidget::None);makeCurrent();glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);update();doneCurrent();
}void MyOpenGLWidget::setWireFrame(bool wireFrame)
{makeCurrent();if(wireFrame){glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);}else{glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);}update();doneCurrent();
}void MyOpenGLWidget::initializeGL()
{initializeOpenGLFunctions();//void glGenVertexArrays(GLsizei n, GLuint *arrays)生成顶点数组对象名称// n: 要产生的VAO对象的数量// arrays: 存放产生的VAO对象的名称glGenVertexArrays(1,&VAO);// void glGenBuffers(GLsizei n,GLuint *buffers)生成顶点缓冲对象// n: 要产生的VBO对象的数量// arrays: 存放产生的VBO对象的名称glGenBuffers(1,&VBO);//初始化索引器glGenBuffers(1,&EBO);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof (indices),indices,GL_STATIC_DRAW);//绑定VAO和VBOglBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER,VBO);//在VBO中存入顶点数据glBufferData(GL_ARRAY_BUFFER,sizeof (verticesColorTexture),verticesColorTexture,GL_STATIC_DRAW);//告诉VAO怎么在VBO中拿数据(顶点位置数据)glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,8*sizeof (float),(void*)0);//开启第一个VAOglEnableVertexAttribArray(0);//告诉VAO怎么在VBO中拿数据(颜色数据)glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,8*sizeof (float),(void*)(3*sizeof(float)));//开启第二个VAOglEnableVertexAttribArray(1);//告诉VAO怎么在VBO中拿数据(纹理数据)glVertexAttribPointer(2,2,GL_FLOAT,GL_FALSE,8*sizeof (float),(void*)(6*sizeof(float)));//开启第三个VAOglEnableVertexAttribArray(2);//用完之后解除绑定(信息已经被记录下来了)glBindBuffer(GL_ARRAY_BUFFER,0);glBindVertexArray(0);//添加着色器shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shaders/Shaders/shape.vert");shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shaders/Shaders/shape.frag");shaderProgram.link();//添加纹理数据textureStar = new QOpenGLTexture(QImage(":/img/images/water.jpg").mirrored());shaderProgram.setUniformValue("textureStar",0);
}void MyOpenGLWidget::resizeGL(int w, int h)
{Q_UNUSED(w);Q_UNUSED(h);}void MyOpenGLWidget::paintGL()
{QMatrix4x4 matrix;unsigned int time = QTime::currentTime().msec();matrix.translate(0.5,-0.5,0.0);matrix.rotate(time,0.0f,0.0f,1.0f);glClearColor(0.5f,0.9f,0.4f,1.0f);glClear(GL_COLOR_BUFFER_BIT);shaderProgram.bind();textureStar->bind(0);//在渲染前只需开启对应的VAO即可glBindVertexArray(VAO);switch (m_shape) {case Rect:shaderProgram.setUniformValue("theMatrix",matrix);glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,&indices);break;default:break;}}
//定时器槽函数内,调用opengl的更新函数
void MyOpenGLWidget::on_timeout()
{update();
}

持续更新中,请大家多多关注…

相关文章:

17. OPenGL实现旋转移动物体

1. 说明&#xff1a; 整体思路&#xff1a;如果想实现动态&#xff0c;可以使用一个矩阵和我们给定的坐标值进行相乘&#xff0c;实时的改变坐标值 类似于坐标的齐次变换&#xff0c;然后使用一个定时器&#xff0c;在规定时间内触发重新绘制的函数。 实际效果&#xff1a; OP…...

《SQL基础》14. 存储过程 · 存储函数

存储过程 存储函数存储过程基本语法变量系统变量用户定义变量局部变量if判断参数case判断while循环repeat循环loop循环游标条件处理程序存储函数存储过程 存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合。调用存储过程可以简化应用开发人员的工作&#xff0c;减…...

NFT Insider #87:The Sandbox 收购游戏开发工作室 Sviper,GHST 大迁徙即将拉开帷幕

引言&#xff1a;NFT Insider由NFT收藏组织WHALE Members(https://twitter.com/WHALEMembers)、BeepCrypto&#xff08;https://twitter.com/beep_crypto&#xff09;联合出品&#xff0c;浓缩每周NFT新闻&#xff0c;为大家带来关于NFT最全面、最新鲜、最有价值的讯息。每期周…...

html部分codewhy网课学习笔记

day1 网页显示的过程和服务器 浏览器内核,也称为渲染引擎 head标签描述网页的原数据&#xff0c;如title shifttab是向前缩进 div>ul>li可以快速生成 <div> <ul> <li></li> </ul> </div> 在早期,单标签如<input>也可写为&l…...

电脑出问题了怎么重装系统修好

电脑在使用过程中经常会出现各种各样的问题&#xff0c;如系统崩溃、蓝屏、病毒感染等。这些问题如果不能及时得到解决&#xff0c;将会给用户带来很多麻烦和损失。小白一键重装系统是一个功能强大的工具&#xff0c;可以帮助用户快速解决电脑常见问题。下面我们就来详细介绍如…...

Nginx国密支持问题记录

文章目录添加国密支持可能出现的问题国密不生效&#xff0c;查看 Nginx 可执行文件路径是否正确证书无法解析Nginx无法启动添加国密支持 NGINX添加国密支持 添加国密支持可以直接按照官网的操作顺序操作即可 参考网址&#xff1a;https://www.gmssl.cn/gmssl/index.jsp 可能出…...

基于ensp的小型局域网网络搭建及需求分析

一 需求分析本实验的目的在于建立小型局域网。由于公司由财政部、人事部、科技部三个部门组成&#xff0c;分布在同一个交换机下。设计以下网络&#xff1a;三个个部门使用两台交换机连接&#xff0c;然后连接到汇聚交换机&#xff0c;再通过路由器与外网以及其他部门网络相连。…...

Kubernetes学习(二)Pod

创建Pod kubectl创建nginx pod 编写 nginx pod的yaml文件 apiVersion: v1 kind: Pod metadata:name: my-nginxlabels:name: my-nginx spec:containers:- image: nginxname: my-nginxresources:limits:memory: "128Mi"cpu: "500m"ports:- name: nginx-po…...

【Docker】docker | 迁移docker目录

一、场景说明1、物理机磁盘空间不够用了2、docker的镜像、容器、卷等资料的默认路径为&#xff1a; /var/lib/docker3、增加了数据盘挂在&#xff0c;需要将docker的全部资料更换个目录二、操作确认是否满足切换条件1&#xff09;服务是否能够暂停&#xff0c;如果可以就OK2&am…...

day24_多线程进阶

今日内容 上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili 同步笔记沐沐霸的博客_CSDN博客-Java2301 零、 复习昨日 一、作业 二、线程安全的集合 三、死锁 四、线程通信 五、生产者消费者 六、线程池 零、 复习昨日 创建线程的几种方式 1) 继承 2) 实现Runnable 3) calla…...

Qt实现系统桌面目录下文件搜索的GUI:功能一:文件查找与现实

⭐️我叫恒心&#xff0c;一名喜欢书写博客的研究生在读生。 原创不易~转载麻烦注明出处&#xff0c;并告知作者&#xff0c;谢谢&#xff01;&#xff01;&#xff01; 这是一篇近期会不断更新的博客欧~~~ 有什么问题的小伙伴 欢迎留言提问欧。 功能点一&#xff1a;文件查找与…...

有关数据库的一级、二级、三级封锁协议

一级封锁协议 一级封锁协议是指&#xff0c;事务T在修改数据R之前必须先对其加X锁&#xff0c;直到事务结束才释放。事务结束包括正常结束&#xff08;COMMIT&#xff09;和非正常结束&#xff08;ROLLBACK).一级封锁协议可防止丢失修改&#xff0c;并保证事务T是可恢复的。在…...

【Android Studio】【学习笔记】【2023春】

文章目录零、常用一、界面布局疑问&报错零、常用 一、界面布局 Android——六大基本布局总结/CSDN小马 同学 【Android】线性布局&#xff08;LinearLayout&#xff09;最全解析/CSDNTeacher.Hu 一个不错的计算器界面&#x1f447; Android Studio App LinearLayout多层…...

window.open()下载文件重命名/js下载文件重命名/js跨域下载文件重命名

普通文件下载 // 1 var fileUrl https://xxxx.docx; window.open(fileUrl"?attname文档.docx");// 2 var a document.createElement(a); a.href https://xxxx.docx; a.download 文档.docx; a.target "_blank"; a.click();以上方式 attname 和 a.down…...

zookeeper:简介及常用命令

目录 一、Zookeeper简介 二、Zookeeper服务端常用命令 1、启动ZooKeeper服务 2、查看ZooKeeper服务状态 3、停止ZooKeeper服务 4、重启ZooKeeper服务 三、Zookeeper客户端常用命令 1、连接ZooKeeper服务端 2、断开连接&#xff1a;quit 3、查看命令帮助&#xff1a;help…...

与流程挖掘布道者熵评科技孙一鸣博士共话流程挖掘市场的起源与前景 | 爱分析访谈

调研&#xff1a;李进宝 陈元新 撰写&#xff1a;李进宝 陈元新 随着数字化转型持续深入&#xff0c;国内企业流程挖掘需求初露端倪。流程挖掘是指通过采集和分析企业数据&#xff0c;以可视化流程图还原企业实际发生的业务流程&#xff0c;进而评估流程运行状况、诊断流程运…...

第十一届蓝桥杯省赛——2解密

题目&#xff1a;【问题描述】小明设计了一种文章加密的方法&#xff1a;对于每个字母 c&#xff0c;将它变成某个另外的字符 Tc。下表给出了字符变换的规则&#xff1a;字母cTc字母cTc字母cTc字母cTcaynlAYNLbxogBXOGcmpoCMPOddquDDQUearfEARFfcssFCSSgitzGITZhkupHKUPinvwINV…...

ChatGPT解答:PYQT5 美化各种控件的方案和实例

ChatGPT解答&#xff1a;PYQT5 美化各种控件的方案和实例 修改按钮样式 button QPushButton(按钮, self) button.setStyleSheet(QPushButton{background-color: red; border-radius: 5px;})修改标签样式 label QLabel(标签, self) label.setStyleSheet(QLabel{color: blue; …...

js实现翻盘抽奖

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>礼物编辑</title><style>* {margin: 0;padding: 0;box-sizing: border-box;list-style-type: none;text-decoration: none;}.container {d…...

Qt QtCreator 安卓开发环境搭建

踩坑 我的qt是使用在线安装工具安装的&#xff0c;Qt版本使用的是5.15.2&#xff0c;QtCreator版本9.0.2 在网上很多教程都是如下步骤 1.安装qt 2.安装jdk 3.安装android-sdk 4.安装android-ndk 5.配置android设置 例如&#xff1a; https://blog.csdn.net/weixin_51363326/…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践

在 Kubernetes 集群中&#xff0c;如何在保障应用高可用的同时有效地管理资源&#xff0c;一直是运维人员和开发者关注的重点。随着微服务架构的普及&#xff0c;集群内各个服务的负载波动日趋明显&#xff0c;传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...

归并排序:分治思想的高效排序

目录 基本原理 流程图解 实现方法 递归实现 非递归实现 演示过程 时间复杂度 基本原理 归并排序(Merge Sort)是一种基于分治思想的排序算法&#xff0c;由约翰冯诺伊曼在1945年提出。其核心思想包括&#xff1a; 分割(Divide)&#xff1a;将待排序数组递归地分成两个子…...

Mac flutter环境搭建

一、下载flutter sdk 制作 Android 应用 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 1、查看mac电脑处理器选择sdk 2、解压 unzip ~/Downloads/flutter_macos_arm64_3.32.2-stable.zip \ -d ~/development/ 3、添加环境变量 命令行打开配置环境变量文件 ope…...

LangChain【6】之输出解析器:结构化LLM响应的关键工具

文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器&#xff1f;1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...

从0开始学习R语言--Day17--Cox回归

Cox回归 在用医疗数据作分析时&#xff0c;最常见的是去预测某类病的患者的死亡率或预测他们的结局。但是我们得到的病人数据&#xff0c;往往会有很多的协变量&#xff0c;即使我们通过计算来减少指标对结果的影响&#xff0c;我们的数据中依然会有很多的协变量&#xff0c;且…...