Issue
I get an error when glDrawElements() is called and I can't figure out why :/ I'm new to using OpenGL and I'm trying to learn how it works.
Note: I am using this library for turning an OBJ file into arrays that OpenGL should be able to use: href="https://github.com/korre/java-obj-to-opengl/blob/master/MeshObjectLoader.java" rel="nofollow noreferrer">https://github.com/korre/java-obj-to-opengl/blob/master/MeshObjectLoader.java
public class Mesh {
private int vaoId;
private List<Integer> vboIdList = new ArrayList<>();
@Getter
@Setter
private float scale = 1;
@Getter
@Setter
private Vector3f position = new Vector3f(0, 0, 0);
@Getter
@Setter
private Vector3f rotation = new Vector3f(0, 0, 0);
@Getter
@Setter
private String textureKey;
private int vertexCount;
private Mesh(MeshObjectLoader.MeshArrays meshArrays) {
vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
var vboId = 0;
vertexCount = meshArrays.getNumVertices();
// Load vertices
vboId = glGenBuffers();
vboIdList.add(vboId);
var vertexBuffer = (FloatBuffer) meshArrays.getVertices();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, vertexBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0 ,0);
// Load texture coordinates
vboId = glGenBuffers();
vboIdList.add(vboId);
var textureCoordsBuffer = (FloatBuffer) meshArrays.getTexCoords();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, textureCoordsBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
// Clean everything up
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
public static Mesh loadFromObjFile(String resourcePath) throws IOException {
try (var resourceStream = Mesh.class.getResourceAsStream(resourcePath)) {
return new Mesh(MeshObjectLoader.loadModelMeshFromStream(resourceStream));
}
}
public void render(int textureId) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
glBindVertexArray(vaoId);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnable(GL_DEPTH_TEST);
glDrawElements(GL_TRIANGLES, vertexCount, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindVertexArray(0);
}
public void cleanup() {
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
for (int vboId : vboIdList) {
glDeleteBuffers(vboId);
}
glBindVertexArray(0);
glDeleteVertexArrays(vaoId);
}
}
Solution
The cause of the crash is that you never bind a buffer object to the GL_ELEMENT_ARRAY_BUFFER
binding point of the VAO, so the last argument of glDrawElements(..., 0)
is interpreted as a host-address pointer instead of an byte-offset in any element array buffer.
And dereferencing the 0
address fails, of course.
Whenever you call an indexed draw call like glDrawElements
you also need an element array buffer (also called "index buffer").
The library returns the list of positions, texture coordinates and normals in such a way that you merely need to do a non-indexed draw call via glDrawArrays()
. This is also pretty typical of a Wavefront OBJ loader, because the Wavefront OBJ format has separate indexes for positions, normals and texture coordinates, so a typical load will do the cross-product of all face indexes anyways and provide you with a linear/duplicated list of vertex data.
So: Do glDrawArrays
instead.
Answered By - httpdigest
Answer Checked By - Dawn Plyler (JavaFixing Volunteer)