【问题标题】:Cutted cube with PyQt5用 PyQt5 切割立方体
【发布时间】:2021-07-02 19:26:53
【问题描述】:

我正在使用 python3.9-64,我需要创建一个 3d 立方体然后我按照这个tutorial, 我把程序分成了更多的文件,我使用 PyQt5 但教程使用 PyQt4,我更改了包含 calsses 的模块(例如:PyQt4 有 Gui.QMainWindow,PyQt5 有 QtWidgets.QMainWindow)

这是我的文件

core.py

cubeVtxList = [
    [0.0, 0.0, 0.0],
    [1.0, 0.0, 0.0],
    [1.0, 1.0, 0.0],
    [0.0, 1.0, 0.0],
    [0.0, 0.0, 1.0],
    [1.0, 0.0, 1.0],
    [1.0, 1.0, 1.0],
    [0.0, 1.0, 1.0]]
        
cubeClrList = [
    [1.0, 0.0, 0.0],
    [1.0, 0.0, 0.0],
    [1.0, 1.0, 0.0],
    [0.0, 1.0, 0.0],
    [0.0, 0.0, 1.0],
    [1.0, 0.0, 1.0],
    [1.0, 1.0, 1.0],
    [0.0, 1.0, 1.0]]
        
cubeIdxList = [
    0, 1, 2, 3,
    3, 2, 6, 7,
    1, 0, 4, 5,
    2, 1, 5, 6,
    0, 3, 7, 4,
    7, 6, 5, 4 ]

GLWidget.py

from PyQt5.QtGui import QColor
from PyQt5.QtOpenGL import QGLWidget
import OpenGL.GL as gl
import OpenGL.GLU as glu
from OpenGL.arrays import vbo
import numpy as np
from core import *
    
class GLWidget(QGLWidget):
    
    def __init__(self, parent=None):
        self.parent = parent
        QGLWidget.__init__(self)
        
    def initializeGL(self):
        self.qglClearColor(QColor(0, 0, 0))
        gl.glEnable(gl.GL_DEPTH_TEST)
        self.initGeometry()
        self.rotX = 0.0
        self.rotY = 0.0
        self.rotZ = 0.0
    
    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)
    
    def paintGL(self):
        gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
        gl.glPushMatrix()
        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)
        
        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.glDisableClientState(gl.GL_VERTEX_ARRAY)
        gl.glDisableClientState(gl.GL_COLOR_ARRAY)
        
        gl.glPopMatrix()
    
    def initGeometry(self):
        self.cubeVtxArray = np.array(cubeVtxList)
        self.vertVbo = vbo.VBO(np.reshape(self.cubeVtxArray, (1, -1)).astype(np.float32))
        self.vertVbo.bind()
        self.cubeClrArray = np.array(cubeClrList)
        self.colorVbo = vbo.VBO(np.reshape(self.cubeClrArray, (1, -1)).astype(np.float32))
        self.colorVbo.bind()
        self.cubeIdxArray = np.array(cubeIdxList)
        
    def setRotX(self, val):
        self.rotX = val

    def setRotY(self, val):
        self.rotY = val

    def setRotZ(self, val):
        self.rotZ = val

MWindow.py

from PyQt5.QtWidgets import QMainWindow, QSlider, QVBoxLayout, QWidget
from PyQt5 import QtCore
from GLWidget import GLWidget
from PyQt5.QtCore import QTimer

class MWindow(QMainWindow):
    
    def __init__(self):
        QMainWindow.__init__(self)
        self.resize(500, 500)
        self.setWindowTitle('titolo')
        self.glWidget = GLWidget(self)
        self.initGui()
        self.timer = QTimer()
        self.timer.setInterval(20)
        self.timer.timeout.connect(self.glWidget.updateGL)
        self.timer.start()
    
    def initGui(self):
        central_widget = QWidget()
        gui_layout = QVBoxLayout()
        central_widget.setLayout(gui_layout)
        self.setCentralWidget(central_widget)
        gui_layout.addWidget(self.glWidget)
        sliderX = QSlider(QtCore.Qt.Horizontal)
        sliderX.valueChanged.connect(lambda val: self.glWidget.setRotX(val))
        sliderY = QSlider(QtCore.Qt.Horizontal)
        sliderY.valueChanged.connect(lambda val: self.glWidget.setRotY(val))
        sliderZ = QSlider(QtCore.Qt.Horizontal)
        sliderZ.valueChanged.connect(lambda val: self.glWidget.setRotZ(val))
        gui_layout.addWidget(sliderX)
        gui_layout.addWidget(sliderY)
        gui_layout.addWidget(sliderZ)

main.py

from MWindow import MWindow
from PyQt5.QtWidgets import QApplication
import sys
    
def Main():
    app = QApplication([])
    mw = MWindow()
    mw.show()
    sys.exit(app.exec_())
    
if __name__ == '__main__':
    Main()

结果应该是一个可以用滑块移动的立方体,但我得到了一个如下图所示的切割立方体

【问题讨论】:

    标签: python opengl pyqt5 pyopengl python-3.9


    【解决方案1】:

    默认的dtypefloat。创建和索引缓冲区时,您必须使用与绘图调用中的类型标识符相对应的整数数据类型。在您的情况下,指定的类型是GL_UNSIGNED_INT。因此数据类型必须是 uint32:

    self.cubeIdxArray = np.array(cubeIdxList)

    self.cubeIdxArray = np.array(cubeIdxList, dtype=np.uint32)
    

    glVertexPointer 的最后一个参数不是顶点缓冲区偏移量。它是缓冲区对象数据存储的偏移量。您必须绑定指定属性的正确缓冲区:

    gl.glVertexPointer(3, gl.GL_FLOAT, 0, self.vertVbo)
    gl.glColorPointer(3, gl.GL_FLOAT, 0, self.colorVbo)

    self.vertVbo.bind()
    gl.glVertexPointer(3, gl.GL_FLOAT, 0, None)
    self.colorVbo.bind()
    gl.glColorPointer(3, gl.GL_FLOAT, 0, None)
    

    【讨论】:

    • @Linus 我在您的代码中发现了另一个问题。我已经扩展了答案。
    • @Linus 所以还有另一个问题。什么“不起作用”?有什么变化吗?
    • 不,它一直是图片中的同一个立方体
    • @Linus 抱歉,事实并非如此。当您按照我的建议进行更改时,必须进行一些更改。 (或许还是不正确,但一定是不同的)
    【解决方案2】:

    只需将 core.py 中 cubeClrList 中的第一个条目更改为

    cubeClrList = [
    [1.0, 0.0, 0.0],
    [1.0, 0.0, 0.0],
    

    cubeClrList = [
    # v change this value
    [0.0, 0.0, 0.0],
    [1.0, 0.0, 0.0],
    

    【讨论】:

      猜你喜欢
      • 2015-11-10
      • 2013-04-06
      • 1970-01-01
      • 2012-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多