【OpenGL实验】在python、Qt5、pyOpenGL程序的若干要点

实验效果图:
在这里插入图片描述
代码

目录

  • 一、说明
  • 二、关于QGLWidget
    • 2.1 三个方便的虚函数
    • 2.2 析构函数
    • 2.3 QGLWidget析构函数
  • 三、关于QGLWidget的三个虚函数分工
    • 3.1 initializeGL:数据准备、数据绑定分离
    • 3.2 resizeGL:视角改变函数
    • 3.3 paintGL:绘画函数
  • 四、主窗口的配合:刷新周期的设定
    • 4.1 分工和管理
    • 4.2 主窗口的配合性代码
  • 五、总结

一、说明

   我们采用Qt5做OpenGL的界面,是因为在QGLWidget窗口上,既可以渲染三维动画,也能有按键,方便人机交互。学习渲染艺术的顺序是:首先要能对一些基本几何图形进行渲染。然后是二维物品渲染,最后是三维物体渲染。以下我们对这个学习过程进行系列解读。

二、关于QGLWidget

2.1 三个方便的虚函数

   QGLWidget提供了三个方便的虚拟函数,可以在子类中重写这些函数来执行典型的OpenGL任务:

  • paintGL() :渲染OpenGL场景。每当需要更新小部件时调用。
  • resizeGL () :设置OpenGL视区、投影等。每当小部件调整了大小时都会调用该视区(并且当它第一次显示时也会调用,因为所有新创建的小部件都会自动获得一个调整大小的事件)。
  • initializeGL() :设置OpenGL呈现上下文,定义显示列表等。在第一次调用resizeGL ()或paintGL()之前调用一次。此虚拟函数实时性很强。

   注意:如果是数据需要准备,在initializeGL()中是不好的,因为数据准备程序量较大,不可以在实时性很强的程序中出现。因该让__init__分担数据读写、初始化等耗时的工作。总之,nitializeGL()越是轻便越好。

2.2 析构函数

   PyQt5 存在一些问题,就是有时析构函数未必被调用,因此,准备的资源释放代码不能执行。

   有时在关闭应用程序时,PyQt不会自动调用类的析构函数,可能导致一些资源无法正常释放。这可能是因为应用程序的主事件循环在关闭窗口时仍在运行,从而导致类的实例无法被销毁。
   为了解决这个问题,我们可以通过重写QMainWindow的closeEvent方法来手动触发析构函数的调用。

from PyQt5.QtWidgets import QApplication, QMainWindow

class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
    def __del__(self):
        print("析构函数被调用")
    def closeEvent(self, event):
        self.__del__()  # 手动调用析构函数
        event.accept()
app = QApplication([])
window = MyWindow()
window.show()
app.exec_()

   在上面的示例代码中,我们重写了closeEvent方法,并在其中手动调用了析构函数。通过这种方式,我们可以确保在关闭窗口时,析构函数会被正确地调用。

   在PyQt中,当一个类的实例被销毁时,Python会自动调用它的析构函数(即__del__方法)。析构函数主要用于释放资源(例如关闭文件、断开网络连接等),以确保在对象被销毁之前进行必要的清理工作。

2.3 QGLWidget析构函数

   我们在实验程序中使用析构函数释放CPU缓存。设计模型如下:
母窗口:

class MainWindow(QtWidgets.QMainWindow):
    ... ...             # 忽略其他程序
    def __del__(self):
        self.glWidget.__del__()
    def closeEvent(self, event):
        self.__del__()  # 手动调用析构函数
        event.accept()

子窗口:

class GLWidget(QtOpenGL.QGLWidget):
    ... ...             # 忽略其他程序
	def __del__(self):
	    print("finished")

   其中self.vertVBO是被生成的数据biffer块。注意,非要在主窗启动closeEvent才能启动主窗的关闭程序,否则,主窗的__del__不能保证次次都被调用。
注意:这里的析构函数不要把buffer清除放入,因为QGLWidget已经给自动执行了,我们加入下列语句

gl.glDeleteBuffers(1, (self.vertVBO,))
gl.glDeleteBuffers(1, (self.colorVBO,))

   反而会干扰系统执行。

三、关于QGLWidget的三个虚函数分工

3.1 initializeGL:数据准备、数据绑定分离

   数据生成是一个长时间的任务,最好是“一次生成,整个程序生命周期有效”,因此,数据生成和使用前绑定需要分布在两个程序段内才能发挥效率。
在这里插入图片描述

3.2 resizeGL:视角改变函数

   视角改变是指用鼠标转换观察角度,或者是在窗口拉大拉小后,需要改变观察点数据,该数据包括位置和角度矩阵。

    def resizeGL(self, width, height):
        gl.glViewport(0, 0, width, height)

        gl.glMatrixMode(gl.GL_PROJECTION)
        gl.glLoadIdentity()
        aspect = width / float(height)

        GLU.gluPerspective(45.0, aspect, 1.0, 100.0)
        gl.glMatrixMode(gl.GL_MODELVIEW)

