N. J. Funk
N. J. Funk

Reputation: 122

I'm trying to render a model using vbo in OpenGL (LWJGL)

I am trying to render a model by importing the .obj File. Im successfully importing and preparing the data to be rendered in FloatBuffers/IntegerBuffers but cant manage to render it. Can someone help me?

This is the class that renders and initializes the VBOs

private int vertexBufferID;
private int indexBufferID;
private int numberIndices;

public void init() {
    try{
        InputStream objInputStream = new FileInputStream("./res/obj/Terrain.obj");
        Obj obj = ObjReader.read(objInputStream);

        obj = ObjUtils.convertToRenderable(obj);

        IntBuffer indices = ObjData.getFaceVertexIndices(obj, 3);
        FloatBuffer vertices = ObjData.getVertices(obj);
//      FloatBuffer texCoords = ObjData.getTexCoords(obj, 2);
//      FloatBuffer normals = ObjData.getNormals(obj);

        vertexBufferID = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferID);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);
        GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

        GL30.glBindVertexArray(0);

        indexBufferID = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
        GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
    }catch(IOException e)
    {
        e.printStackTrace();
    }
}

public void render() {
    GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferID);
    GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);

    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
    GL11.glDrawElements(GL11.GL_TRIANGLES, numberIndices, GL11.GL_UNSIGNED_INT, 0);
}

I get no error code the object is just not rendered. I am able to render the Object using Display Lists.

Upvotes: 1

Views: 318

Answers (1)

N. J. Funk
N. J. Funk

Reputation: 122

I've now solved the problem and am now able to import .obj-Files and render them using vbo/vao. Im using "Obj - a simple Wavefront OBJ file loader and writer" to prepare the data to be rendered.

The code to load up and prepare the .obj file

        InputStream objInputStream = new FileInputStream(pathTObjFile);
        Obj obj = ObjReader.read(objInputStream);

        obj = ObjUtils.convertToRenderable(obj);

        IntBuffer indices = ObjData.getFaceVertexIndices(obj, 3);
        FloatBuffer vertices = ObjData.getVertices(obj);

Now the data is stored in 2 VBOs and the VBO for the vertices is stored in a VAO:

        vaoId = GL30.glGenVertexArrays();

The Vertex Array Object ID (vaoID) is an Integer that is called if we are calling the VAO.

        GL30.glBindVertexArray(vaoId);

To be able to do anything with the VAO we have to bind or "select" it.

        vboId = GL15.glGenBuffers();

The VBOs also have an ID to be called with. We are creating the Vertex Buffer Object ID here (vboId)

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);

Now we select the VBO and store the vertices in it.

        GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

        GL30.glBindVertexArray(0);

First we put the VBO in the first attribute list of the VAO (a VAO has 16 lists), then we unbind the VAO and the VBO.

        vboiId = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);
        GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW);

        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); 


        indicesCount = indices.capacity();

At the end of the Initialization we have create the vbo for the indices so the Vertices can be connected to each others to create faces in the right way. Therefor we bind the vboiId and store the index data inside. Then we unbind the VBO again and save the number of Indices stored in the VBO because we have to tell it OpenGL to be able to render it later.

Rendering the Object:

    GL30.glBindVertexArray(vaoId);
    GL20.glEnableVertexAttribArray(0);
    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);

To Render the Object we have to bind the VAO and the VBO inside. We also have to select the VBO for the Indices. That is done by the code snippet above.

    GL11.glDrawElements(GL11.GL_TRIANGLES, indicesCount, GL11.GL_UNSIGNED_INT, 0);

Now we draw the Object and

    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
    GL20.glDisableVertexAttribArray(0);
    GL30.glBindVertexArray(0);

Deselect the VBOs and VAOs again.

Here is the whole code combined

private int vboiId;
private int vaoId;
private int vboId;
private int indicesCount;

public void init() {

    try{

        InputStream objInputStream = 
            new FileInputStream("./res/obj/Terrain.obj");
        Obj obj = ObjReader.read(objInputStream);

        obj = ObjUtils.convertToRenderable(obj);

        IntBuffer indices = ObjData.getFaceVertexIndices(obj, 3);
        FloatBuffer vertices = ObjData.getVertices(obj);
        FloatBuffer texCoords = ObjData.getTexCoords(obj, 2);
        FloatBuffer normals = ObjData.getNormals(obj);



        indicesCount = indices.capacity();


        vaoId = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(vaoId);


        vboId = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);

        GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);


        GL30.glBindVertexArray(0);


        vboiId = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);
        GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW);

        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
    }catch(IOException e)
    {
        e.printStackTrace();
    }


}

public void render() {
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);


    GL30.glBindVertexArray(vaoId);
    GL20.glEnableVertexAttribArray(0);


    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);


    GL11.glDrawElements(GL11.GL_TRIANGLES, indicesCount, GL11.GL_UNSIGNED_INT, 0);


    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
    GL20.glDisableVertexAttribArray(0);
    GL30.glBindVertexArray(0);
}

For further and more detailed information i strongly recommend u to read The quad with Draw Array, The Quad with Draw Elements and if you want to go more in detail look up the OpenGL 3.2 and above tutorials on the Main Page of the LWJGL Wiki. For information on how to use the Obj loader I used look up The sample projects using this loader

My code basically consists of a mixture of the code on this websites.

Edit: If you try to render multiple Objects you have to Clear the Color before rendering the first object (First line of the Render method)

Upvotes: 3

Related Questions