Jump to content
  • Advertisement
Sign in to follow this  
Alessandro

Clarification about GL_LINE_STRIP and Vertex Arrays

This topic is 2494 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I need to render a bunch of GL_LINE_STRIP primitives and the render function looks like this:


glPushMatrix();
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer(3, GL_FLOAT, 0, verts);
glDrawElements( GL_LINE_STRIP, numIndices, GL_UNSIGNED_INT, indices );
glDisableClientState( GL_VERTEX_ARRAY );
glPopMatrix();


I already packed the verts array, and I'm a bit confused about the indices assignment.

The number of indices is actually equal to (number of line strips), or to the (number of line strips * number of line segments) ?

Share this post


Link to post
Share on other sites
Advertisement
The number of indices is just what it says; the number of indices to draw. If you have an index array that contains four indices that makes up your line strip, then the parameter is four. The parameter has exactly the same meaning for any type of primitive you can draw.

Share this post


Link to post
Share on other sites
Say you have N line strips, each with V number of vertices.

The number of indices should be N*V (since a line strip draws a connected group of line segments from the first vertex to the last), correct?

[s]But how glDrawElements understand where a line strip ends and a new one begins?[/s]

I think I found out that I can't call a unique glDrawElements to draw all the line strips at once. I will have to use glMultiDrawElements.

Here is an example I found:


static GLubyte oneIndices[] = {0, 1, 2, 3, 4, 5, 6};
static GLubyte twoIndices[] = {7, 1, 8, 9, 10, 11};
static GLsizei count[] = {7, 6};
static GLvoid * indices[2] = {oneIndices, twoIndices};
glMultiDrawElements(GL_LINE_STRIP, count, GL_UNSIGNED_BYTE,indices, 2);


I wonder how I'd define the indices[] array in case I have one global array of indices, since the element count it's always the same (in the example they use two separate indices and they have a different number of elements).

Share this post


Link to post
Share on other sites
You just put pointers to the parts of the global index array you want to draw from in the indices array instead of pointers to two different arrays.
[source]
static GLvoid *indices[] = {globalindices, globalindices+10, globalindices+42};
[/source]

Share this post


Link to post
Share on other sites
Thanks Bob, will try that. I was just playing (that's the correct term) with glDrawRangeElements: obviously this stuff is rocket science for me.

The following call correctly draw 6 points:


glDrawRangeElements( GL_POINTS, 0, 5, 6, GL_UNSIGNED_INT, indices );


Now, (newbie thought) that is supposed to be equivalent:

glDrawRangeElements( GL_POINTS, 0, 2, 3, GL_UNSIGNED_INT, indices );
glDrawRangeElements( GL_POINTS, 3, 5, 3, GL_UNSIGNED_INT, indices );


I mean, I just make two "partial" calls, correctly passing the proper indicies. Instead, to my surprise, glDrawRangeElements( GL_POINTS, 3, 5, 3, GL_UNSIGNED_INT, indices ); it just matches with the glDrawRangeElements( GL_POINTS, 0, 2, 3, GL_UNSIGNED_INT, indices ); Only the first 3 points are drawn...

How is that possible, since I specified different indicies? wacko.png blink.png huh.png

Share this post


Link to post
Share on other sites
If you want the third line to draw the second half, then you have to point the index array to the second half as well.
[source]
glDrawRangeElements( GL_POINTS, 3, 5, 3, GL_UNSIGNED_INT, indices+3 )
[/source]
Otherwise you're drawing the same thee vertices twice.

The pointer and the number of indices to draw exclusively determine what values to read from the index array. The range-parameters are not what sub-part of the index array to draw, but what values OpenGL can expect when reading the index array. In the third call, 3 and 5 does not mean "draw between indices 3 and 5", it means "when reading index values pointed to by the pointer, the index values are expected to be between 3 and 5".

Share this post


Link to post
Share on other sites
Bob thank you for the explanation, I now understood what I was doing wrong. glDrawRangeElements now works fine in my application, and they are much faster than glDrawArrays and also glDrawElements. Tomorrow I'll try to use glDrawRangeElements with VBO's: shouldn't be too difficult now that arrays are setup properly.

About the glMultiDrawElements, I was wondering if there is a way to actually assign indices dinamically, so that instead of


static GLvoid *indices[] = {globalindices, globalindices+10, globalindices+42};


one could do something like this:

static GLvoid **indices;
indices[0]=globalIndices;
indices[1]=globalIndices+10;
indices[2]=globalIndices+20;


Thanks again for the precious help and patience. My mind is more oriented to arts and painting, but mathematics and 3D graphics, even if I'm such a rookie at those, they do fascinate me (and scare sometimes unsure.png rolleyes.gif biggrin.png ) ...

Share this post


Link to post
Share on other sites
Use a dynamic container.
[source]
std::vector<void *> indices;

indices.push_back(globalindices);
...
[/source]
Then pass a pointer to the first element to OpenGL:
[source]
glMultiDrawElements(... , &indices[0], indices.size());
[/source]

Share this post


Link to post
Share on other sites
Ok, here is the working code I came up thanks to Bob hints, which renders a bunch of GL_LINE_STRIP primitives using glMultiDrawElements. Maybe someone can find it useful...


// declare stuff
unsigned int *indices; // this array holds all the line strips indices
vector3_t *verts; // this array holds all the line strips vertices
int *globalIndexCount;
std::vector<void *> globalIndices; // this is a pointer to the *indices above

void setup()
{
/* ... fill verts and indices with data ... */

globalIndexCount=new int[NUM_OF_STRIPS];
for (int i=0; i<NUM_OF_STRIPS; i++)
{
globalIndexCount=POINTS_PER_STRIP; // store number of points for a line strip
globalIndices.push_back(indices+i*POINTS_PER_STRIP); // store the reference to a indices data set
}
}

void render()
{
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer(3, GL_FLOAT, 0, verts);
glPushMatrix();
glMultiDrawElements(GL_LINE_STRIP, globalIndexCount, GL_UNSIGNED_INT, (const void **) &globalIndices[0], globalIndices.size() );
glPopMatrix();
glDisableClientState( GL_VERTEX_ARRAY );
}



Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!