1
votes

I want to create mesh class with VBO in C++. The class looks like following:

mesh::mesh(std::vector<Vector3d>* Vertices, std::vector<unsigned int>* Indices, std::vector<Vector2d>* TextureCoords) {
    if(Vertices) this->vertices = *Vertices;
    if(Indices) this->indices = *Indices;
    if(TextureCoords) this->textureCoords = *TextureCoords;
    chatbox.AddMessageToQueue("vertices.size() : %d", vertices.size());
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vector3d) + textureCoords.size()*sizeof(Vector2d), 0, GL_STATIC_DRAW);
    glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size()*sizeof(Vector3d), vertices.data());
    glBufferSubData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vector3d), textureCoords.size()*sizeof(Vector2d), textureCoords.data());

    glGenBuffers(1, &IND);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IND);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
}

void mesh::draw() {
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);

    glVertexPointer(3, GL_FLOAT, 0, (void*)0);
    glTexCoordPointer(2, GL_FLOAT, 0, (void*)(sizeof(float)*3*6));

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IND);
    glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (unsigned int*)0 + 0);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

The problem is in the texture coordinates only. I'm trying to create the mesh like so:

std::vector<unsigned int> indices;
std::vector<mesh::Vector3d> vertices;
std::vector<mesh::Vector2d> texCoords;

vertices.push_back({PosX, PosY, 1.0});
vertices.push_back({PosX + SizeX, PosY, 1.0});
vertices.push_back({PosX + SizeX, PosY + SizeY, 1.0});
vertices.push_back({PosX, PosY + SizeY, 1.0});

indices.push_back(0);
indices.push_back(1);
indices.push_back(2);

indices.push_back(0);
indices.push_back(2);
indices.push_back(3);

texCoords.push_back({0, 1});
texCoords.push_back({1, 0});
texCoords.push_back({0, 0});

texCoords.push_back({0, 1});
texCoords.push_back({1, 1});
texCoords.push_back({1, 0});

gui_checkbox = new mesh(&vertices, &indices, &texCoords);

But the result is wrong, as you can see in the left picture below (the picture on the right is the desired one):

The image on the left side is from VBO, on the right side is immediate mode

The vertices are in ortho mode, so the coordinate origin for vertices is in top left corner and for texture coordinates the origin is in the bottom left just like in OpenGL.

1

1 Answers

5
votes

When one is using indices to address the vertex positions, the texture coordinates also get indexed. In your case this means, that you are only using the first four entries in texCoords. The strange looking comes from texCoords[0] == texCoords[3].

The correct texCoords would most probably be

texCoords.push_back({0, 1});
texCoords.push_back({1, 1});
texCoords.push_back({1, 0});
texCoords.push_back({0, 0});

These can be derived from the vertex-coordinates: texCoords should have the same value at a component whenever their corresponding vertices have the same component value. e.g. if vertices[0].y == vertices[1].y => texCoords[0].y == texCoords[1].y and so on. In addition, the texCoords y coordinates have to be flipped, since vertex origin as on top-left while texcoords start at bottom left.

Edit:

glTexCoordPointer(2, GL_FLOAT, 0, (void*)(sizeof(float)*3*6));

does not look correct to me. This statement tells that the first texture coordinate starts after the sixth vector3, but shouldn't they start after the fourth one? (You only have 4 entries in vertices):

glTexCoordPointer(2, GL_FLOAT, 0, (void*)(sizeof(float)*3*4));