glReadPixels показывает ошибку с PyQt5.с GLUT Window это работает правильно - PullRequest
0 голосов
/ 10 июня 2019

Я занимаюсь разработкой программного обеспечения, в котором у меня есть окно OpenGL. Я создаю графический интерфейс программного обеспечения с использованием PyQt5 и для окна opengGL я использую QOpengGLWidget, а для выбора объектов я использую трафарет буфер и чтение STENCIL_INDEX как следующая функция на mousePressEvent(self, event):

id = glReadPixels(event.x(), self.height - event.y() - 1, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)

но это не работает, когда я использую с Qt5 GUI и показываю следующую ошибку:

Traceback (most recent call last):
  File "/home/akv26/Desktop/internProject/Main/opengl.py", line 92, in mousePressEvent
    val = glReadPixels(event.x(), self.height - event.y() - 1, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)
  File "/home/akv26/.local/lib/python3.7/site-packages/OpenGL/GL/images.py", line 371, in glReadPixels
    imageData
  File "/home/akv26/.local/lib/python3.7/site-packages/OpenGL/platform/baseplatform.py", line 402, in __call__
    return self( *args, **named )
  File "/home/akv26/.local/lib/python3.7/site-packages/OpenGL/error.py", line 232, in glCheckError
    baseOperation = baseOperation,
OpenGL.error.GLError: GLError(
    err = 1282,
    description = b'invalid operation',
    baseOperation = glReadPixels,
    cArguments = (
        183,
        228,
        1,
        1,
        GL_DEPTH_COMPONENT,
        GL_FLOAT,
        array([[0.]], dtype=float32),
    )
)
Aborted (core dumped)

и вот код для моего кастома QOpenGLWidget:

import sys
from PyQt5.QtWidgets import QOpenGLWidget
from PyQt5.QtCore import QSize, Qt
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
from math import *


class MyGLWidget(QOpenGLWidget):

    def initializeGL(self):
        glutInit()

        glClearColor(1.0, 0.5, 0.2, 0.5)
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_LIGHTING)
        glEnable(GL_COLOR_MATERIAL)
        glEnable(GL_LIGHT0)
        glEnable(GL_LIGHT1)
        glEnable(GL_NORMALIZE)

        glShadeModel(GL_SMOOTH)

    def resizeGL(self, w, h):
        self.height=h
        if h==0:
            h=1
        ratio =  w * 1.0 / h

        # Use the Projection Matrix
        glMatrixMode(GL_PROJECTION)

        # Reset Matrix
        glLoadIdentity()

        # Set the viewport to be the entire window
        glViewport(0, 0, w, h)

        # Set the correct perspective.
        gluPerspective(45.0, ratio, 0.1, 100.0)

        # Get Back to the Modelview
        glMatrixMode(GL_MODELVIEW)

    def paintGL(self):
        glClearStencil(0)
        glClear(GL_STENCIL_BUFFER_BIT)

        glEnable(GL_STENCIL_TEST)
        glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE)

        ambientColor = [0.2,0.2,0.2,1.0]
        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor)

        lightColor0 = [0.5,0.5,0.5,1.0]
        lightPos0 = [0, 0, -10.0, 1.0]
        glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0)
        glLightfv(GL_LIGHT0, GL_POSITION, lightPos0)

        lightColor1 = [0.5, 0.2, 0.2, 1.0]
        lightPos1 = [-1.0, 0.5, 0.5, 0.0]
        glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor1)
        glLightfv(GL_LIGHT1, GL_POSITION, lightPos1)

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        gluLookAt(-5,  5, -5, 0, 0,  0, 0.0, 1.0,  0.0)

        self.drawSome()

    def drawSome(self):
        glStencilFunc(GL_ALWAYS, 1, -1)

        glBegin(GL_QUADS)
        glColor3f(0.0, 0.5, 0.0)
        glNormal3f(0,0,-1)
        glVertex3f(-1,-1,0)
        glVertex3f(-1,1,0)
        glVertex3f(1,1,0)
        glVertex3f(1,-1,0)

        glEnd()

        glTranslatef(0,0,0)
        glColor3f(0.5,0,0)
        glStencilFunc(GL_ALWAYS, 2, -1)
        glutSolidCube(1.0)

    def mousePressEvent(self, event):

        id = glReadPixels(event.x(), self.height - event.y() - 1, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_INT)
        print(id)

и то же работает правильно, когда я использую это с окном GLUT следующим образом:

from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
from math import *
import numpy as np


window_width=0
window_height=0

