# stride with vertex arrays

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

## Recommended Posts

Little confused about stride in the gl*Pointer functions.
Quote:
  void glNormalPointer( GLenum type, GLsizei stride, const GLvoid *pointer ) PARAMETERS stride Specifies the byte offset between consecutive normals. If stride is 0- the initial value-the normals are understood to be tightly packed in the array. 
So, if I had a class with data members like so:
class CVertex3d
{
CVector3d point;
CVector3d normal;
float u,v;
}

class CVector3d
{
float x,y,z;
}


Would the stride be
 sizeof(CVertex3d) - sizeof(CVector3d)
something like this?

##### Share on other sites
If your vertex array looked like

[vx vy vz][nx ny nz][vx vy vz][nx ...]

v for vertex and n for normal then the stride would be 3 floats (12 bytes). There are 3 vertex values (xyz) in between every normal value.

so sizeof(CVertex3d) in your case, sizeof(CVertex3d) - sizeof(CVertex3d) is 0 :p

HTH

EDIT: didn't see the uv in there, works the same way tho (5 floats instead of 3 in between the consecutive normal values) :)

##### Share on other sites
Okay, I still don't understand.

The stride is the number of bytes between each set of normal values.

So, if we had it like your example, nts, then is the stride 12 bytes?

If, so, then for me, the stride would be 20 bytes, right?

##### Share on other sites
like nts said
float verts_and_norms[] = {1,1,1, 1,0,0, 2,2,2, 1,0,0}; // first 3 nums are vert next 3 norm next 3 vert + next 3 norm
thus the stride is 3*sizeof(float)

the other method is having two seperate arrays
float verts[] = {1,1,1, 2,2,2};
float norms[] = {1,0,0, 1,0,0};

##### Share on other sites
Okay, thanks guys, I've gotten that part straightened out, but I have another problem. My function "drawIndexedTriangleList", which should be working with gl*Pointer functions and glDrawElements isn't working.

// basic classesclass CVertex3d{public:	CVector3d point;	CVector3d normal;	float u, v;			CColor color;};class CVector3d{public:	float	x,y,z;};class CColor{private:	unsigned int color;};

	CVertex3d arr[4]; 	// in constructor params, pos is first, then normal, color, then u,v	arr[0] = CVertex3d( CVector3d(25.0f,  25.0f, 0.0f), CVector3d(1.0f, 0.0f, 0.0f), CColor(1.0f,1.0f,1.0f,1.0f), 0.0f, 0.0f);	arr[1] = CVertex3d( CVector3d(25.0f, -25.0f, 0.0f), CVector3d(1.0f, 0.0f, 0.0f), CColor(1.0f,1.0f,1.0f,1.0f), 0.0f, 0.0f);	arr[2] = CVertex3d( CVector3d(-25.0f,-25.0f, 0.0f), CVector3d(1.0f, 0.0f, 0.0f), CColor(1.0f,1.0f,1.0f,1.0f), 0.0f, 0.0f);	arr[3] = CVertex3d( CVector3d(-25.0f, 25.0f, 0.0f), CVector3d(1.0f, 0.0f, 0.0f), CColor(1.0f,1.0f,1.0f,1.0f), 0.0f, 0.0f);	unsigned int index[6] = {0,1,2, 3,0,2};	while( engine.run() ){		driver->beginScene();	// clears the window with glClear		glTranslatef(0.0f, 0.0f, -5.0f);		driver->drawIndexedTriangleList(arr, 4, index, 6/3);		driver->endScene();// actually renders the window (SwapBuffer)	}

