'Constructs VBO and prepares vertex attribute bindings. OpenGL context must be up already (initializeGL
has been called).
:param data: Data array (vertices) to be sent to the GPU.
:type numpy.array
:param format_description: Describes vertex attribute bindings. This parameter must be an iterable
of tuples. Each tuple specifies a generic vertex attribute (the order is important!) by specifying
the number of components (must be 1,2,3 or 4) and data type (e.g. GL_FLOAT, GL_INT). See the example
above. Normalization for fixed-point values is turned off.
:type an iterable of tuples
:param usage: Specifies the expected usage pattern. The symbolic constant must be GL_STREAM_DRAW,
GL_STREAM_READ, GL_STREAM_COPY, GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY,
GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, or GL_DYNAMIC_COPY. Default is GL_STATIC_DRAW.
:type GLenum'

def __init__(self, data, format_description, usage=GL_STATIC_DRAW):

    self._format_description = format_description
    if glGenVertexArrays:
        self._vao = GLuint(42)
        glGenVertexArrays(1, self._vao)
        glBindVertexArray(self._vao)
        vertex_buffer_id = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id)
        glBufferData(GL_ARRAY_BUFFER, data, usage)
        vertex_size = sum(((attribute[0] * 4) for attribute in format_description))
        self._num_vertices = (len(data) / (vertex_size / 4))
        current_size = 0
        for (i, (num_components, type)) in enumerate(format_description):
            glVertexAttribPointer(i, num_components, type, GL_FALSE, vertex_size, c_void_p(current_size))
            glEnableVertexAttribArray(i)
            current_size += (num_components * 4)
        glBindVertexArray(0)
        glBindBuffer(GL_ARRAY_BUFFER, 0)
    else:
        self._vbo_id = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, self._vbo_id)
        glBufferData(GL_ARRAY_BUFFER, data, usage)
        self._data_length = len(data)
        glBindBuffer(GL_ARRAY_BUFFER, 0)
