-1

I'm attempting to write simple voxelized terrain engine using heightmaps and chunked approach. I wanted to construct separate mesh for each chunk and load the meshes into separate VBOs. I've prepared all the logic, but I don't seem to get VBO rendering to work properly. I prepared very simple heightmap for testing which should render only 2 lines of voxels 16x16x2 = 512 cubes 12 triangles each overall. The problem is my result looks nothing like it should - here's what I mean:

Click

It looks very similar no matter how far I zoom in or out or twist the camera, the lines just move a bit.
Here's how I'm trying to do this:
Constructing buffers for paricular mesh represented by CMesh class:

void CMesh::generateVertexBufferData()
{
    this->vertexBuffer = new GLuint();
    glGenBuffers(1,vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, *this->vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*meshVertexData->size(),&meshVertexData[0],GL_STATIC_DRAW);
    this->vertexCount = meshVertexData->size();
}
void CMesh::generateIndexBufferData()
{
    this->indexBuffer = new GLuint();
    glGenBuffers(1,this->indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *this->indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*meshIndexData->size(),&meshIndexData[0],GL_STATIC_DRAW);
    this->indexCount = meshIndexData->size();
}


Rendering done by GeometryManager class:

glPushMatrix();
    pRenderer->ImmediateColorAlpha(1.0f,1.0f,1.0f,1.0f);
    pRenderer->SetRenderMode(GL_LINE);

    pRenderer->TranslateWorldMatrix(geometryPosition.x*Chunk::CHUNK_SIZE,
                    geometryPosition.y*Chunk::CHUNK_SIZE,
                    geometryPosition.z*Chunk::CHUNK_SIZE);
    glBindBuffer(GL_ARRAY_BUFFER,*meshArray->at(geometryID)->getBuffer(VERTEX_BUFFER));
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3,GL_FLOAT,0,BUFFER_OFFSET(0));


    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,*meshArray->at(geometryID)->getBuffer(INDEX_BUFFER));
    glDrawElements(GL_TRIANGLES,meshArray->at(geometryID)->indexCount,GL_UNSIGNED_INT,BUFFER_OFFSET(0));

glPopMatrix();


I have checked weather I'm calculating vertex positions correctly by rendering them out as points straight from the std::vector* meshVertexData using simple immediate mode like this:

for(int i=0; i < meshArray->at(geometryID)->meshVertexData->size(); i+=3)
{
    glBegin(GL_POINTS);
    glVertex3f(meshArray->at(geometryID)->meshVertexData->at(i),
            meshArray->at(geometryID)->meshVertexData->at(i+1),
            meshArray->at(geometryID)->meshVertexData->at(i+2));
    glEnd();
}

And the result seems to be correct.
I'm completely stumped about this, I'm not sure what happens between populating VBO with data and rendering that makes it look like it does. I humbly ask for help in this matter, I don't really see what am I doing wrong. Is my approach completely flawed or I'm missing something simple?
If anyone is seriously interested in helping me with solving the problem, but needs more information I'm willing to provide anything you ask me for including full CMesh and GeometryManager code on pastebin.

Shilghter
  • 94
  • 1
  • 10
  • Does `indexBuffer` really need to be a pointer? That seems overly complicated - having to allocate a `GLuint` every time you generate a VBO or IBO. It is not like you are saving any storage by doing this, you have to store a pointer in your class which is generally going to be 32-bit or 64-bit and then you have to allocate another 4 bytes of memory to hold the ID later on. You might as well just create an actual `GLuint` in your class and then pass the address of that to `glGenBuffers (...)` instead. – Andon M. Coleman Jun 21 '14 at 16:28
  • Thank you for quick reply! I think you are right on this one, following your advice I made both buffers public non-pointer `GLuint`. It certainly makes things less complicated, but unfortunately doesn't solve my problem. By the way - each buffer generated by `glGenBuffers` is getting ID automaticaly iterated regadless of when, how and by which class was `glGenBuffers` called am I right? – Shilghter Jun 21 '14 at 16:47
  • Yes, each time you call `glGenBuffers (...)` it will return 1 or more *unused* IDs and then reserve those IDs so that another call to `glGenBuffers` does not also return them. It does not necessarily increment the ID every time you call it, it might recycle old IDs that are no longer in use after a call to `glDeleteBuffers (...)`. – Andon M. Coleman Jun 21 '14 at 16:53
  • In any case, the biggest difference here between the working and non-working code is actually the primitive type. The last bit of code uses `GL_POINTS` which does not have any connectivity between points, so if your problem is actually the order you draw your vertices in, then that is not going to show up. – Andon M. Coleman Jun 21 '14 at 16:59
  • Just as an experiment, can you try drawing with `glDrawArrays()` instead of `glDrawElements()`? The connectivity of the primitives will of course be wrong, but it should still show if the vertices are in the right place. I have a feeling that the problem is not in the code we're seeing. Could be many things. The content of `meshIndexData` could just be wrong. Or it could have the wrong type. Your `CMesh` class might have a destructor that wipes out the buffer objects. – Reto Koradi Jun 21 '14 at 18:43
  • I really appreciate your contribution! Maybe you're right saying the problem may not be in this code... I tried `glDrawArrays()` and what appeared was only 3 lines. I changed render primitive to `GL_POINTS` and it showed only one single point. I'm using Visual Studio so I checked the content of both data vectors and it appears to be right. I have also checked my destructor for `CMesh` and yes it was clearing all buffers by `glDeleteBuffers`, but I'm pretty sure it doesn't run before rendering since all `CMesh` objects are kept within `GeometryManager` in `std::vector*`. – Shilghter Jun 21 '14 at 21:25
  • 1
    After some time spent debugging I have finally found the bug, turns out it was in the code I posted after all. It seems that for `std::vector` this expression `&meshVertexData[0]` does NOT equal `&meshVertexData->at(0)`. Changed the `glBufferData` allocation to the latter and code runs just fine. I hope someone will learn from my mistakes. Thanks everyone for helping me with your insight! – Shilghter Jun 21 '14 at 22:26
  • Pleast post it as an answer:, by synthetizing it in one place it will make it easier for others when checking out this entry, rather than having to go through all the comments. – didierc Jun 22 '14 at 05:49

1 Answers1

0

After some time spent debugging and testing suggested solutions I have finally found the bug. Turns out that for std::vector this expression &meshVertexData[0] does NOT equal this expression &(meshVertexData->at(0)). As a result it wasn't allocating data in VBO correctly. Changed the glBufferData allocation to the latter and code runs just fine. I hope someone will learn from my mistakes. Thanks everyone for helping me with your insight!

Shilghter
  • 94
  • 1
  • 10
  • It looks like `meshVertexData` is a **pointer to** a vector. Which seems quite unusual, I had never seen anybody do this. In this case, `meshVertexData[0]` is the vector object, and `&meshVertexData[0]` is the address of the vector object, which is indeed not what you want. I don't think `&v->at(0)` is correct, that gives a compile error. You'll need either &(v->at(0))` or `&(*meshVertexData)[0]`. – Reto Koradi Jun 22 '14 at 14:39
  • Now that you mentioned it this really makes sense. `meshVertexData` is indeed a pointer to a vector. When I think about it, it really would make more sense to use expressions you mentioned. I checked it out and you are absolutely right `&(meshVertexData->at(0))` is correct. Though `&meshVertexData->at(0)` actually compiled and rendered result which, at first glance, looked like something I was expecting. Testing out your suggestion proved me wrong, but I'm afraid I can't explain why compilation and render actually worked for me. – Shilghter Jun 22 '14 at 18:56