Чтение нарушения прав доступа PyOpenGL при вызове glutWireSphere()

Я создаю приложение, используя PyOpenGL и PyQt5 на Python3.5.2

Цель приложения - настроить окно с классом QGLWidget и нарисовать сферу с помощью функции glutWireSphere. Код отлично работает на моем ноутбуке Ubuntu Linux 16.04 LTS, но на моем рабочем столе Windows 7 происходит сбой с OSError: exception: access violation reading 0x00000000000000C1 в строке glutWireSphere. Если я закомментирую эту строку, программа будет выполняться нормально. Я попробовал другой пример кода (пример ниже), который демонстрирует, как рисовать сферу с помощью glut, и он не разбивается, но управляет окнами с помощью glut.

Мой код:

from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
from PyQt5.QtOpenGL import *
from PyQt5 import QtGui
from PyQt5 import QtWidgets
from PyQt5 import QtCore


class MyWidget(QGLWidget):

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

        self.cameraDistanceZ = 10

    def paintGL(self):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glColor3f(0.33, 0.33, 0.33)
        glutSolidSphere(1, 20, 20)


    def resizeGL(self, w, h):
        glViewport(0, 0, w, h)
        self.setOrthoProjection()
        self.screenCenterX = w/2
        self.screenCenterY = h/2

    def setOrthoProjection(self):
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        w = self.width()
        h = self.height()
        glOrtho(-10, 10, -10, 10, -5.0, 15.0)
        gluLookAt(0,0,self.cameraDistanceZ, 0,0, -10, 0,1,0)

    def initializeGL(self):
        print("Start init process")
        glutInit(sys.argv)
        glClearColor(0.0, 0.0, 0.1, 0.0)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glClearDepth(1.0)

        self.updateGL()


def main():
    app = QtWidgets.QApplication(["To parathyro"])
    widget = MyWidget()
    widget.show()
    sys.exit(app.exec_())
if __name__ == '__main__':
    main()

Рабочий пример:

from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
import sys


def main():
    glutInit(sys.argv)
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
    glutInitWindowSize(400,400)
    glutCreateWindow(b"myWindow")

    glClearColor(0.,0.,0.,1.)
    glShadeModel(GL_SMOOTH)
    glEnable(GL_CULL_FACE)
    glEnable(GL_DEPTH_TEST)
    glEnable(GL_LIGHTING)
    lightZeroPosition = [10.,4.,10.,1.]
    lightZeroColor = [0.8,1.0,0.8,1.0] #green tinged
    glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition)
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor)
    glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1)
    glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05)
    glEnable(GL_LIGHT0)
    glutDisplayFunc(display)
    glMatrixMode(GL_PROJECTION)
    gluPerspective(40.,1.,1.,40.)
    glMatrixMode(GL_MODELVIEW)
    gluLookAt(0,0,10,
              0,0,0,
              0,1,0)
    glPushMatrix()
    glutMainLoop()
    return

def display():
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    glPushMatrix()
    color = [1.0,0.,0.,1.]
    glMaterialfv(GL_FRONT,GL_DIFFUSE,color)
    glutWireSphere(1,20,20)
    glPopMatrix()
    glutSwapBuffers()
    return

if __name__ == '__main__': main()

Если я пытаюсь нарисовать что-то другое, например glutSolidSphere, я получаю ту же ошибку, но по другому адресу. Все ошибки нарушения прав доступа, которые я нашел в Интернете, относятся к конкретным приложениям и в основном связаны с неправильным типом ввода в какой-либо функции. В моем приложении не так много места для такой ошибки, так как функции в моем коде не принимают много аргументов, или есть что-то, чего я еще не заметил.

Для моей настольной системы Windows 7 я загрузил Python 3.5.2 с официального сайта, я установил PyQt5 с помощью pip и PyOpenGL через Неофициальные двоичные файлы Windows для пакетов расширений Python согласно эти инструкции

Я думал, что это связано с проблемами в библиотеке freeglut, но это работает на другом примере. Я предполагаю, что это как-то связано с тем, как я инициализирую freeglut в своем приложении, или это связано с PyQT5

Вопрос

