I am trying to map a texture image to a sphere.
I have vertices and texture coords in different vectors, that's why I am using glBufferSubData.
std::vector<glm::vec3> sphere_vertices;
std::vector<int> sphere_indices;
std::vector<glm::vec2> sphere_texcoords;
I don't use any colors , only vertices,indices,textures.
I am using:
// upload geometry to GPU
glBindVertexArray(sphere_VAO);
glGenBuffers(1, &sphere_vertices_VBO);
glBindBuffer(GL_ARRAY_BUFFER, sphere_vertices_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * sphere_vertices.size() + sizeof(float) * sphere_texcoords.size(),
0, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * sphere_vertices.size(), sphere_vertices.data());
glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * sphere_vertices.size(), sizeof(float) * sphere_texcoords.size(), sphere_texcoords.data());
glGenBuffers(1, &sphere_indices_VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sphere_indices_VBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * sphere_indices.size(), sphere_indices.data(), GL_STATIC_DRAW);
// setup vertex attributes
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
// texture coords attrib
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float) , (void*)(sizeof(float) * sphere_vertices.size()));
and the image does not map correctly on the sphere.
The image I am receiving:
-- UPDATE ---
I used sphere_texcoords.push_back((glm::vec2((x + 1) / 2.0, (y + 1) / 2.0))); for texcoords and it works now!
The size of the buffer and the buffer offsets have to be specified in bytes.
Note, the size of an element is sizeof(glm::vec3) respectively sizeof(glm::vec2) rather than sizeof(float):
size_t vertices_size = sizeof(glm::vec3) * sphere_vertices.size();
size_t texcoords_size = sizeof(glm::vec2) * sphere_texcoords.size();
glBufferData(GL_ARRAY_BUFFER, vertices_size + texcoords_size, 0, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices_size, sphere_vertices.data());
glBufferSubData(GL_ARRAY_BUFFER, vertices_size, texcoords_size, sphere_texcoords.data());
When named buffer object is bound the the last parameter of glVertexAttribPointer is treated as a byte offset into this buffer.
The offset of the texture coordinates has to be:
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), (void*)vertices_size);
In general the size of the data of a std::vector<T> v in bytes can be get by:
size_t size = sizeof(T) * v.size();
respectively
size_t size = sizeof(*v.data()) * v.size();
Related
Im having problems to add a struct to a OpenGL VBO
This is my struct
struct Vertex {
//vertices
std::vector<glm::vec3> vertices;
//texture coordinates
std::vector<glm::vec3> texCord;
}
This is how im assigning and initializing the VBO
glGenVertexArrays(1, &buffer.VAO);
glGenBuffers(1, &buffer.VBO);
glGenBuffers(1, &buffer.EBO);
glBindBuffer(GL_ARRAY_BUFFER, buffer.VAO);
//Initialize buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffer.VBO);
glBufferData(GL_ARRAY_BUFFER,
vertex.vertices.size() * sizeof(glm::vec3) +
vertex.texCord.size() * sizeof(glm::vec3)
&vertex,
GL_STATIC_DRAW);
//indices attribute
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertex.indices.size() * sizeof(glm::vec2), &vertex.indices[0], GL_STATIC_DRAW);
//vertices coordinates attribute
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, vertices));
//texture coordinates attribute
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texCord));
And my draw command looks like this
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(buffer.VAO);
glDrawElements(GL_TRIANGLES, vertex.indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
Is it possible to initialize buffer data with a raw struct and if yes how?
std::vector stores a pointer to dynamically allocated memory. However, you must pass a consecutive buffer to glBufferData.
Create the object's data store with glBufferData, but use glBufferSubData to initialize the buffer:
size_t vertexSize = vertex.vertices.size() * sizeof(glm::vec3);
size_t texCordSize = vertex.texCord.size() * sizeof(glm::vec3);
glBufferData(GL_ARRAY_BUFFER, vertexSize + texCordSize, nullptr, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertexSize, vertex.vertices.data());
glBufferSubData(GL_ARRAY_BUFFER, vertexSize, texCordSize, vertex.texCord.data());
Thanks to #Rabbid76 I now solved my problem. Code is down below.
Note: I need to create the buffer before filling data with glBufferSubData
glGenVertexArrays(1, &buffer.VAO);
glGenBuffers(1, &buffer.VBO);
glGenBuffers(1, &buffer.EBO);
glBindBuffer(GL_ARRAY_BUFFER, buffer.VAO);
int vertexSize = sizeof(glm::vec3) * vertex.vertices.size();
int texCordSize = sizeof(glm::vec2) * vertex.texCord.size();
int totalSize = vertexSize + texCordSize;
int indicesSize = sizeof(unsigned int) * vertex.indices.size();
//Create Buffer dynamically
glBufferData(GL_ARRAY_BUFFER, totalSize, NULL, GL_DYNAMIC_DRAW);
//Fill the buffer with data
glBindBuffer(GL_ARRAY_BUFFER, buffer.VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertexSize, vertex.vertices.data());
glBufferSubData(GL_ARRAY_BUFFER, vertexSize, texCordSize, vertex.texCord.data());
//indices attribute
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesSize, vertex.indices.data(), GL_STATIC_DRAW);
//position attribute
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3) + sizeof(glm::vec2), (void*)0);
//texture attribute
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec3) + sizeof(glm::vec2), (void*)sizeof(glm::vec3));
glBindVertexArray(0);
I am trying to construct a bar.
First i declare a structure
struct VertexFormat
{
glm::vec3 positions;
glm::vec3 normal;
glm::vec2 texCoord;
VertexFormat(glm::vec3 pos, glm::vec3 norm, glm::vec2 coord) : positions(pos), normal(norm), texCoord(coord)
{ }
};
and than i configure the VAO and the VBO
glBindVertexArray(m_VAO);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(VertexFormat), &data[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size(), &indices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, data.size() * sizeof(VertexFormat), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, data.size() * sizeof(VertexFormat), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, data.size() * sizeof(VertexFormat), (void*)(6 * sizeof(float)));
glBindVertexArray(0);
Nothing gets drawn when i issue the drawing commands
glBindVertexArray(m_VAO);
glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
My question is that am i defining the offsets for the data in the buffer correctly ?
There are several problems with this code:
First, the amount of data uploaded to the EBO is wrong. The size of the data has to be given in byte. Assuming that indices contains unsigned integers, the code should be:
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
Then, stride describes the offset between two consecutive vertices in the buffer, not the total size of your data. In your case, every vertex starts sizeof(VertexFormat) after the previous one.
The correct code should be:
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (void*)(6 * sizeof(float)));
I am creating and storingthe position of the vertices of a 256*256 grid in a simple for loop like this:
ind=0;
for(i=0, i<256, i++){
for(j=0, j<256, j++){
vertexPosition[ind].x= i;
vertexPosition[ind].y= 1.0;
vertexPosition[ind].z= j;
ind++;
I am sending these vertices to the shader using vertex arrays. However, when drawing this with
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 256*256)
glBindVertexArray(0);
I get the following result.
I understand that this has to do with how opengl draws triangles? I am creating my vertices row by row but it seems that this is not how opengl draws the triangles (obviously). I am quite stuck here and would be glad if anyone could point me in the right direction in how to get the grid to display properly
This is how I store the vertex info in buffers
//Terrain Vertex Position
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(3, VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glBufferData(GL_ARRAY_BUFFER, nrOfVertices * 3 * sizeof(GLfloat), terrainVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(sizeof(glm::vec3) * 0));
//Terrain Normals
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
glBufferData(GL_ARRAY_BUFFER, nrOfVertices * 3 * sizeof(GLfloat), normals, GL_STATIC_DRAW);
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(sizeof(glm::vec3) * 3));
//Terrain UV
glBindBuffer(GL_ARRAY_BUFFER, VBO[2]);
glBufferData(GL_ARRAY_BUFFER, nrOfVertices * 2 * sizeof(GLfloat), uv, GL_STATIC_DRAW);
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), BUFFER_OFFSET(sizeof(glm::vec3) * 6));
glBindVertexArray(0); //End the array here
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glBufferData(GL_ARRAY_BUFFER, nrOfVertices * 3 * sizeof(GLfloat), terrainVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT,GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(sizeof(glm::vec3) * 0));
^^^^^^^^^^^^^^^^^
No. Your vertices buffer VBO[0] is XYZXYZXYZ. So no stride is needed. Set it to 0.
If your buffer was XYZnnXYZnnXYZ then stride=2 (the two 'n').
Correction: The stride is a number of bytes. If you have two 'n' interleaved and your are reading each vale in buffer as a float, then the stride for each XYZ is 2*sizeof(float)
Same for Normals and UV
My question connected with another my question: How to render large number of similar objects?
I trying to render set of points. For one point I using this code:
glUseProgram(programId);
glUniformMatrix4fv(matrixId, 1, GL_FALSE, &(vp * getModelMatrix(pos, scale))[0][0]);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_POINTS, 0, 1);
glDisableVertexAttribArray(0);
I slightly puzzled with task about set of points. I allocated more memory for vertices:
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, totalParticleCount * 3 * sizeof(GLfloat), gVertexBufferData, GL_STATIC_DRAW);
And I using this draw call for rendering:
glDrawArrays(GL_POINTS, 0, totalParticleCount);
But I don't understand which transformation I must use for glUniformMatrix4fv function and how I must set vertices. I'm trying do this:
for (int i = 0; i < totalParticleCount; i++) {
gVertexBufferData[3 * i + 0] = hState[i].pos.x;
gVertexBufferData[3 * i + 1] = hState[i].pos.y;
gVertexBufferData[3 * i + 2] = hState[i].pos.z;
}
And set uniform matrix:
glUniformMatrix4fv(matrixId, 1, GL_FALSE, &vp[0][0]);
In my case I see nothing and I can't understand whats wrong.
This post (https://gamedev.stackexchange.com/questions/90471/should-unbind-buffers) turned out very helpful in my situation. After updating vertices I must bind VAO and VBO again. Now I have this working code:
for (int i=0; i<totalParticleCount; i++) {
gVertexBufferData[3 * i + 0] = hState[i].pos.x;
gVertexBufferData[3 * i + 1] = hState[i].pos.y;
gVertexBufferData[3 * i + 2] = hState[i].pos.z;
}
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, totalParticleCount * 3 * sizeof(GLfloat), gVertexBufferData, GL_STATIC_DRAW);
glUseProgram(programId);
glUniformMatrix4fv(matrixId, 1, GL_FALSE, &vp[0][0]);
The problem I am having is that once I create a VBO for the main geometry in a level, when I create a second for the objects, the object VBO does not work. I am assuming I have some buffer bound incorrectly but I can't for the life of me find it. I create the level VBO first and then the object VBO and again, when I disable the creation of the level VBO, the object VBO creates correctly.
Here is my code.
in level.h:
// Zone VBO
GLuint zoneVBO;
GLuint zoneVAO;
GLuint zoneIBO;
// Object VBO
GLuint objVBO;
GLuint objVAO;
GLuint objIBO;
Creation of zone (geometry) VBO - just as a note, the creation works correctly in both VBOs so the data moving around isn't the issue, it is I think, a binding error:
void WLD::createZoneVBO()
{
// Get the size for our VBO
int numVert = 0;
int numPoly = 0;
int VBOsize = 0;
int IBOsize = 0;
// Get the count of vertices and polygons
for(int i = 0; i < zoneFragMap[0x36]; i++)
{
numVert += zmeshes[i].numVert;
numPoly += zmeshes[i].numPoly;
VBOsize += zmeshes[i].numVert * sizeof(Vertex);
IBOsize += zmeshes[i].numPoly * 3 * sizeof(GLuint);
}
// Create the IBO and VBO data
GLuint* iboData = new GLuint[zonePolyProcessed * 3];
Vertex* vboData = new Vertex[zoneVertProcessed];
int iboPos = 0;
int vboPos = 0;
// Create the VBO and IBO
for(int i = 0; i < zoneFragMap[0x36]; i++)
{
// Copy the data to the IBO
memcpy(&iboData[iboPos], zmeshes[i].indices, zmeshes[i].numPoly * 3 * sizeof(GLuint));//sizeof(*zmeshes[i].indices));
// Advance the position
iboPos += zmeshes[i].numPoly * 3;
// Copy the data to the VBO
memcpy(&vboData[vboPos], zmeshes[i].vertices, zmeshes[i].numVert * sizeof(Vertex));//sizeof(*zmeshes[i].vertices));
// Advance the position
vboPos += zmeshes[i].numVert;
}
//Create VBO for the triangle
glGenBuffers(1, &zoneVBO);
glBindBuffer(GL_ARRAY_BUFFER, zoneVBO);
glBufferData(GL_ARRAY_BUFFER, zoneVertProcessed * sizeof(Vertex), vboData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//Create the IBO for the triangle
//16 bit indices
//We could have actually made one big IBO for both the quad and triangle.
glGenBuffers(1, &zoneIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, zoneIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, zonePolyProcessed * 3 * sizeof(GLuint), iboData, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// Create the VAO
glGenVertexArraysAPPLE(1, &zoneVAO);
glBindVertexArrayAPPLE(zoneVAO);
glBindBuffer(GL_ARRAY_BUFFER, zoneVAO);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glVertexAttribPointer(opaque["position"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
glVertexAttribPointer(opaque["normal"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 3));
glVertexAttribPointer(opaque["texcoord"], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 6));
glVertexAttribPointer(opaque["color"], 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 8));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArrayAPPLE(0);
delete[] iboData;
delete[] vboData;
}
And the objects - again, the object geometry is loaded perfectly, but only if the zone geometry hasn't been loaded yet:
void WLD::createObjectVBO()
{
// Get the size for our VBO
int numVert = 0;
int numPoly = 0;
int VBOsize = 0;
int IBOsize = 0;
// Get the count of vertices and polygons
for(int i = 0; i < objFragMap[0x36]; i++)
{
numVert += objMeshes[i].numVert;
numPoly += objMeshes[i].numPoly;
VBOsize += objMeshes[i].numVert * sizeof(Vertex);
IBOsize += objMeshes[i].numPoly * 3 * sizeof(GLuint);
}
// Create the IBO and VBO data
GLuint* iboData = new GLuint[objPolyProcessed * 3];
Vertex* vboData = new Vertex[objVertProcessed];
int iboPos = 0;
int vboPos = 0;
// Create the VBO and IBO
for(int i = 0; i < objFragMap[0x36]; i++)
{
// Copy the data to the IBO
memcpy(&iboData[iboPos], objMeshes[i].indices, objMeshes[i].numPoly * 3 * sizeof(GLuint));//sizeof(*zmeshes[i].indices));
// Advance the position
iboPos += objMeshes[i].numPoly * 3;
// Copy the data to the VBO
memcpy(&vboData[vboPos], objMeshes[i].vertices, objMeshes[i].numVert * sizeof(Vertex));//sizeof(*zmeshes[i].vertices));
// Advance the position
vboPos += objMeshes[i].numVert;
}
//Create VBO for the triangle
glGenBuffers(1, &objVBO);
glBindBuffer(GL_ARRAY_BUFFER, objVBO);
glBufferData(GL_ARRAY_BUFFER, objVertProcessed * sizeof(Vertex), vboData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//Create the IBO for the triangle
//16 bit indices
//We could have actually made one big IBO for both the quad and triangle.
glGenBuffers(1, &objIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, objIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, objPolyProcessed * 3 * sizeof(GLuint), iboData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Create the VAO
glGenVertexArraysAPPLE(1, &objVAO);
glBindVertexArrayAPPLE(objVAO);
glBindBuffer(GL_ARRAY_BUFFER, objVAO);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glVertexAttribPointer(opaque["position"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
glVertexAttribPointer(opaque["normal"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 3));
glVertexAttribPointer(opaque["texcoord"], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 6));
glVertexAttribPointer(opaque["color"], 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 8));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArrayAPPLE(0);
}
Rendering these two VBOs:
opaque.Use();
glBindVertexArrayAPPLE(getVAO(2));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, zoneIBO);
glBindBuffer(GL_ARRAY_BUFFER, zoneVBO);
glUniformMatrix4fv(opaque("camera"), 1, GL_FALSE, glm::value_ptr(cameraMat));
renderGeometry(&cameraMat, 0, curRegion);
glBindVertexArrayAPPLE(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArrayAPPLE(objVAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, objIBO);
glBindBuffer(GL_ARRAY_BUFFER, objVBO);
glUniformMatrix4fv(opaque("camera"), 1, GL_FALSE, glm::value_ptr(cameraMat));
renderObjects(&cameraMat);
glBindVertexArrayAPPLE(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
opaque.UnUse();
To summarize, I think it's an issue in the creation of the VBOs. I think I am doing something wrong and keeping something bound when it should be bound.
// Create the VAO
glGenVertexArraysAPPLE(1, &zoneVAO);
glBindVertexArrayAPPLE(zoneVAO);
glBindBuffer(GL_ARRAY_BUFFER, zoneVAO); //<-------
glEnableVertexAttribArray(0);
In the line I have highlighted, this looks like it should be zoneVBO, not zoneVAO.
You should be checking for errors with glGetError, it might have spotted this mistake.
Also it's not required to bind the buffers before calling renderObjects. If you have the vertex pointer stored in the VAO, then you do not need to bind the buffer, as the vertex pointers already point to the correct location.