I was using IBOs to render meshes (for example a cube) from wave-front files (.obj), without texture coordinates or normals, in OpenGL.
Following this, I attempted to implemented texturing. The mesh was distorted because the indices are not referencing the correct vertices. There is a one-to-one relation between texture coordinates and vertices. Therefore, by implementing texture coordinates, extra vertices have been added to the vertex array/buffer (vertices with the same position but with different texture coordinates). Therefore, existing vertices have been offset and no longer correspond to the indices array/buffer.
Related rendering Code:
private int vbo;
private int ibo;
private int size;
public Mesh() {
vbo = glGenBuffers();
ibo = glGenBuffers();
size = 0;
}
public void addVertices(Vertex[] vertices, int[] indices) {
size = indices.length;
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, Util.createFlippedBuffer(vertices),
GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
Util.createFlippedBuffer(indices), GL_STATIC_DRAW);
}
public void draw() {
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, Vertex.SIZE * 4, 12);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}
I had to switch to a vertex buffer object (VBO) only method of rendering to properly display the mesh with its texture. However, now will not gain any benefits of IBOs when render other, more complex meshes.
Related rendering Code:
private int vbo;
private int size;
public Mesh() {
vbo = glGenBuffers();
size = 0;
}
public void addVertices(Vertex[] vertices, int[] indices) {
size = vertices.length;
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, Util.createFlippedBuffer(vertices),
GL_STATIC_DRAW);
}
public void draw() {
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, Vertex.SIZE * 4, 12);
glDrawArrays(GL_TRIANGLES, 0, size);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}
Code for loading meshes from wave-front files:
ArrayList<Vertex> vertices = new ArrayList<Vertex>();
ArrayList<Integer> indices = new ArrayList<Integer>();
ArrayList<Integer> textureIndices = new ArrayList<Integer>();
ArrayList<Vector2f> textureCoordinates = new ArrayList<Vector2f>();
BufferedReader meshReader = null;
try {
meshReader = new BufferedReader(new FileReader("./res/models/"
+ fileName));
String line;
while ((line = meshReader.readLine()) != null) {
String[] tokens = line.split(" ");
tokens = Util.removeEmptyStrings(tokens);
if (tokens.length == 0 || tokens[0].equals("#"))
continue;
else if (tokens[0].equals("v"))
vertices.add(new Vertex(new Vector3f(Float
.valueOf(tokens[1]), Float.valueOf(tokens[2]),
Float.valueOf(tokens[3]))));
else if (tokens[0].equals("vt"))
textureCoordinates.add(new Vector2f(Float
.valueOf(tokens[1]), Float.valueOf(tokens[2])));
else if (tokens[0].equals("f")) {
for (int t = 1; t < 4; t++) {
String[] splitToken = tokens[t].split("/");
indices.add(Integer.parseInt(splitToken[0]) - 1);
textureIndices.add(Integer.parseInt(splitToken[1]) - 1);
}
}
}
meshReader.close();
ArrayList<Vertex> processedVertices = new ArrayList<Vertex>();
for(int i = 0; i < indices.size(); i++) {
processedVertices.add(new Vertex(vertices.get(indices.get(i)).getPos(), textureCoordinates.get(textureIndices.get(i))));
}
// Then 'indices' and 'processedVertices' are sent to the GPU.
How can I correctly implement IBOs with texture coordinates, so that an IBO is 'aligned' to a VBO after adding extra vertices (vertices with the same position but with different texture coordinates)?
vetices
andindicdes
.(If this is indeed the problem, I will post this as an answer so you can accept it) Could I also see your rendering code? \$\endgroup\$