void COpenGLDriver::drawIndexedTriangleList(const scene::CVertex3d* v, unsigned int vertex_count,          const unsigned int* index_list, unsigned int index_size){	util::array<unsigned char> color_buffer;	// Enable the use of vertex arrays	glEnableClientState(GL_COLOR_ARRAY);	glEnableClientState(GL_VERTEX_ARRAY);	glEnableClientState(GL_TEXTURE_COORD_ARRAY );	glEnableClientState(GL_NORMAL_ARRAY );	// convert colors into a format OGL understands (from a single int, to a series of chars)	color_buffer.resize(vertex_count);	for(int i=0; i < vertex_count; i+=4){		color_buffer = v[i/4].color.getRed();		color_buffer[i+1] = v[i/4].color.getGreen();		color_buffer[i+2] = v[i/4].color.getBlue();		color_buffer[i+3] = v[i/4].color.getAlpha();	}	// define arrays to use	glColorPointer(4, GL_UNSIGNED_BYTE, 0, color_buffer.getPtr() );	glNormalPointer(GL_FLOAT, sizeof(scene::CVertex3d) - sizeof(util::CVector3d), &v[0].normal );	glTexCoordPointer(2, GL_FLOAT, sizeof(scene::CVertex3d) - (sizeof(float)*2), &v[0].u );	glVertexPointer(3, GL_FLOAT, sizeof(scene::CVertex3d) - sizeof(util::CVector3d), &v[0].point );	glDrawElements(GL_TRIANGLES, vertex_count, GL_UNSIGNED_INT, index_list);	// draw all four arrays	glFlush();	// flush the pipeline}

I'm a little unsure about the 'vertex_count' in the glDrawElements.

And, we can assume that the rest of the OGL code is working, because 10 minutes ago I was looking at a rotating quad, drawn using glBegin() and glEnd().

So, can anyone tell if its a problem with my code? (my thinking) Or the values I gave the vertices?

##### Share on other sites
The stride is the number of bytes between the start of one entry in the vertex array to the start of the next entry. That is, how many bytes you must move in memory to get the next following entry. So the stride in your case should be sizeof(CVertex3d).

And the vertex_count should actually be called index_count, as that parameter tells glDrawElements how many indices that index pointer contains (or rather, how many of them should be drawn, of course), which is 6 in your case.

##### Share on other sites
Quote:
 Original post by Brother BobThe stride is the number of bytes between the start of one entry in the vertex array to the start of the next entry. That is, how many bytes you must move in memory to get the next following entry. So the stride in your case should be sizeof(CVertex3d).

Quoted for being the right answer. The fact that you can specify zero as the stride for tightly packed arrays seems to throw people off. Zero is a special case which instructs the GL to calculate the stride for itself (since it has enough information to do so).

Enigma

##### Share on other sites
Hmmm, now I can see the 2 triangles being drawn, but they rapidly move along the z axis into the screen until they disappear (probably because they pass the far clipping distance). This confuses me, because as far as I can tell, I'm not changing the vertices at all. The basic classes are still the same, but here is the code that changed:

	while( engine.run() ){				driver->beginScene();	// clears the window with glClear		glTranslatef(0.0f, 0.0f, -5.0f);			driver->drawIndexedTriangleList(arr, 4, index, 6);		driver->endScene();	// actually renders the window	}

void COpenGLDriver::drawIndexedTriangleList(const scene::CVertex3d* v, unsigned int vertex_count,         const unsigned int* index_list, unsigned int index_size){	util::array<unsigned char> color_buffer;	// temporarily holds the colors in float format, which OGL understands	// Enable the use of vertex arrays	glEnableClientState(GL_COLOR_ARRAY);	glEnableClientState(GL_VERTEX_ARRAY);	glEnableClientState(GL_TEXTURE_COORD_ARRAY );	glEnableClientState(GL_NORMAL_ARRAY );	// convert colors into a format OGL understands (from a single int, to a series of chars)	color_buffer.resize(vertex_count);	for(int i=0; i < vertex_count; i+=4){		color_buffer = v[i/4].color.getRed();		color_buffer[i+1] = v[i/4].color.getGreen();		color_buffer[i+2] = v[i/4].color.getBlue();		color_buffer[i+3] = v[i/4].color.getAlpha();	}	// define arrays to use	/* http://www.gamedev.net/community/forums/viewreply.asp?ID=2242450	 * The stride is the number of bytes between the start of one entry in the 	 * vertex array to the start of the next entry. That is, how many bytes you 	 * must move in memory to get the next following entry. So the stride in your 	 * case should be sizeof(CVertex3d).	 */	glColorPointer(4, GL_UNSIGNED_BYTE, 0, color_buffer.getPtr() );	glNormalPointer(GL_FLOAT, sizeof(scene::CVertex3d), &v[0].normal );	glTexCoordPointer(2, GL_FLOAT, sizeof(scene::CVertex3d), &v[0].u );	glVertexPointer(3, GL_FLOAT, sizeof(scene::CVertex3d), &v[0].point );	glDrawElements(GL_TRIANGLES, index_size, GL_UNSIGNED_INT, index_list);	// draw all four arrays	glFlush();	// flush the pipeline}

##### Share on other sites
You call glTranslate before rendering, so unless you reset the matrix somewhere else between the frames, translations will accumulate and increase the rendering distance by 5 for each frame, eventually reaching the far clip plane.

##### Share on other sites
Quote:
 Original post by zedzeeklike nts saidfloat verts_and_norms[] = {1,1,1, 1,0,0, 2,2,2, 1,0,0}; // first 3 nums are vert next 3 norm next 3 vert + next 3 normthus the stride is 3*sizeof(float)

Oh la la. Shame on you. The correct stride is 6 floats, not 3. I don't know for nts, but since i know you're an experienced GL programmer, you should have noticed that :) And for the OP, the stride you should sizeof(CVertex3d), or 8 floats.

Y.

##### Share on other sites
Quote:
 Original post by Brother BobYou call glTranslate before rendering, so unless you reset the matrix somewhere else between the frames, translations will accumulate and increase the rendering distance by 5 for each frame, eventually reaching the far clip plane.

Okay, looks like someone (me) is not paying 100% attention to what he is coding!

Thanks guys.

##### Share on other sites
Quote:
 Oh la la. Shame on you. The correct stride is 6 floats, not 3. I don't know for nts, but since i know you're an experienced GL programmer

youre correct, and to make matter worse i was doing tests on exactly this yesterday :) (mucking around with adding VBO to my engine).
in my defence i was using sizeof(..)

##### Share on other sites
Just a note on performance of stride:

It will be more efficient to put your vertices with data interleaved at strides of 32 bytes or 64 bytes. And this is because on contemporary hardware, the vertex cache-line size is 32 bytes.

There was some talk about this by Richard Huddy from ATI in the presentations at GDC 2005. Definitely worth a look when they discuss little tidbits like this.

edit: this advice also extends to Nvidia hardware by the way. (One of the presentations by Richard Huddy was a joint ATI/Nvidia effort).

[Edited by - FReY on September 5, 2005 7:05:35 AM]