c++openglsurfacecubes

Indicies, glDrawElements and/or other methods of drawing big vertex arrays


I am trying to display an isosurface, built using a marching cubes algorithm, which, I suppose, produces a set of triangles. I a complete amateur in graphics programming, however, and I am struggling with understanding the few methods of effectively drawing them.

What I had in mind is to draw it all in a one call using something like glVertexPointer-glDrawElement construction. The latter, though, requires me to know the indices, and I clearly do not know them. Furthermore, I am actually not exactly sure of their purpose: I think that they are a merely a, duh, indexes, the order in which the driver will use them and also a way to save up memory by excluding the same vertex appearing multiple times.

So, is my vision of indices' purpose correct and what is the correct way to solve my problem?


Solution

  • If you don't have a need for indices, then... don't use indices! Yes, they can be used to make rendering more efficient if the same vertex is used multiple times. But they are entirely optional.

    The draw call you use when rendering without indices is glDrawArrays(). This will use the vertices in your vertex buffer in their natural order, based on the primitive type passed to the draw call. For example, with GL_TRIANGLES, it will draw a triangle with vertices at positions (0, 1, 2) in the buffer, a triangle with vertices (3, 4, 5), etc.

    So in your isosurface algorithm, you can simply calculate the 3 vertices every time you generate a triangle, and append them to a list of vertices you end up storing in the vertex buffer. Then draw the whole thing with glDrawArrays(GL_TRIANGLES, ...), and that's all there is.

    Now, in a mesh that covers a surface, the same vertex is shared by an average of approximately 6 triangles (look at a regular mesh to see how this number is derived). So if you generate the vertices separately for each triangle, you'll have the same vertex approximately 6 times, resulting in a substantial amount of unnecessary memory use, and time for vertex processing.

    This is where indices come in. One approach you can use is that, for each edge of the grid, you track if an isosurface vertex on the edge was already created, and store its index if it was. Then, anytime you need a vertex for a grid edge while generating your triangles, you create a new vertex (with a new index) if the edge does not have a vertex yet, or use the index of the already created vertex. Then you store the resulting index sequence in an index buffer, and draw with glDrawElements(GL_TRIANGLES, ...).

    A minor variation of the above is that you loop over all mesh edges first, calculate all vertices for edges that intersect the isosurface, and again store the vertex index for each of those edges. Then, when you iterate over the mesh cubes to generate the triangles, you can simply grab the vertex index from each of its intersecting edges.