Daler
Daler

Reputation: 103

Problems dynamically moving VBO

I am making a 3D game that has a player with the follow cam. Before I started using real models I used the cube and I rendered it using displaylist and it everything moved fine. However, now that I am importing full 3D models with many more vertices, I looked into VBOs. I have a full structure setup for my VBOs and I can see the model drawn initially but it is drawn at the center of the game world. When I move the player, the model doesn't translate as it should. The model doesn't move its position.

Here is the code that I used initially to draw the player as a rectangle (which works):

public static void drawRectPrism(float centerx, float centery, float centerz, float length, float height, float width, float rx, float ry, float rz)
{
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    {
        glTranslatef(centerx, centery, centerz);
        glRotatef(rx, 1, 0, 0);
        glRotatef(ry, 0, 1, 0);
        glRotatef(rz, 0, 0, 1);
        glTranslatef(-centerx, -centery, -centerz);
        glTranslatef(-length/2f, -height/2f, -width/2f);


        glBegin(GL_QUADS);
        {
            glColor3f(1.0f, 0, 0);
            glVertex3f(centerx, centery, centerz);
            glVertex3f(centerx + length, centery, centerz);
            glVertex3f(centerx + length, centery + height, centerz);
            glVertex3f(centerx, centery + height, centerz);

            glColor3f(0, 1.0f, 0);
            glVertex3f(centerx, centery, centerz + width);
            glVertex3f(centerx + length, centery, centerz + width);
            glVertex3f(centerx + length, centery + height, centerz + width);
            glVertex3f(centerx, centery + height, centerz + width);

            glColor3f(0, 0, 1.0f);
            glVertex3f(centerx, centery, centerz);
            glVertex3f(centerx, centery + height, centerz);
            glVertex3f(centerx, centery + height, centerz + width);
            glVertex3f(centerx, centery, centerz + width);          

            glColor3f(0, 1.0f, 1.0f);
            glVertex3f(centerx + length, centery, centerz);
            glVertex3f(centerx + length, centery + height, centerz);
            glVertex3f(centerx + length, centery + height, centerz + width);
            glVertex3f(centerx + length, centery, centerz + width); 

            glColor3f(1.0f, 1.0f, 0);
            glVertex3f(centerx, centery, centerz);
            glVertex3f(centerx + length, centery, centerz);
            glVertex3f(centerx + length, centery, centerz + width);
            glVertex3f(centerx, centery, centerz + width);

            glColor3f(1.0f, 0, 1.0f);
            glVertex3f(centerx, centery + height, centerz);
            glVertex3f(centerx + length, centery + height, centerz);
            glVertex3f(centerx + length, centery + height, centerz + width);
            glVertex3f(centerx, centery + height, centerz + width);         
        }
        glEnd();
    }
    glPopMatrix();
}   

I tried a couple of different ways somewhere better than others and probably implemented terrible programming structure, but I figured it should still work.

First attempt: to adapt the rectangle code to load my vertices and models instead of specific rectangle verticies:

public void translate(float x, float y, float z, float rx, float ry, float rz)
{

        File f = new File("graveDigga.obj");
        try{
            m = OBJLoader.loadModel(f);
        }
        catch(FileNotFoundException e)
        {
            e.printStackTrace();
            Display.destroy();
            System.exit(1);
        }
        catch(IOException e)
        {
            e.printStackTrace();
            Display.destroy();
            System.exit(1);
        }
        displayListChar = glGenLists(1);
        glNewList(displayListChar, GL_COMPILE);
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        {
            glTranslatef(x, y, z);
            glRotatef(rx, 1, 0, 0);
            glRotatef(ry, 0, 1, 0);
            glRotatef(rz, 0, 0, 1);
            //glTranslatef(-x, -y, -z);
            //glTranslatef(-length/2f, -height/2f, -width/2f);
            glBegin(GL_TRIANGLES);
            for(Face face : m.faces)
            {
                Vector2f t1 = m.textures.get((int) face.textures.x - 1);
                glTexCoord2f(t1.x +x ,1-(t1.y +y ));
                Vector3f n1 = m.normals.get((int) face.normal.x-1);
                glNormal3f(n1.x +x ,n1.y+y,n1.z +z);
                Vector3f v1 = m.vertices.get((int) face.vertex.x-1);
                glVertex3f(v1.x +x,v1.y+y,v1.z+z);
                Vector2f t2 = m.textures.get((int) face.textures.y - 1);
                glTexCoord2f(t2.x +x, 1 - (t2.y+y ));
                Vector3f n2 = m.normals.get((int) face.normal.y-1);
                glNormal3f(n2.x+x,n2.y+y ,n2.z+z);
                Vector3f v2 = m.vertices.get((int) face.vertex.y-1);
                glVertex3f(v2.x+x,v2.y+y ,v2.z+z);
                Vector2f t3 = m.textures.get((int) face.textures.z - 1);
                glTexCoord2f(t3.x +x, 1 - (t3.y +y));
                Vector3f n3 = m.normals.get((int) face.normal.z-1);
                glNormal3f(n3.x+x,n3.y+y,n3.z +z);
                Vector3f v3 = m.vertices.get((int) face.vertex.z-1);
                glVertex3f(v3.x+x,v3.y+y,v3.z +z);

            }
            glEnd();
        }
        glPopMatrix();

    //}
    //glPopMatrix();
    build();
}

