物体的不可见部分

invisible part of object

我一直在尝试在 opengl 上创建一些对象,但我遇到了对象某些部分消失的问题。

这是我的代码。它实际上是一个默认的例子,但我改变了一些部分

import sys
from PyQt5.QtCore import pyqtSignal, QPoint, QSize, Qt
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import (QApplication, QHBoxLayout, QOpenGLWidget, QSlider,
                             QWidget)
import OpenGL.GL as gl

from OpenGL.GL import *
from OpenGL.GLU import *


class Window(QWidget):

    def __init__(self):
        super(Window, self).__init__()

        self.glWidget = GLWidget()


        mainLayout = QHBoxLayout()
        mainLayout.addWidget(self.glWidget)

        self.setLayout(mainLayout)

        self.setWindowTitle("Hello GL")

class GLWidget(QOpenGLWidget):
    xRotationChanged = pyqtSignal(int)
    yRotationChanged = pyqtSignal(int)
    zRotationChanged = pyqtSignal(int)

    def __init__(self, parent=None):
        super(GLWidget, self).__init__(parent)

        self.object = 0
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0

        self.lastPos = QPoint()

        self.trolltechGreen = QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
        self.trolltechPurple = QColor.fromCmykF(0.0, 0.0, 0.0, 1.0)

        self.quadric = gluNewQuadric()
    def initializeGL(self):
        print(self.getOpenglInfo())

        self.setClearColor(self.trolltechPurple.darker())
        self.object = self.main()
        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
        gl.glEnable(gl.GL_BLEND)
        gl.glShadeModel(gl.GL_FLAT)
        gl.glEnable(gl.GL_DEPTH_TEST)
        gl.glEnable(gl.GL_CULL_FACE)

    def mousePressEvent(self, event):
        self.lastPos = event.pos()


    def minimumSizeHint(self):
        return QSize(100, 100)

    def sizeHint(self):
        return QSize(600, 600)

    def setXRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.xRot:
            self.xRot = angle
            self.xRotationChanged.emit(angle)
            self.update()

    def setYRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.yRot:
            self.yRot = angle
            self.yRotationChanged.emit(angle)
            self.update()

    def setZRotation(self, angle):
        angle = self.normalizeAngle(angle)
        if angle != self.zRot:
            self.zRot = angle
            self.zRotationChanged.emit(angle)
            self.update()

    def mousePressEvent(self, event):
        self.lastPos = event.pos()

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if event.buttons() & Qt.LeftButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setYRotation(self.yRot + 8 * dx)
        elif event.buttons() & Qt.RightButton:
            self.setXRotation(self.xRot + 8 * dy)
            self.setZRotation(self.zRot + 8 * dx)

        self.lastPos = event.pos()

    def getOpenglInfo(self):
        info = """
            Vendor: {0}
            Renderer: {1}
            OpenGL Version: {2}
            Shader Version: {3}
        """.format(
            gl.glGetString(gl.GL_VENDOR),
            gl.glGetString(gl.GL_RENDERER),
            gl.glGetString(gl.GL_VERSION),
            gl.glGetString(gl.GL_SHADING_LANGUAGE_VERSION)
        )
        return info

    def paintGL(self):
        gl.glClear(
            gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
        gl.glLoadIdentity()
        gl.glTranslated(0.0, 0.0, -10.0)
        gl.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
        gl.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
        gl.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
        gl.glCallList(self.object)

    def resizeGL(self, width, height):
        side = min(width, height)
        if side < 0:
            return

        gl.glViewport((width - side) // 2, (height - side) // 2, side,
                           side)

        gl.glMatrixMode(gl.GL_PROJECTION)
        gl.glLoadIdentity()
        gl.glOrtho(-3, 3, 3, -3, 4.0, 55.0)
        gl.glMatrixMode(gl.GL_MODELVIEW)

立方体和圆柱体吃水

    def main(self):
        genList = gl.glGenLists(1)
        gl.glNewList(genList, gl.GL_COMPILE)

        glPushName(1)
        glBegin(GL_QUADS)
        glColor4f(0.0, 0.0, 1.0, 0.5)
        glNormal3f(0.0, 0.0, 1.0)  # Allows for light to reflect off certain parts of surface
        glVertex3f(1.0, 0.0, 0.0)
        glVertex3f(1.0, 1.0, 0.0)
        glVertex3f(1.0, 1.0, 1.0)
        glVertex3f(1.0, 0.0, 1.0)
        glEnd()

        # Back face - Green
        glPushName(2)
        glBegin(GL_QUADS)
        glColor4f(0.0, 1.0, 0.0, 0.5)
        glNormal3f(0.0, 0.0, -1.0)
        glVertex3f(0.0, 0.0, 0.0)
        glVertex3f(0.0, 1.0, 0.0)
        glVertex3f(0.0, 1.0, 1.0)
        glVertex3f(0.0, 0.0, 1.0)
        glEnd()

        # Left face - Red
        glPushName(3)
        glBegin(GL_QUADS)
        glColor4f(1.0, 0.0, 0.0, 0.5)
        glNormal3f(-1.0, 0.0, 0.0)
        glVertex3f(0.0, 0.0, 0.0)
        glVertex3f(1.0, 0.0, 0.0)
        glVertex3f(1.0, 0.0, 1.0)
        glVertex3f(0.0, 0.0, 1.0)
        glEnd()

        # Right face - Orange
        glPushName(4)
        glBegin(GL_QUADS)
        glColor4f(1.0, 0.55, 0.0, 0.5)
        glNormal3f(1.0, 0.0, 0.0)
        glVertex3f(1.0, 1.0, 0.0)
        glVertex3f(1.0, 1.0, 1.0)
        glVertex3f(0.0, 1.0, 1.0)
        glVertex3f(0.0, 1.0, 0.0)
        glEnd()

        # Top face - White
        glPushName(5)
        glBegin(GL_QUADS)
        glColor4f(1.0, 1.0, 1.0, 1.0)
        glNormal3f(0.0, 1.0, 0.0)
        glVertex3f(0.0, 0.0, 1.0)
        glVertex3f(1.0, 0.0, 1.0)
        glVertex3f(1.0, 1.0, 1.0)
        glVertex3f(0.0, 1.0, 1.0)
        glEnd()

        # Bottom face - Yellow
        glPushName(6)
        glBegin(GL_QUADS)
        glColor4f(1.0, 1.0, 0.0, 1.0)
        glNormal3f(0.0, -1.0, 0.0)
        glVertex3f(0.0, 0.0, 0.0)
        glVertex3f(0.0, 1.0, 0.0)
        glVertex3f(1.0, 1.0, 0.0)
        glVertex3f(1.0, 0.0, 0.0)
        glEnd()

        # Window on Front (Blue) Face
        glPushName(7)
        glBegin(GL_QUADS)
        glColor4f(0.0, 1.0, 1.0, 0.4)
        glNormal3f(0.0, 0.0, 1.0)
        glVertex3f(1.0, 0.25, 0.25)
        glVertex3f(1.0, 0.75, 0.25)
        glVertex3f(1.0, 0.75, 0.75)
        glVertex3f(1.0, 0.25, 0.75)
        glEnd()
        gluCylinder(self.quadric,0.4,0.4,0.3,16,1)
        gl.glEndList()

        return genList
    def setClearColor(self, c):
        gl.glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF())

    def setColor(self, c):
        gl.glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF())

    def normalizeAngle(self, angle):
        while angle < 0:
            angle += 360 * 16
        while angle > 360 * 16:
            angle -= 360 * 16
        return angle

if __name__ == '__main__':

    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

结果如下:

我不知道如何解决这个问题,如有任何帮助,我将不胜感激

问题是由 Face Culling 引起的。只有当所有图元的缠绕顺序相同时,面剔除才能正常工作。

禁用面部剔除:

gl.glDisable(gl.GL_CULL_FACE)

或者简单的不启用它(默认情况下面部剔除被禁用)。

gl.glEnable(gl.GL_CULL_FACE)