I am confused with how to populate my vertex array for it to be correctly drawn. The OpenGL code that I am using is:
float vertices[size];
//Here I have a method to populate the array with my values from a 2D matrix
glGenVertexArrays(1, &vaoID[0]); // Create our Vertex Array Object
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object so we can use it
glGenBuffers(1, vboID); // Generate our Vertex Buffer Object
glBindBuffer(GL_ARRAY_BUFFER, vboID[0]); // Bind our Vertex Buffer Object
glBufferData(GL_ARRAY_BUFFER, (size) * sizeof(GLfloat), vertices, GL_STATIC_DRAW); // Set the size and data of our VBO and set it to STATIC_DRAW
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); // Set up our vertex attributes pointer
glEnableVertexAttribArray(0); // Disable our Vertex Array Object
glBindVertexArray(0); // Disable our Vertex Buffer Object
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object
glDrawArrays(GL_TRIANGLES, 0, size/3); // Draw
glBindVertexArray(0); // Unbind our Vertex Array Object
Hopefully the image makes this easier to understand. In image 'A' the 3x3 matrix on the left shows what I am currently getting when I draw triangles, the matrix on the right is what I am trying to achieve.
Currently when I create the array of vertices to draw from, I populate it in the order shown in image 'B'. I add values to the array as I work along a row, then step down a column and repeat. So for example:
vertexArray[0] = matrixElement[0].x
vertexArray[1] = matrixElement[0].y
vertexArray[2] = matrixElement[0].z
vertexArray[3] = matrixElement[1].x
vertexArray[4] = matrixElement[1].y
vertexArray[5] = matrixElement[1].z
This order of input into the vertexArray gives results that can be seen in image 'C', where the wrong triangles are created.
My question is: what is the sensible way of populating a vertex array, in an order that is going to create triangles on a large matrix of vertices in a way that looks like the right hand diagram in image 'A'.
If you want to avoid any redundancy, and draw the whole mesh with a single draw call, one option is to use a combination of:
GL_TRIANGLE_STRIP
as the primitive type.The primitive restart feature is needed because you can't easily represent this mesh with a single triangle strip. Using the numbering from your sketch, you can for example describe the topology with two triangle strips using these two index sequences:
0 3 1 4 2 5
3 6 4 7 5 8
Setting up and enabling primitive restart can be done with these calls:
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(0xFFFF);
You can chose the index, but the common policy (and only option supported in OpenGL ES) is to use the largest possible value, which is 0xFFFF if you use GLushort
as the type of the indices.
Once primitive restart is enabled, the "special" index will then start a new triangle strip. So the two triangle strips above can now be given by a single index sequence:
0 3 1 4 2 5 0xFFFF 3 6 4 7 5 8
You should be able to find plenty of examples that show how to set up an index buffer (you can recognize them by their use of GL_ELEMENT_ARRAY_BUFFER
), so I'll skip that part. The draw call is then:
glDrawElements(GL_TRIANGLE_STRIP, 0, 13, GL_UNSIGNED_SHORT, 0);
where 13 is the number of indices used.
There are alternatives to using primitive restart:
Use repeated vertices. This was a common trick before primitive restart was widely available. I wouldn't recommend it anymore. Just for illustration, the index sequence in this case would be:
0 3 1 4 2 5 5 3 3 6 4 7 5 8
The two repeated indices will result in a degenerate (0 pixel) triangle that "connects" the two triangle strips.
glMultiDrawElements()
to draw multiple triangle strips with a single draw call.