PDA

View Full Version : How to draw middle portion of vertex array



techstak
10-12-2013, 02:08 PM
I have a small Qt/OpenGL 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

techstak
10-13-2013, 03:53 AM
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?

GClements
10-13-2013, 04:22 AM
So how can I make glDrawElements work with a std::vector<GLuint> array of indices?



glDrawElements(GL_TRIANGLES, endCount-startCount, GL_UNSIGNED_INT, &indices[startCount]);