Search code examples
pythonopenglglfwpyopengltexturing

Sending a pointer to glVertexAttributePointer in Pyrthon


I need to pass an offset pointer to glVertexAttribPointer in Python. Currently I have coming out of pythons console window when an instance of Box class is created:

C:\Users\phill\PycharmProjects\texturebox\venv\Scripts\python.exe C:\Users\phill\PycharmProjects\texturebox\main.py 
Traceback (most recent call last):
File "C:\Users\phill\PycharmProjects\texturebox\main.py", line 29, in <module>
main()
File "C:\Users\phill\PycharmProjects\texturebox\main.py", line 18, in main
m_box = Box()
        ^^^^^
File "C:\Users\phill\PycharmProjects\texturebox\Box.py", line 60, in __init__
array_colors_offset(*vertices_list)
IndexError: invalid index

Process finished with exit code 1

Does anyone know how an offset pointer might be passed in Python?

The corresponding C code for the (void *) looks like this:

// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

Box.py:

from OpenGL import GL as GL
import ctypes


class Box:
    def __init__(self):
        #3 floats for vertices x,y,z 3 floats for color R G B 2 floats for tex co-ords
        vertices_list = [
            0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0,
            0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0,
            -0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
            -0.5, 0.5, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0
        ]

        indices_list = [
            0, 1, 3,
            1, 2, 3
        ]

        self.EBO = None
        self.VBO = None
        self.VAO = None

        self.VAO = GL.glGenVertexArrays(1)

        self.VBO = GL.glGenBuffers(1)
        self.EBO = GL.glGenBuffers(1)

        GL.glBindVertexArray(self.VAO)

        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.VBO)
        array_type_vertices = (GL.GLfloat * len(vertices_list))
        GL.glBufferData(GL.GL_ARRAY_BUFFER, len(vertices_list) * ctypes.sizeof(ctypes.c_float),
                        array_type_vertices(*vertices_list), GL.GL_STATIC_DRAW)

        GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, self.EBO)
        array_type_indices = (GL.GLint * len(indices_list))
        GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, len(indices_list) * ctypes.sizeof(ctypes.c_ulong),
                        array_type_indices(*indices_list), GL.GL_STATIC_DRAW)

        GL.glVertexAttribPointer(
            0,
            3,
            GL.GL_FLOAT,
            False,
            8 * ctypes.sizeof(ctypes.c_float),
            None
        )

        GL.glEnableVertexAttribArray(0)


        # attempting to pass the pointer
        array_colors_offset = (GL.GLfloat * 3)
        GL.glVertexAttribPointer(1,
                                 3,
                                 GL.GL_FLOAT,
                                 False,
                                 8 * ctypes.sizeof(ctypes.c_float),
                                 array_colors_offset(*vertices_list)
                                 )
        GL.glEnableVertexAttribArray(1)

        array_tex_offset = (GL.GLfloat * 6)
        GL.glVertexAttribPointer(2,
                                 2,
                                 GL.GL_FLOAT,
                                 GL.GL_FALSE,
                                 8 * ctypes.sizeof(ctypes.c_float),
                                 array_tex_offset(*vertices_list)
                                  )

        print("Box()")
        
        

So I started with code from gitlabs opengl python examples. The basic triangle does not seem to enumerate how to pass a pointer to glVertexAtribPointer. So there is an offset to pass as a (void *) according to the C code I have that I am moving over into Python.


Solution

  • (GL.GLfloat * 6)(*vertices_list) does not do what you expect. It creates an array with 6 elements.

    See pyopengl, glVertexAttribPointer. The argument must be a void pointer. You can use the ctypes.c_void_p to create a void pointer, e.g.:

    GL.glVertexAttribPointer(1,
                             3,
                             GL.GL_FLOAT,
                             False,
                             8 * ctypes.sizeof(ctypes.c_float),
                             ctypes.c_void_p(3 * ctypes.sizeof(ctypes.c_float))
                             )