I am trying to update my engine that used OpenGL 2.x vertex arrays to work with OpenGL 3.x, which means updating for VAO / VBOs. I think that I am not getting attached to VBO properly. Read below for more information or skip the code and find what I am doing wrong.
A brief overview of my grid classes looks something like this:
Grid
MeshNode
- convert
- VAO Index
- VBO index
- array of child MeshNodes
- an array of MeshObjects objects
Meshhobject
- all vertex and index data loaded from a file for a separate part of the general grid
- top of the vbo index
If I draw a MeshNode with only one MeshObject, it seems to be drawn perfectly. When I draw a MeshNode with several MeshObjects, I get that the general shape of the model that I am trying to draw is distorted.
I checked the vertex data in the Visual Studio debugger and the VBO data through gDEbugger and everything looks great, so I'm sure loading from a file and loading in VBOs works.
I used gDEbugger to make it draw points for all the vertices instead of triangles, and it has the shape of a single MeshObject, which makes me think that I just don't attach to different VBOs properly. As if he is trying to draw with different indices, but the same vertices every time.
VertexData is as follows:
struct VertexData { enum { NUM_TEXCOORDS = 1, }; vector3 vertex; vector3 normal; vector2 texCoord[NUM_TEXCOORDS]; };
Relevant MeshNode Code:
void MeshNode::initVAO(void) { closeVAO(); unsigned int scan; //init index data if (m_meshObjects.size() > 0) { glGenVertexArrays(1, &m_meshVAO); glBindVertexArray(m_meshVAO); { //add up the total index count for all the mesh objects in this node unsigned int indexCount = 0; for (scan = 0; scan < m_meshObjects.size(); ++scan) { indexCount = indexCount + m_meshObjects[scan].getIndices()->size(); } //make the actual index buffer glGenBuffers(1, &m_indexVBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexVBO); { glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(unsigned short), NULL, GL_STATIC_DRAW); //set up VBOs and fill the index buffer with the index data from each mesh object unsigned int offset = 0; for (scan = 0; scan < m_meshObjects.size(); ++scan) { m_meshObjects[scan].initVBOs(offset); } } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } glBindVertexArray(0); } for (scan = 0; scan < m_childMeshNodes.size(); ++scan) { m_childMeshNodes[scan]->initVAO(); } } void MeshNode::closeVAO(void) { if (m_meshVAO != 0) { glBindVertexArray(m_meshVAO); { glDeleteBuffers(1, &m_indexVBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } glBindVertexArray(0); glDeleteVertexArrays(1, &m_meshVAO); m_meshVAO = 0; m_indexVBO = 0; } } void MeshNode::render(const matrix4 &_parentTransform) { matrix4 transform = _parentTransform * m_transform; if (m_meshObjects.size() > 0) { glBindVertexArray(m_meshVAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexVBO); { for (unsigned int objectScan = 0; objectScan < m_meshObjects.size(); ++objectScan) { m_meshObjects[objectScan].render(transform); } } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindVertexArray(0); } for (unsigned int childScan = 0; childScan < m_childMeshNodes.size(); ++childScan) { m_childMeshNodes[childScan]->render(transform); } }
Corresponding MeshObject code:
void MeshObject::initVBOs(unsigned int& _indexOffset) { //sub in this section of the index data m_indexOffset = _indexOffset; _indexOffset = _indexOffset + m_indices.size(); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, m_indexOffset * sizeof(unsigned short), m_indices.size() * sizeof(unsigned short), &(m_indices[0])); //init vertex data glGenBuffers(1, &m_vertexVBO); glBindBuffer(GL_ARRAY_BUFFER, m_vertexVBO); { glBufferData(GL_ARRAY_BUFFER, m_data.size() * sizeof(VertexData), &(m_data[0]), GL_STATIC_DRAW); glVertexAttribPointer(Shader::POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (char*)0); glEnableVertexAttribArray(Shader::POSITION); glVertexAttribPointer(Shader::NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (char*)12); glEnableVertexAttribArray(Shader::NORMAL); glVertexAttribPointer(Shader::TEXCOORD0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (char*)24); glEnableVertexAttribArray(Shader::TEXCOORD0); } glBindBuffer(GL_ARRAY_BUFFER, 0); } void MeshObject::closeVBOs(void) { glDeleteBuffers(1, &m_vertexVBO); m_vertexVBO = 0; } void MeshObject::render(const matrix4& _transform) { m_material->bind(_transform); glBindBuffer(GL_ARRAY_BUFFER, m_vertexVBO); { glEnableVertexAttribArray(Shader::POSITION); glEnableVertexAttribArray(Shader::NORMAL); glEnableVertexAttribArray(Shader::TEXCOORD0); glDrawRangeElements(GL_TRIANGLES, m_indexOffset, m_indexOffset + m_indices.size(), m_indices.size(), GL_UNSIGNED_SHORT, (char*)0); glDisableVertexAttribArray(Shader::POSITION); glDisableVertexAttribArray(Shader::NORMAL); glDisableVertexAttribArray(Shader::TEXCOORD0); } glBindBuffer(GL_ARRAY_BUFFER, 0); }