def changeSize(w, h):
    global window_height, window_width
    window_width=w
    window_height=h
    # Prevent a divide by zero, when window is too short
    # (you cant make a window of zero width).
    if h==0:
        h=1
    ratio =  w * 1.0 / h

    # Use the Projection Matrix
    glMatrixMode(GL_PROJECTION)

    # Reset Matrix
    glLoadIdentity()

    # Set the viewport to be the entire window
    glViewport(0, 0, w, h)

    # Set the correct perspective.
    gluPerspective(45.0, ratio, 0.1, 100.0)

    # Get Back to the Modelview
    glMatrixMode(GL_MODELVIEW)


def drawSome():

    glStencilFunc(GL_ALWAYS, 1, -1)

    glBegin(GL_QUADS)
    glColor3f(0.0, 0.5, 0.0)
    glNormal3f(0,0,-1)
    glVertex3f(-1,-1,0)
    glVertex3f(-1,1,0)
    glVertex3f(1,1,0)
    glVertex3f(1,-1,0)

    glEnd()

    glTranslatef(0,0,0)
    glColor3f(0.5,0,0)
    glStencilFunc(GL_ALWAYS, 2, -1)
    glutSolidCube(1.0)

def renderScene():

    glClearStencil(0)
    glClear(GL_STENCIL_BUFFER_BIT)

    glEnable(GL_STENCIL_TEST)
    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE)

    ambientColor = [0.2,0.2,0.2,1.0]
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor)

    lightColor0 = [0.5,0.5,0.5,1.0] #Color
    lightPos0 = [0, 0, -10.0, 1.0]
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0)
    glLightfv(GL_LIGHT0, GL_POSITION, lightPos0)

    lightColor1 = [0.5, 0.2, 0.2, 1.0]
    lightPos1 = [-1.0, 0.5, 0.5, 0.0]
    glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor1)
    glLightfv(GL_LIGHT1, GL_POSITION, lightPos1)

    # Clear Color and Depth Buffers
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    # Reset transformations
    glLoadIdentity()
    # Set the camera
    # gluLookAt(x,  1.0, z, x+lx, 1.0,  z+lz,   0.0, 1.0,  0.0)
    gluLookAt(-5,  5, -5, 0, 0,  0, 0.0, 1.0,  0.0)

    drawSome()

    glutSwapBuffers()

def mouse(button, state, x, y):

    global window_height
    id = glReadPixels(x, window_height - y - 1, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_INT)
    print(id[0][0])

if __name__ == '__main__':
    glutInit()
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
    # glutInitWindowPosition(100,100)
    glutInitWindowSize(320,320)
    glutCreateWindow("Lighthouse3D - GLUT Tutorial")
    glClearColor(1.0, 0.5, 0.2, 0.5)
    # register callbacks
    glutDisplayFunc(renderScene)
    glutReshapeFunc(changeSize)
    glutMouseFunc(mouse)
    # glutTimerFunc(0, Timer, 0)

    # here are the new entries
    glutIgnoreKeyRepeat(1)

    # OpenGL init
    glEnable(GL_DEPTH_TEST)
    glEnable(GL_LIGHTING)
    glEnable(GL_COLOR_MATERIAL)
    glEnable(GL_LIGHT0)
    glEnable(GL_LIGHT1)
    glEnable(GL_NORMALIZE)
    glShadeModel(GL_SMOOTH)

    glutMainLoop()

Как решить проблему с QT5 GUI?

Ответы [ 2 ]

1 голос
/ 10 июня 2019

Я подозреваю, что при вызове glReadPixels текущий контекст OpenGL отсутствует. Вы mousePressEvent должны, вероятно, позвонить QOpenGLWidget::makeCurrent ...

def mousePressEvent(self, event):

    # Make the OpenGL context associated with this `QOpenGLWidget` current. and dont forget self
    self.makeCurrent()

    id = glReadPixels(event.x(), self.height - event.y() - 1, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_INT)
    print(id)
    self.doneCurrent()
1 голос
/ 10 июня 2019

glReadPixels требует, чтобы контекст рендеринга был текущим в потоке. Qt выполняет автоматическое управление контекстом, и хорошо задокументировано, что вне методов с именем …GL контекст может быть не текущим.

Вы должны явно сделать контекст текущим вне тех методов, для которых классы Qt OpenGL предлагают методы makeCurrent и doneCurrent. Подготовьте свой вызов glReadPixels к вызовам этих функций; убедитесь, что makeCurrent успешно, так как контекст может быть текущим в другом потоке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...