Reputation: 103
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
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:
Wheras without the line, the grass is not rotated at all:
Same with the ship. Using glRotatef(40, -1, 0, 0) returns this result:
Wheras without the line it just returns flat:
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:
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