0

I'm in the process of building a graphics app where the user can specify vertices by clicking on a canvas and then the vertices are used to draw polygons.

The app supports line, triangle and polygon modes. Drawing a line and triangle is done by counting the number of clicks. Then vertex arrays are created and data is bound to buffers and rendered using glDrawArrays(). The tricky one is the polygon mode. The user can specify any number of vertices and clicking right mouse button triggers drawing. I initially planned to use glMultiDrawElements, but somehow I wasn't getting any output. So I tried to call glDrawElements() in a loop. still with no luck. I searched a lot and read a lot of documentation about using glDrawElements()/glMultiDrawElements() with VBOs and VAOs and also with glVertexPointer() and glColorPointer. Still no luck.

I have used the following for keeping track of vertex attributes:

GLfloat ** polygonVertices; //every polygon vertex list goes into this..
GLuint * polygonIndicesCounts; //pointer to hold the number of vertices each polygon has
GLuint ** polygonIndices; //array of pointers to hold indices of vertices corresponding to polygons
GLfloat * polygonColors; //for every mouse click, colors are randomly generated.

and the code for rendering:

glVertexPointer(4, GL_FLOAT, 0, (GLvoid*)polygonVertices);
glEnableClientState(GL_VERTEX_ARRAY);

glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_FLOAT, 0, (GLvoid*)polygonColors);

//glMultiDrawElements(GL_POLYGON, polygonIndicesCounts, GL_UNSIGNED_INT, polygonIndices, polygonCount);

for(int i = 0 ; i < polygonCount; i ++)
    glDrawElements(GL_POLYGON, polygonIndicesCounts[i], GL_UNSIGNED_INT, polygonIndices[i]);
Shantha Kumara
  • 2,679
  • 3
  • 32
  • 48

1 Answers1

1

Why are polygonVertices pointers to pointers? If you cast that to (void*) the only thing OpenGL sees is the value of pointer to which each points. You want those to be flat a array, so their type signature should be compatible with float* (not float**). A pointer to a pointer makes sense only for the glMultiDrawArrays call.

datenwolf
  • 149,702
  • 12
  • 167
  • 273
  • Hi datenwolf, the ** version works. I didn't have to flatten it. The following worked: `GLfloat vertices[4][3] = { {0.2f, 0.2f, 0.0f}, {-0.2f, 0.2f, 0.0f}, {0.2f, -0.2f, 0.0f}, {-0.2f, -0.2f, 0.0f} }; GLfloat colors[12] = { 0.32f, 0.92f, 0.30f, 0.32f, 0.12f, 0.50f, 0.82f, 0.42f, 0.80f, 0.52f, 0.72f, 0.10f }; GLuint indices []= {0, 1, 3, 2}; glEnableClientState(GL_VERTEX_ARRAY);glVertexPointer(3, GL_FLOAT, 0, vertices); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, colors); glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_INT, indices);` – Ankur Huralikoppi Sep 09 '13 at 20:00
  • @AnkurHuralikoppi: This particular version works, because you're allocating an multidimensional array in automatic memory. The C language standard specifies, that in this particular situation all the elements in the multidimensional array *must* be contiguous. However the `**` is still wrong. Because what happens if you do this: `GLfloat **a2 = malloc(sizeof(float*)*4); for(int i=0; i<4; i++) a2[i] = malloc(sizeof(float)*3);`. In that case if you passed `*a2` to OpenGL, all OpenGL sees in only the very first (i=0) block of 3 floats allocated, but the rest will be somewhere else. – datenwolf Sep 09 '13 at 20:09
  • 1
    @AnkurHuralikoppi: To make a long story short: **NEVER** use pointers to pointers to pointers to … for multidimensional data. **ALWAYS** allocate a flat buffer of `malloc(width * height * depth * …);` (or equivalent `new`) and address with `[… + width*height*z + width*y + x]`. Everything else is madness. Also very inefficient, because each and every pointer level introduces a costly indirection that's hard on the cache. – datenwolf Sep 09 '13 at 20:12
  • I flattened the arrays and then copied the indices in GL_ELEMENT_ARRAY_BUFFER and then used index offsets. That solved the problem! – Ankur Huralikoppi Sep 18 '13 at 17:38