3.3 paintGL:绘画函数

   在每次刷新窗口的时候,需要正式调用一次paintGL;注意,该函数是与时间密切相关的。刷新周期可以交给用户执行。

    def paintGL(self):
        gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)

        gl.glPushMatrix()  # push the current matrix to the current stack

        gl.glTranslate(0.0, 0.0, -50.0)  # third, translate cube to specified depth
        gl.glScale(20.0, 20.0, 20.0)  # second, scale cube
        gl.glRotate(self.rotX, 1.0, 0.0, 0.0)
        gl.glRotate(self.rotY, 0.0, 1.0, 0.0)
        gl.glRotate(self.rotZ, 0.0, 0.0, 1.0)
        gl.glTranslate(-0.5, -0.5, -0.5)  # first, translate cube center to origin
        gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
        gl.glEnableClientState(gl.GL_COLOR_ARRAY)

        gl.glVertexPointer(3, gl.GL_FLOAT, 0, self.vertVBO)
        gl.glColorPointer(3, gl.GL_FLOAT, 0, self.colorVBO)

        # gl.glDrawElements(gl.GL_QUADS, len(self.cubeIdxArray), gl.GL_UNSIGNED_INT, self.cubeIdxArray)
        gl.glDrawArrays(gl.GL_POINTS, 0, 100)

        gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
        gl.glDisableClientState(gl.GL_COLOR_ARRAY)

        gl.glPopMatrix() # restore the previous modelview matrix

四、主窗口的配合:刷新周期的设定

4.1 分工和管理

   主窗口的特点是:主窗口是时间、事件的触发地,通常,QGLWidget附着在主窗口上,主窗口负责整体协调,如图:
在这里插入图片描述

4.2 主窗口的配合性代码

该主窗口的构造函数,首先

class MainWindow(QtWidgets.QMainWindow):

    def __init__(self):
        QtWidgets.QMainWindow.__init__(self) # call the init for the parent class

        self.resize(600, 600)
        self.setWindowTitle('Hello OpenGL App')

        self.glWidget = GLWidget(self)
        self.initGUI()

        # 设置循环刷屏

        timer = QtCore.QTimer(self)
        timer.setInterval(20) # period, in milliseconds
        timer.timeout.connect(self.glWidget.updateGL)
        timer.start()

五、总结

   GLUT、pygame、QT5都能实现渲染界面,虽然它们的区别是微小的,但是,足以在一个小问题上浪费几周的时光,因此,本系列文章将逐步暴露它们的方式分别,以确保在正式开发中流畅自如,而不是现学现卖。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/550280.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

苍穹外卖分类管理

