Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to draw middle portion of vertex array



  • I have a small application that draws information from a file. The data is dynamically loaded and may vary in size or content depending on what file is read. I had previously been loading this data into a QGLBuffer, which I would bind before drawing. While this provides pretty good performance, I have run into a lot of compatibility issues with older video cards that do not support this. Because of that, I want to offer a fallback method that uses simple vertex arrays instead of VBOs. So some example code might look like this:

    Binding the initial QGLBuffer (the vertices array is a std::vector<QVector3D> that is built while parsing the file)
    @ qglbuffer = new QGLBuffer(QGLBuffer::VertexBuffer);
    if (qglbuffer->create())
    {
    if (qglbuffer->bind())
    {
    qglbuffer->setUsagePattern(QGLBuffer::StaticDraw);
    qglbuffer->allocate(vertices.data(), sizeof(QVector3D)*vertices.size());
    qglbuffer->release();
    }
    }@

    Drawing loop
    @ if (qglbuffer->bind())
    {
    glVertexPointer(3, GL_FLOAT, 0, (GLvoid*)NULL);
    glDrawArrays(GL_LINES, 0, vertices.size());
    qglbuffer->release();
    }
    else
    {
    glVertexPointer(3, GL_FLOAT, 0, vertices.data());
    glDrawArrays(GL_LINES, 0, vertices.size());
    }@

    So the idea is that if the QGLBuffer fails to bind then it resorts to the vertex array methods. This works fine as long as I want to draw the entire vertex array, but I have had a very difficult time figuring out how to draw only a portion of this array. I have one case where I use both a vertices array and an indices array along with glDrawElements(). This works fine with the QGLBuffer method since I can just supply the appropriate offset and then limit the element count to constrain the information that is drawn (see below).

    @ bool buffer1success = vertexBuffer->bind();
    glVertexPointer(3, GL_FLOAT, 0, (GLvoid*)NULL);
    bool buffer2success = indicesBuffer->bind()
    if ((buffer1success == true) && (buffer2success == true))
    {
    glDrawElements(GL_TRIANGLES, endCount-startCount, GL_UNSIGNED_INT, (GLvoid*)(startCount*sizeof(GLuint)));
    indicesBuffer->release();
    verticesBuffer->release();
    }
    else
    {
    // can't figure out what to do here???
    }@

    In this case I only want to draw the data between startCount and endCount, not the entire array. My problem is that I cannot figure out an equivalent method that will work with simple vertex arrays. Everything I have come across requires some form of buffer binding or extremely slow glBegin/glEnd calls.

    Does anyone know of a good way to do something equivalent to QGBuffer/glDrawElements( , count, , offset) but only using simple vertex arrays?

    Any help would be greatly appreciated!

    Thanks in advance



  • From what I have read, I only have 2 options for drawing indexed vertex arrays: glDrawElements() and glDrawRangeElements(). The latter requires knowledge of the min and max index that is referenced for a specific range of vertices, but this would be costly to compute for my circumstances. So that makes me think all I am left with is glDrawElements(), but for a vertex array and not a VBO. Please correct me if I am wrong.

    So here is what I have been trying
    @ glVertexPointer(3, GL_FLOAT, 0, vertices.data());
    glDrawElements(GL_TRIANGLES, endCount-startCount, GL_UNSIGNED_INT, indices + startCount*sizeof(GLuint));@

    But this will not compile. The indices array is a std::vector<GLuint>, which I think might be part of my problem. Is was dynamically allocated and is not just a simple predefined array like
    @GLuint indices[20] = { .... };@

    So how can I make glDrawElements work with a std::vector<GLuint> array of indices?


  • Lifetime Qt Champion

    Hi,

    If you are using C++11 the vector has now a data function otherwise, you can use Qt's QVector

    Hope it helps


Log in to reply