Search code examples
pythonpython-3.xopenglpyopengl

Which are the modern glTranslate and glRotate alternatives?


Important edit: I am using the PyOpenGL binding of OpenGL I am trying not to use the glRotate and glTranslate functions, but I have not found any alternative to this two functions. This functions are deprecated. What can I use?


Solution

  • The modern way is to write a Shader program, to use Vertex Array Objects and to use Uniform variable(s) of type mat4.
    There is more code to write, in compare to the deprecated fixed function pipeline but the benefit is high flexibility and a far better performance, in compare to drawing by glBegin/glEnd sequences.

    For the matrix calculations can be used the PyGLM library, which is the python version of the c++ OpenGL Mathematics (glm) library.

    e.g. A scale, rotation matrix around the z-axis by an angle and translation can set by:

    model = glm.mat4(1)
    model = glm.translate(model, glm.vec3(0.2, 0.2, 0))
    model = glm.rotate(model, angle, glm.vec3(0, 0, 1))
    model = glm.scale(model, glm.vec3(0.5, 0.5, 1))
    

    In compare to the the Legacy OpenGL operation glRoatate, the angle has to be set in radians.
    Note, instead of using PyGLM it is also possible to use the popular NumPy library and numpy.matrix, but PyGLM is closer to that what you know from Legacy OpenGL and the functions glScale, glTranslate and glRotate.
    Of course it would be possible to set the the 4x4 matrices with out any library and to implement the matrix operations by yourself, too.

    See the small example program, which uses PyOpenGL and PyGLM (beside the modules math and ctypes):

    import math 
    import ctypes
    import glm 
    from OpenGL.GLUT import *
    from OpenGL.GL import *
    from OpenGL.GL.shaders import *
    
    class MyWindow:
    
        __caption = 'OpenGL Window'
        __vp_size = [800, 600]
        __vp_valid = False
        __glut_wnd = None
    
        __glsl_vert = """
            #version 450 core
    
            layout (location = 0) in vec3 a_pos;
            layout (location = 1) in vec4 a_col;
    
            out vec4 v_color;
    
            layout (location = 0) uniform mat4 u_proj; 
            layout (location = 1) uniform mat4 u_view; 
            layout (location = 2) uniform mat4 u_model; 
    
            void main()
            {
                v_color     = a_col;
                gl_Position = u_proj * u_view * u_model * vec4(a_pos.xyz, 1.0);
            }
        """
    
        __glsl_frag = """
            #version 450 core
    
            out vec4 frag_color;
            in  vec4 v_color;
    
            void main()
            {
                frag_color = v_color;
            }
        """
    
        __program = None
        __vao = None
        __vbo = None
    
        def __init__(self, w, h):
    
            self.__vp_size = [w, h]
    
            glutInit()
            glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
            glutInitWindowSize(self.__vp_size[0], self.__vp_size[1])
            __glut_wnd = glutCreateWindow(self.__caption)
    
            self.__program = compileProgram( 
                compileShader( self.__glsl_vert, GL_VERTEX_SHADER ),
                compileShader( self.__glsl_frag, GL_FRAGMENT_SHADER ),
            )
    
            attribures = [
            #    x       y    z    R  G  B  A
                -0.866, -0.5, 0,   1, 0, 0, 1, 
                 0.866, -0.5, 0,   1, 1, 0, 1,
                 0,      1.0, 0,   0, 0, 1, 1
            ]
            vertex_attributes = (GLfloat * len(attribures))(*attribures)
            itemsize = ctypes.sizeof(ctypes.c_float)
    
            self.__vbo = glGenBuffers(1)
            glBindBuffer(GL_ARRAY_BUFFER, self.__vbo)
            glBufferData(GL_ARRAY_BUFFER, vertex_attributes, GL_STATIC_DRAW)
    
            self.__vao = glGenVertexArrays(1)
            glBindVertexArray(self.__vao)
            glVertexAttribPointer(0, 3, GL_FLOAT, False, 7*itemsize, None)
            glEnableVertexAttribArray(0)
            glVertexAttribPointer(1, 4, GL_FLOAT, False, 7*itemsize, ctypes.c_void_p(3*itemsize))
            glEnableVertexAttribArray(1)
    
            glUseProgram(self.__program)
    
            glutReshapeFunc(self.__reshape)
            glutDisplayFunc(self.__mainloop)
    
        def run(self):
            self.__starttime = 0
            self.__starttime = self.elapsed_ms()
            glutMainLoop()
    
        def elapsed_ms(self):
          return glutGet(GLUT_ELAPSED_TIME) - self.__starttime
    
        def __reshape(self, w, h):
            self.__vp_valid = False
    
        def __mainloop(self):
    
            if not self.__vp_valid:
                self.__vp_size = [glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT)]
                self.__vp_valid = True
                glViewport(0, 0, self.__vp_size[0], self.__vp_size[1])
    
            proj  = glm.mat4(1)
            view  = glm.mat4(1)
            model = glm.mat4(1)
    
            aspect = self.__vp_size[0]/self.__vp_size[1]
            aspect_x = aspect if self.__vp_size[0] > self.__vp_size[1] else 1.0
            aspect_y = 1/aspect if self.__vp_size[0] < self.__vp_size[1] else 1.0 
            proj = glm.ortho(-aspect_x, aspect_x, -aspect_y, aspect_y, -1.0, 1.0)
    
            angle = self.elapsed_ms() * math.pi * 2 / 3000.0
            model = glm.translate(model, glm.vec3(0.2, 0.2, 0))
            model = glm.rotate(model, angle, glm.vec3(0, 0, 1))
            model = glm.scale(model, glm.vec3(0.5, 0.5, 1))
    
            glUniformMatrix4fv(0, 1, GL_FALSE, glm.value_ptr(proj) )
            glUniformMatrix4fv(1, 1, GL_FALSE, glm.value_ptr(view) )
            glUniformMatrix4fv(2, 1, GL_FALSE, glm.value_ptr(model) )
    
            glClearColor(0.2, 0.3, 0.3, 1.0)
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    
            glDrawArrays(GL_TRIANGLES, 0, 3)
    
            glutSwapBuffers()
            glutPostRedisplay()
    
    
    window = MyWindow(800, 600)
    window.run()