Как я могу отследить проблему и решить ее, не переходя на другую архитектуру моего приложения?


person Boombastic    schedule 20.02.2018    source источник
comment
Любые рекомендации о том, как сделать этот вопрос более ясным?   -  person Boombastic    schedule 02.03.2018
comment
Я не знаю решения, но мне удалось воспроизвести точно такую ​​же проблему с PyQt5 и перенасыщением Py 3 (так что, вероятно, это связано с этой цепочкой инструментов).   -  person Fabio Zadrozny    schedule 13.03.2018
comment
Я предполагаю, что это связано с тем, как PyQt5 настраивает переполнение, или между ними есть какое-то неправильное управление памятью. Я читал в документации Qt, что виджет QGL устарел и вместо него следует использовать QOpenGLWidget, но результаты такие же.   -  person Boombastic    schedule 14.03.2018
comment
Да... лично я постараюсь не использовать перенасыщение (для меня проблемы с зависимостью того не стоят, но я уверен, что если вы скомпилируете freeglut в режиме отладки и войдете в отладчик, вы сможете для диагностики проблемы).   -  person Fabio Zadrozny    schedule 14.03.2018
comment
Я запускаю свою программу в режиме отладки, и проблема заключается в freeglut.dll, относительном скачке в коде сборки. Но как исходить оттуда? Или вы имеете в виду что-то другое?   -  person Boombastic    schedule 18.03.2018
comment
Я имею в виду получение исходников freeglut, локальную компиляцию и исправление (вы также можете попробовать обратиться к мейнтейнерам freeglut, но, поскольку последний выпуск выпущен в 2015 году, он может быть неактивным). Вероятно, где-то внутри: github.com/dcnieho /FreeGLUT/blob/ (или кто знает, может быть, в основной версии это исправлено, но они просто еще не выпустили ее).   -  person Fabio Zadrozny    schedule 19.03.2018


Ответы (1)


Кажется, сбой происходит из-за того, что glutWireSphere требует, чтобы вы сначала вызвали glutCreateWindow, посмотрите, например, этот небольшой фрагмент:

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

from PyQt5.Qt import *  # noqa


class MyWidget(QGLWidget):

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

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

        glPushMatrix()
        color = [1.0, 0., 0., 1.]
        glMaterialfv(GL_FRONT, GL_DIFFUSE, color)
        glutWireSphere(1, 20, 20)
        glPopMatrix()
        glutSwapBuffers()

    def glutInitialization(self):
        glutInit(sys.argv)
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
        glutInitWindowSize(400, 400)
        glutCreateWindow(b"Glut Window")

    def initializeGL(self):
        glClearColor(0., 0., 0., 1.)
        glShadeModel(GL_SMOOTH)
        glEnable(GL_CULL_FACE)
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_LIGHTING)
        lightZeroPosition = [10., 4., 10., 1.]
        lightZeroColor = [0.8, 1.0, 0.8, 1.0]  # green tinged
        glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition)
        glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor)
        glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1)
        glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05)
        glEnable(GL_LIGHT0)
        glMatrixMode(GL_PROJECTION)
        gluPerspective(40., 1., 1., 40.)
        glMatrixMode(GL_MODELVIEW)
        gluLookAt(0, 0, 10,
                  0, 0, 0,
                  0, 1, 0)
        glPushMatrix()

        self.glutInitialization()


def main():
    app = QApplication(["To parathyro"])
    widget = MyWidget()
    widget.setWindowTitle("Pyqt Widget")
    widget.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

Вы можете увидеть, как сфера будет выглядеть в окне pyqt (активный контекст gl). Затем прокомментируйте glutCreateWindow(b"Glut Window") и запустите его снова, так что вы увидите, что сбой сегментации снова появится.

Мое предложение? Я бы не стал полагаться на геометрическую функцию переполнения, если бы не использовал Glut в качестве системы управления окнами opengl.

Кстати, создание сферы совсем не сложно и стоит ты попробуй :)

person BPL    schedule 02.04.2018
comment
Спасибо, кстати, мне любопытно, почему эта ошибка не появляется в системе Linux. - person Boombastic; 05.04.2018