pythonopenglpyqtpyopenglopengl-compat

Change perspective of a PyOpenGL widget


I am trying to change the perspective of my scene in a PyQt5 OpenGL widget. I know I have to override some methods, but I do not know which one should I use.

def initializeGL(self):
    glClear(GL_COLOR_BUFFER_BIT)
    glEnable(GL_DEPTH_TEST)

def paintGL(self):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glBegin(GL_LINES)
    # More code

Where should I use the glOrtho function? And where can I found information about overriding this methods? When I go to the declaration of this methods, they have a pass statement and nothing else, how and when are they executed? Should I use QPainter instead of OpenGL?

    def __init__(self, parent=None):
        super().__init__(parent)
        self._x = 0
        self._y = -0.3
        self._z = 0.5
        self._rz = 0
        self._ry = -0.5
        self.vertices_vertical = [[1000, 1000, 000], [1000, -1000, 000],
                                  [-1000, -1000, 000], [-1000, 1000, 000]]
        self.vertices_horizontal = [[1000, 000, -1000], [1000, 000, 1000],
                                    [-1000, 000, 1000], [-1000, 000, -1000]]
    def initializeGL(self):
        glClear(GL_COLOR_BUFFER_BIT)
        glEnable(GL_DEPTH_TEST)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(0, 1000, 750, 0, -1, 1)

    def paintGL(self):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        glBegin(GL_LINES)

        glColor3d(1, 0, 0)
        glVertex3d(0, 0, 0)
        glVertex3d(1, 0, 0)

        glColor3d(0, 1, 0)
        glVertex3d(0, 0, 0)
        glVertex3d(0, 1, 0)

        glColor3d(0, 0, 1)
        glVertex3d(0, 0, 0)
        glVertex3d(0, 0, 1)

        glEnd()
        # glLoadIdentity()

        glTranslate(self._x, self._y, self._z)
        glRotate(self._ry, 0, 1, 0)
        glRotate(self._rz, 0, 0, 1)

        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR)
        glBegin(GL_QUADS)
        glColor4fv((0, 1, 0, 0.6))
        for vertex in range(4):
            glVertex3fv(self.vertices_vertical[vertex])
        glColor4fv((1, 0, 0, 0.6))
        for vertex in range(4):
            glVertex3fv(self.vertices_horizontal[vertex])
        glEnd()
        glDisable(GL_BLEND)

Solution

  • In Legacy OpenGL the current matrix is a global state. There are different kind of matrices, for each kind of matrix exists a matrix stack. The top of the matrix stack is the current matrix. The matrix stack which is the target for subsequent matrix operations like glOrtho, glPushMatrix/glPopMatrix, glLoadIdentity,etc. can be chosen by glMatrixMode.

    Each vertex coordinate (glVertex) is transformed by the model view matrix (GL_MODELVIEW) and the projection matrix (GL_PROJECTION).

    Chose the projection matrix mode in initializeGL. Set the Identity matrix and set the orthographic projection by glOrtho. Note, glOrtho dose not only set a matrix, it defines a Orthographic projection matrix and multiplies the current matrix by the new matrix.

    e.g. Set an orthographic projection, which transforms "window" coordinates to the normalized device space. In the following (windowdWidth, windowHeight) is the size of the window:

    def initializeGL(self):
        glClear(GL_COLOR_BUFFER_BIT)
        glEnable(GL_DEPTH_TEST)
    
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(0, windowdWidth, windowHeight, 0, -1, 1) 
    

    Use the model view matrix mode to set the model view transformations, before you draw the model:

    def paintGL(self):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        # model view transformations
        # [...]
    
        glBegin(GL_LINES)
        # [...]
        glEnd()