How can I iterate a buffer with a stride? For example, I saved the pointer to a vertex buffer for later use. I've got the stride, the pointer, and triangle count for vertices. I want to iterate my pointer using this info to get the vertices. I'm doing it wrong right now because it doesn't display all of them.

Anyone have any idea how I can use this information to get each vertex?

struct BufferObject
{
    GLint ID;
    GLsizei Size;
    GLboolean Reserved;
    GLenum Type, Usage;
    const GLvoid* BufferPointer;
};

BufferObject CurrentBuffer;
std::vector ListOfBuffers;

GL_EXPORT __stdcall void GLHook_glBindBufferARB(GLenum target, GLuint buffer)
{
    BufferBound = true;
    CurrentBuffer.Type = target;
    CurrentBuffer.ID = buffer;

    (*optr_glBindBufferARB) (target, buffer);
}

GL_EXPORT __stdcall void GLHook_glBufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage)
{
    if (BufferBound)
    {
        BufferBound = false;
        CurrentBuffer.Size = size;
        CurrentBuffer.Usage = usage;
        CurrentBuffer.BufferPointer = data;
        ListOfBuffers.push_back(CurrentBuffer);
    }
    (*optr_glBufferDataARB) (target,  size, data, usage);
}

void IterateModelVertices()
{
        for (size_t I = 0; I < ListOfBuffers.size(); I++)
        {
            if (ListOfBuffers[I].ID == CurrentBuffer.ID)
            {
                const GLfloat* Ptr = static_cast(ListOfBuffers[I].BufferPointer);

                for (int J = 0; J < ModelPtr->TriangleCount; J++)
                {
                    Not sure if I'm using it correctly though.
                    ModelPtr->Vertices.push_back(Vector3D(*(Ptr + (J * ModelPtr->Stride)), *(Ptr + (J * ModelPtr->Stride + 1)), *(Ptr + (J * ModelPtr->Stride + 2))));
                }
                break;
            }
        }
}

I've also tried:

    for (int I = 0; I < TriangleCount; I++)
    {
       cout<<"X: " << *(Pointer + (I * Stride))<<endl;
       cout<<"Y: " << *(Pointer + (I * Stride + 1))<<endl;
       cout<<"Z: " << *(Pointer + (I * Stride + 2))<<endl;
    }

Dani AI

Generated

Short answer: the stride OpenGL uses is measured in bytes, while pointer arithmetic on a float* advances in floats (typically 4 bytes each). As explained, that mismatch is why some vertices looked wrong. Two other frequent gotchas in this thread: ModelPtr->TriangleCount may be triangles (not vertices) — non‑indexed meshes need triangleCount * 3 vertices — and the data pointer saved from glBufferData is just the client source pointer (it can become invalid after the caller frees that memory). Either keep a CPU copy of the upload or read back the buffer with GL calls.

Practical steps to iterate vertex positions from an interleaved buffer:

  • Ensure strideBytes is actually in bytes. If the value is in floats convert: strideBytes = strideFloats * sizeof(GLfloat). If stride is 0, treat the vertex as tightly packed (e.g. position-only = 3 * sizeof(GLfloat)).
  • If position is not the first attribute, account for its byte offset inside each vertex: posOffsetBytes.
  • To compute vertex N address do byte arithmetic: baseByte + N * strideBytes + posOffsetBytes, then reinterpret that address as const GLfloat* and read v[0], v[1], v[2].

Example workflow (read from a VBO via mapping):

glBindBuffer(GL_ARRAY_BUFFER, vboID);
void* mapped = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
if (mapped) {
  const unsigned char* base = reinterpret_cast<const unsigned char*>(mapped);
  for (size_t i = 0; i < vertexCount; ++i) {
    const float* p = reinterpret_cast<const float*>(base + i*strideBytes + posOffsetBytes);
    positions.push_back(Vector3D(p[0], p[1], p[2]));
  }
  glUnmapBuffer(GL_ARRAY_BUFFER);
}

Troubleshooting notes: if values are garbage, check (1) whether the saved BufferPointer is valid, (2) whether the code is iterating triangles vs vertices, (3) the correct posOffsetBytes inside the interleaved vertex, and (4) that the buffer being inspected is the intended BufferID (don't rely on a changing CurrentBuffer.ID). These checks address the gaps in 's original code and complement 's pointer-arithmetic explanation.

Recommended Answers

All 4 Replies

The problem here is that when you add a number to a pointer, it moves the pointer by that number of objects that the pointer points to, not by that number of bytes. Say you have float* ptr;, then *(ptr + 4) is equivalent to ptr[4], meaning that it gets the float value that is 4 floats after the pointer address, not the float value that is 4 bytes after the pointer address. In OpenGL, the stride is specified as a number of bytes, so I assume your "Stride" variables are also in bytes. The way to solve this is by casting the pointer to a 1-byte type pointer, for instance, char*, then do the addition by the stride, and then cast it back to the actual pointer type to retrieve the value. As so:

for (int I = 0; I < TriangleCount; I++)
{
   cout<<"X: " << *( reinterpret_cast<const GLfloat*>(reinterpret_cast<const char*>(Pointer) + (I * Stride) ) ) << endl;
   cout<<"Y: " << *( reinterpret_cast<const GLfloat*>(reinterpret_cast<const char*>(Pointer) + (I * Stride) ) + 1 ) << endl;
   cout<<"Z: " << *( reinterpret_cast<const GLfloat*>(reinterpret_cast<const char*>(Pointer) + (I * Stride) ) + 2 ) << endl;
}

Notice also how the + 1 and + 2 are put after the cast back to const GLfloat*.

commented: Perfect! +6

Wow... I got lost there ={
Usually I understand but this time I really got lost.

meaning that it gets the float value that is 4 floats after the pointer address, not the float value that is 4 bytes after the pointer address.

This part confused me. I got lost there. Can you break that down further?

You can try and run this:

#include <iostream>

float arr[] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0};

int main() {
  float* ptr = arr;

  // get the actual "address" that the pointer points to:
  std::size_t ptr_value = reinterpret_cast<std::size_t>(ptr);
  std::cout << "ptr = " << ptr_value << std::endl;

  // if you offset the pointer by 4, you get:
  float* ptr1 = ptr + 4;
  std::size_t ptr1_value = reinterpret_cast<std::size_t>(ptr1);
  std::cout << "ptr1 - ptr = " << ptr1_value - ptr_value << " bytes." << std::endl;

  // check this condition:
  if( ptr1_value - ptr_value == 4 * sizeof(float) )
    std::cout << "The difference between ptr1 and ptr is equal to 4 times the size of a float." << std::endl;

  // if you offset the pointer by 4 bytes, you get:
  float* ptr2 = reinterpret_cast<float*>(reinterpret_cast<char*>(ptr) + 4);
  std::size_t ptr2_value = reinterpret_cast<std::size_t>(ptr2);
  std::cout << "ptr2 - ptr = " << ptr2_value - ptr_value << " bytes." << std::endl;

  // check this condition:
  if( ptr2_value - ptr_value == 4 )
    std::cout << "The difference between ptr2 and ptr is equal to 4 bytes." << std::endl;

  return 0;
};

The meaning of my sentence was to explain the behavior of the above piece of code. Try it for yourself and you'll see.

PERFECT!! It works! I understand now =] Thank you so much mike!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.