分析 需求分析 SQL的写法 1 在mapper中写 2 在xml中写 Mapper public interface CategoryMapper {/*** 插入数据* param category*/AutoFill(OperationType.INSERT)Insert("insert into category(type, name, sort, status, create_time, update_time, create_user, upd…

docker安装并跑通QQ机器人实践(2)-签名服务器bs-qsign搭建

在前文中,我们详尽阐述了QQ机器人的搭建过程及其最终实现的各项功能展示。接下来,我们将转向探讨该项目基于Docker构建服务的具体实践。本篇将以QQ机器人签名服务——qsign为起点,逐步展开论述。 1 获取和运行 xzhouqd/qsign:8.9.63 镜像 1.…

【K8s】:在 Kubernetes 集群中部署 MySQL8.0 高可用集群(1主2从)

【K8s】:在 Kubernetes 集群中部署 MySQL8.0 高可用集群(1主2从) 一、准备工作二、搭建nfs服务器2.1 安装 NFS 服务器软件包(所有节点执行)2.2 设置共享目录2.3 启动 NFS 服务器2.4 设置防火墙规则(可选&am…

【ROS2】搭建ROS2-Humble + Vscode开发流程

【ROS2】搭建ROS2-Humble Vscode开发流程 文章目录 【ROS2】搭建ROS2-Humble Vscode开发流程1.基本环境配置2.搭建Vscode开发环境 1.基本环境配置 基本的环境配置包括以下步骤: 安装ROS2-Humble,可以参考这里安装一些基本的工具,可以参考…

Webrtc 信令服务器实现

webrtc建联流程图 由上图可知,所谓的信令服务器其实就是将peer的offer/candidate/answer传给对端而已。这样的话实现方式就有很多种了,目前普遍的方式HTTP/HTTPS,WS/WSS。像webrtc-demo-peerconnection就是实现HTTP这种方式。本文使用WS&…

APIGateway的认证

APIGateway的支持的认证如下: 我们从表格中可以看到,HTTP API 不支持资源策略的功能,另外是通过JWT的方式集成Cognito的。 对于REST API则是没有显示说明支持JWT认证,这个我们可以通过Lambda 自定义的方式来实现。 所以按照这个…

LangChain-Chatchat 开源知识库来了

LangChain-Chatchat 开源知识库来了 LangChain-Chatchat 架构设计LangChain-ChatChat 具体实现过程 一键本地离线部署软件环境硬件环境支持三种部署方式 LangChain-Chatchat 是基于 ChatGLM 等大语言模型与 LangChain 等应用框架实现,开源、可离线部署的 RAG 检索增…

Django数据导出与导入问题

执行: python manage.py loaddata data.json 的常见错误: * 1. UnicodeDecodeError: utf-8 codec cant decode byte 0xff in position 0: invalid start byte* 2. raise JSONDecodeError("Unexpected UTF-8 BOM (decode using utf-8-sig)",...django.core.serializer…

vue的就地更新与v-for的key属性

vue的就地更新 Vue中的就地更新到底是怎么回事,为什么会存在就地更新的现象? 注意下面的例子,使用v-for指令时,没有绑定key值,才有就地更新的现象,因为Vue默认按照就地更新的策略来更新v-for渲染的元素列表…

windows Webrtc +VS2019 (M124)下载编译以及调通测试demo

下载depot tools 设置梯子 git config --global http.proxy 127.0.0.1:10000 git config --global https.proxy 127.0.0.1:10000 下载 $ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git 设置depot_tools目录为环境变量 下载webrtc # 设置系统代…

CommunityToolkit.Mvvm笔记1---Instruction

CommunityToolkit.Mvvm是一个官方社区套件(Windows Community Toolkit),延续了MVVMLight的风格,是一个现代、快速和模块化的 MVVM 库。 它是 .NET 社区工具包的一部分。 第一:入门安装 1,用NuGget安装,搜索Community…

.NET 发布,部署和运行应用程序

.NET应用发布 发布.Net应用有很多种方式,下面列举三种发布方式: 单文件发布跨平台发布Docker发布 单文件发布 右键工程,选择“发布”,部署模式选择“独立”,目标运行时选择自己想要部署到的系统,我这里用…

【Windows10】Anaconda3安装+pytorch+tensorflow+pycharm

文章目录 一、下载anaconda0.双击下载的文件1. 选择All users2. 安装路径3. 勾选环境变量和安装python4.安装完成5.添加环境变量6.测试是否安装成功 二、安装pytorch(先看四!先检查一下自己电脑是不是只能安装GPU版的1.查看conda图形化界面2.在安装pytor…

ES源码二:集群启动过程

命令行参数解析 Elasticsearch:在main里面创建了Elasticsearch实例,然后调用了main方法,这个main方法最终会调用到父类Command的main方法 这里做了几件事: 注册一个 ShutdownHook,其作用就是在系统关闭的时候捕获IO…

使用SpringBoot3+Vue3开发公寓管理系统

项目介绍 公寓管理系统可以帮助公寓管理员更方便的进行管理房屋。功能包括系统管理、房间管理、租户管理、收租管理、房间家具管理、家具管理、维修管理、维修师傅管理、退房管理。 功能介绍 系统管理 用户管理 对系统管理员进行管理,新增管理员,修改…

CentOS 7开机启动过程,引导和服务,密码的修改

开机启动过程: 引导过程:1.开机自检(BIOS)->2.MBR引导->GRUB菜单->加载内核kernel->systemd进程初始化 程序:执行特定任务的一串代码,静态,存在硬盘中。 进程:运行中的程序叫进程&#xff0…

Unity 点击次数统计功能

介绍 💡.调用方便,发生点击事件后直接通过"xxx".CacheClick缓存 💡. 在允许的时间间隔内再次点击会累计点击次数,直到超出后触发事件 传送门👈

计算机视觉——OpenCV Python基于颜色识别的目标检测

1. 计算机视觉中的颜色空间 颜色空间在计算机视觉领域的应用非常广泛,它们在图像和视频处理、物体检测等任务中扮演着重要角色。颜色空间的主要作用是将颜色以数值形式表示出来,这样计算机算法就能够对其进行处理和分析。不同的颜色空间有着不同的特点和…

uniapp--登录和注册页面-- login

目录 1.效果展示 2.源代码展示 测试登录 login.js 测试请求 request.js 测试首页index.js 1.效果展示 2.源代码展示 <template><view><f-navbar title"登录" navbarType"4"></f-navbar><view class"tips"><…

2024蓝桥杯每日一题(最大公约数)

备战2024年蓝桥杯 -- 每日一题 Python大学A组 试题一&#xff1a;公约数 试题二&#xff1a;最大公约数 试题三&#xff1a;等差数列 试题四&#xff1a;最大比例 试题五&#xff1a;Hankson的趣味题 试题一&#xff1a;公约数 【题目描述】 …