Search code examples
c++openglpointersmemory-managementvertex-array

C++ struct memory layout and OpenGL glVertexPointer?


I have following struct to store my vertex data.

struct Rz3DContourNode {
  float x; //pos x
  float y;   //pos y
  float z;  //pos z
  float nx;  //normal x
  float ny;  //normal y
  float nz;  //normal z
};

I store list of vertices in STL vector as follows :

std::vector < Rz3DContourNode >  nodes;

When I try to use this as as vertex-array in OPEGL ,in does not render incorrectly.

glVertexPointer(3, GL_FLOAT, 12, &nodes[0]);
glDrawArrays(GL_POINTS,0,nodes.size());

So, I tried to confirm the values using pointer arithmetic (assuming thats the way OPENGL handle data) as follows:

float *ptr=(float*) &nodes[0];

for(int i=0;i<nodes.size();i++)
{

   Rz3DContourNode confirmNode=nodes[i];  

  float x=*ptr;
    ptr++;

  float y=*ptr;
    ptr++;

  float z=*ptr;
     ptr++;


  //Confirm values !!! Do not equal ??
  qDebug("x=%4.2f  y=%4.2f z=%4.2f  | nx=%4.2f ny=%4.2f nz=%4.2f
        ",confirmNode.x,confirmNode.y,confirmNode.z,x,y,z);



  //Skip normal positions
  ptr++;
  ptr++;
  ptr++;

}

The values does not equal if I directly access values from the struct.

Does this means struct does not save the values contiguously ?

[EDIT] I Just noticed that using sizeof() instead of 12 fix the problem as follows:

glVertexPointer(3, GL_FLOAT, sizeof(Rz3DContourNode), &nodes[0]);

But still I am confused why my hack didnt traverse correctly in memory?(why qDebug doesnt print identical values ?)


Solution

  • sizeof(Rz3DContourNode) == 6*4 = 24 bytes ... not 12!
    

    The stride is the # of bytes between the start of each vertex, not the padding. Although 0 is a special value that indicates tightly packed data.

    So, if you're using 3 floats as vertex data, there's no difference between a stride of 0 and 12 (because 3 floats are 12 bytes). In your case, your struct is 24 bytes, so you should put that.

    This convention (stride = step size, not padding) allows the simple use of sizeof, so you ended up doing the the right thing intuitively. That's good API design for you. :)

    See glVertexPointer docs:

    stride

    Specifies the byte offset between consecutive vertices. If stride is 0, the vertices are understood to be tightly packed in the array. The initial value is 0.