'Renders primitives from data array. By default it renders triangles using all the data. Consult
OpenGL documentation (specifically ``glDrawArrays``) for detail info.
:param primitives: What kind of primitives to render. Symbolic constants GL_POINTS, GL_LINE_STRIP,
GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_QUAD_STRIP,
GL_QUADS, and GL_POLYGON are accepted.
:type GLenum
:param first: Specifies the starting index into data.
:type int
:param count: The number of indices (not primitives) to be rendered.
:type int'

def draw(self, primitives=GL_TRIANGLES, first=0, count=(-1)):

    if hasattr(self, '_vao'):
        glBindVertexArray(self._vao)
        glDrawArrays(primitives, first, (count if (count != (-1)) else (self._num_vertices - first)))
        glBindVertexArray(0)
    else:
        glBindBuffer(GL_ARRAY_BUFFER, self._vbo_id)
        vertex_size = sum(((attribute[0] * 4) for attribute in self._format_description))
        current_size = 0
        for (i, (num_components, type)) in enumerate(self._format_description):
            glVertexAttribPointer(i, num_components, type, GL_FALSE, vertex_size, c_void_p(current_size))
            glEnableVertexAttribArray(i)
            current_size += (num_components * 4)
        glDrawArrays(primitives, first, (count if (count != (-1)) else ((self._data_length / (vertex_size / 4)) - first)))
        for i in range(len(self._format_description)):
            glDisableVertexAttribArray(i)
        glBindBuffer(GL_ARRAY_BUFFER, 0)