I next tried to display model by creating a VBO from this data and call a rander method in my game loop. Before calling render I would run through the code to attempt to translate the position of VBO but nothing was happening.

glMatrixMode(GL_MODELVIEW);
            glPushMatrix();
            {
                //glLoadIdentity();
                glTranslatef(x,y,z);
                glRotatef(rx, 1, 0, 0);
                glRotatef(ry, 0, 1, 0);
                glRotatef(rz, 0, 0, 1);
                glTranslatef(-x,-y,-z);
                glDrawArrays(GL_TRIANGLES, 0, m.faces.size() * 3);

}

I am not sure if I should be using shaders for this or not, but part of me is questioning why it is hard to move a 3D model in world space? Is there a messy way that is easier to implement for a temporary basis?

Upvotes: 1

Views: 205

Answers (1)

Joehot200
Joehot200

Reputation: 1090

Considering you're a new person with 1 rep, have an upvote. Nicely written question :).

I am not sure if I should be using shaders for this or not, but part of me is questioning why it is hard to move a 3D model in world space? Is there a messy way that is easier to implement for a temporary basis?

A simple glTranslatef() call should suffice to move an object, and simple glRotatef() call will rotate the object.

For example, using glRotatef(90, 1, 0, 0) returns this result: enter image description here Wheras without the line, the grass is not rotated at all: enter image description here

Same with the ship. Using glRotatef(40, -1, 0, 0) returns this result: enter image description here Wheras without the line it just returns flat: enter image description here

Obviously that is just the pitch. glRotatef(AmountToRotate, PITCH, YAW, ROLL) can roll the ship onto its side, or rotate the ship around.

Enough about rotation.

For rendering the grass, I just use this:

public void render(){
    Main.TerrainDemo.shader.start();
    glPushMatrix();
    glDisable(GL_LIGHTING);
    glTranslatef(location.x * TerrainDemo.scale, location.y, location.z * TerrainDemo.scale);
    TexturedModel texturedModel = TerrainDemo.texModel;
    RawModel model = texturedModel.getRawModel();
    GL30.glBindVertexArray(model.getVaoID());
    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, texturedModel.getTexture().getID());
    glScalef(10f, 10f, 10f);
    glColor4f(0, 0, 0, 0.5f);
    glDrawElements(GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
    GL20.glDisableVertexAttribArray(0);
    GL20.glDisableVertexAttribArray(1);
    GL30.glBindVertexArray(0);
    glEnable(GL_LIGHTING);
    glPopMatrix();
    Main.TerrainDemo.shader.stop();
}

To cut through code which you will probably not recognize/understand, I am basically just saying that glTranslatef(location.x * TerrainDemo.scale, location.y, location.z * TerrainDemo.scale) is the only thing that is setting the location. After translating, I simple set the scale (the size), and then draw it.

Wheras if I remove the glTranslatef() line, all the grass will just render in the same location: enter image description here

So to answer your question: use something like this (Psuedocode)

PUSH MATRIX HERE (glPushMatrix) SO TO NOT SAVE THE CURRENT TRANSLATION
USE GLTRANSLATEF ON LOCATION OF CURRENT OBJECT
RENDER/DRAW OBJECT
POP THE MATRIX

Unfortunately, looking through your code I could'nt find the specific issue that is actually causing it not to draw, meaning I cannot just say "Have xxx code and it will work", but I hope that it helped on how to move/rotate an object.

I am using VBOs just like you are for rendering the grass, ship, and trees (though I use a display list for terrain because I am lazy). My skype is joehot200 if you wish to discuss anything further.

Upvotes: 1

Related Questions