Jump to content

  • Log In with Google      Sign In   
  • Create Account

Clarification about GL_LINE_STRIP and Vertex Arrays


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
10 replies to this topic

#1 Alessandro   Members   -  Reputation: 296

Like
0Likes
Like

Posted 09 February 2012 - 12:46 PM

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) ?

Sponsor:

#2 Brother Bob   Moderators   -  Reputation: 8631

Like
1Likes
Like

Posted 09 February 2012 - 01:05 PM

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.

#3 V-man   Members   -  Reputation: 805

Like
1Likes
Like

Posted 09 February 2012 - 02:33 PM

The number of indices is number of strips + 1
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);

#4 Alessandro   Members   -  Reputation: 296

Like
0Likes
Like

Posted 09 February 2012 - 03:06 PM

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?

But how glDrawElements understand where a line strip ends and a new one begins?

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).

#5 Brother Bob   Moderators   -  Reputation: 8631

Like
2Likes
Like

Posted 09 February 2012 - 04:39 PM

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.
static GLvoid *indices[] = {globalindices, globalindices+10, globalindices+42};


#6 Alessandro   Members   -  Reputation: 296

Like
0Likes
Like

Posted 09 February 2012 - 04:46 PM

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? Posted Image Posted Image Posted Image

#7 Brother Bob   Moderators   -  Reputation: 8631

Like
1Likes
Like

Posted 09 February 2012 - 05:05 PM

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.

glDrawRangeElements( GL_POINTS, 3, 5, 3, GL_UNSIGNED_INT, indices+3 )


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".

#8 Alessandro   Members   -  Reputation: 296

Like
0Likes
Like

Posted 09 February 2012 - 06:19 PM

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 Posted Image Posted Image Posted Image ) ...

#9 Brother Bob   Moderators   -  Reputation: 8631

Like
1Likes
Like

Posted 10 February 2012 - 03:34 AM

Use a dynamic container.

std::vector<void *> indices;



indices.push_back(globalindices);

...


Then pass a pointer to the first element to OpenGL:

glMultiDrawElements(... , &indices[0], indices.size());



#10 Alessandro   Members   -  Reputation: 296

Like
0Likes
Like

Posted 10 February 2012 - 05:53 AM

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[i]=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 );   
}





#11 Alessandro   Members   -  Reputation: 296

Like
0Likes
Like

Posted 10 February 2012 - 06:00 AM

Hey, not finished yet: how about glMultiDrawElements + VBO's? Posted Image

I think I've setup correctly the buffers, but I can't figure out how the glMultiDrawElements render call should look like:

void initGL()
{
...
glGenBuffersARB(1, &vboId);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, fullHairCounter*HAIRPOINTS*sizeof(vector3_t), verts, GL_DYNAMIC_DRAW_ARB);	  
glGenBuffersARB(1, &iboId);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, iboId);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, numIndices*sizeof(unsigned int), indices, GL_DYNAMIC_DRAW_ARB);
...
}

void setupVBO()
{
...
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, fullHairCounter*HAIRPOINTS*sizeof(vector3_t), verts, GL_DYNAMIC_DRAW_ARB);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, iboId);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, globalIndices.size() *sizeof(unsigned int), (const void **) &globalIndices[0], GL_DYNAMIC_DRAW_ARB);
...
}

void renderVBO()
{
glPushMatrix();
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, iboId);
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer(3, GL_FLOAT, 0, 0);
glMultiDrawElements(GL_LINE_STRIP, globalIndexCount, GL_UNSIGNED_INT,  0, globalIndices.size() ); // this is clearly wrong: I don't understand how to reference data to be passed to the glMultiDrawElements...
glDisableClientState( GL_VERTEX_ARRAY );  
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glPopMatrix();
}






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS