Problems dynamically moving VBO - java
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?
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.
Related
Blue/black borders around textures: OpenGL?
I have had this bug for awhile now. I can't seem to get rid of it. I am thinking I may just have to draw my quads as normal rectangles; and create the illusion they are "rotated" when they aren't (using the textures). Anyway, as you can see from the image, there are blue borders around all my tiles. I can't seem to get them to go away. I have tried other tilesheets and the same problem appears - except sometimes it's a black border. I will post a decent bit of code - just so you have all the resources necessary to understand what I am doing. My OpenGL setup code: //******** SET UP OPENGL ******* public void setUpOpenGL() { GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); // enable alpha blending GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glLoadIdentity(); GL11.glOrtho(0, 800, 0, 600, 1, -1); GL11.glMatrixMode(GL11.GL_MODELVIEW); } Drawing code: #Override public void drawTile(int tileX, int tileY, Texture atlas) { int tileXcoord, tileYcoord; tileXcoord = (tileX - tileY) * (TILE_XHALF); // TILE_WIDTH = 128 tileYcoord = (tileX + tileY) * (TILE_YHALF); // TILE_HEIGHT = 64 atlas.bind(); GL11.glColor3f(255, 255, 255); GL11.glBegin(GL11.GL_QUADS); { setTextureCoordinates(1); GL11.glVertex2f(tileXcoord, tileYcoord); setTextureCoordinates(2); GL11.glVertex2f(tileXcoord + TILE_XHALF, tileYcoord + TILE_YHALF); setTextureCoordinates(3); GL11.glVertex2f(tileXcoord + (TILE_XHALF * 2), tileYcoord); setTextureCoordinates(4); GL11.glVertex2f(tileXcoord + TILE_XHALF, tileYcoord - TILE_YHALF); } GL11.glEnd(); } //***** SET TEXTURE COORDINATES ***** public void setTextureCoordinates(int pos) { Rectangle rect = textureAtlas.getTexture(ID); float x = rect.getX(), y = rect.getY(); float height = rect.getHeight(), width = rect.getWidth(); switch (pos) { case 1 : GL11.glTexCoord2f(x, y + (height / 2)); //GL11.glTexCoord2f(0.0f, 0.03125f); //GL11.glTexCoord2f(0.0f, 0.5f); break; case 2: GL11.glTexCoord2f(x + (width / 2), y + height); //GL11.glTexCoord2f(0.03125f, 0.0625f); //GL11.glTexCoord2f(0.5f, 1f); break; case 3: GL11.glTexCoord2f(x + width, y + (height / 2)); //GL11.glTexCoord2f(0.0625f, 0.03125f); //GL11.glTexCoord2f(1f, 0.5f); break; case 4: GL11.glTexCoord2f(x + (width / 2), y); //GL11.glTexCoord2f(0.03125f, 0.0f); //GL11.glTexCoord2f(0.5f, 0.0f); break; } } Where drawing code gets its coordinates from (gridW = 9, gridH = 9, tilePixelWidth = 128, tilePixelHeight = 64, tilePercentOfWidth/Height comes out too 0.0625; total image resolution = 2048 x 1024): //**** GET ID SPECIFIC TEXTURE CELL ****** public Rectangle getTexture(int id) { int columnNumber = (int)(id % gridW); // Column of texture (using MOD so I can get textures beyond next column [next row]) int rowNumber = (int)(id / gridH); // Row number for texture // TODO: Get texture selection working! // Create bounding box float tilePercentOfWidth = this.tilePixelWidth / this.tPWidth; float tilePercentOfHeight = this.tilePixelHeight / this.tPHeight; float boxX = (columnNumber * (tilePixelWidth / tPWidth)); float boxY = (rowNumber * (tilePixelHeight / tPHeight)); float boxWidth = tilePercentOfWidth; float boxHeight = tilePercentOfHeight; // End bounding box creation Rectangle textureBounds = new Rectangle (boxX, boxY, boxWidth, boxHeight); return textureBounds; }
LWJGL Texture Unbinding
I'm currently working on a simple textured rectangle class using LWJGL (GL11). This is what I have so far in the draw method. glEnable(GL_TEXTURE_2D); color.bind(); glBegin(GL_QUADS); t.bind(); if (centered) { glTexCoord2d(0, 0); glVertex2d(x - (width / 2), y - (height / 2)); glTexCoord2d(t.getWidth(), 0); glVertex2d(x + (width / 2), y - (height / 2)); glTexCoord2d(t.getWidth(), t.getHeight()); glVertex2d(x + (width / 2), y + (height / 2)); glTexCoord2d(0, t.getHeight()); glVertex2d(x - (width / 2), y + (height / 2)); } else { glTexCoord2d(0, 0); glVertex2d(x, y); glTexCoord2d(t.getWidth(), 0); glVertex2d(x + width, y); glTexCoord2d(t.getWidth(), t.getHeight()); glVertex2d(x + width, y + height); glTexCoord2d(0, t.getHeight()); glVertex2d(x, y + height); } glEnd(); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); The problem is with the second to last line (glBindTexture(GL_TEXTURE_2D, 0)). If I leave this on, the image will display for a split second (probably one frame) and then turn solid white. If I comment this out, it will display, but always displays the last texture that was loaded. Any ideas?
I think it's because you are binding your texture between the glBegin() and glEnd() calls. This is invalid. I'm guessing when you leave the glBindTexture(GL_TEXTURE_2D, 0) call off, then the binding is taking effect the next frame. Not sure why it would work for one frame, though. You can use glGetError to see if there are any errors generated.
LWJGL 2D Hud Just Wont Budge
For some reason I cannot fo the life of me figuire out what i'm doing wrong here. I am tring to render a 2d orthographic hud ontop of my 3d stuff which is rendered via shaders not draw calls. I've spent almost 8 hours and well I suck, please help. There are no errors in the console! EngineWindow.bindAsRenderTarget(); //Set render target to display. glDepthMask(false); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_CLAMP); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); glPushMatrix(); glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, width, height, 0, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); System.out.println(this.x + " " + this.y + " " + this.width + " " + this.height); //Its at the right position too. GL13.glActiveTexture(GL13.GL_TEXTURE0); texture.bind(); //Binds blue texture with writing. glBegin(GL_QUADS); glVertex2i(x, y); glTexCoord2f(0f, 0f); glVertex2i(x, y+height); glTexCoord2f(0f, 1f); glVertex2i(x+width, y+height); glTexCoord2f(1f, 1f); glVertex2i(x+width, y); glTexCoord2f(1f, 0f); glEnd(); glPopMatrix(); glDepthFunc(GL_LESS); glDepthMask(true); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glDisable(GL_BLEND); glEnable(GL_DEPTH_CLAMP);
Texture not rotating LWJGL
I am using the LWJGL and Slick-Util libraries in an attempt to rotate a texture. Here is my code I'm using to try and rotate a texture. GL11.glBegin(GL11.GL_QUADS); GL11.glPushMatrix(); GL11.glTranslatef(x, y, 0); GL11.glRotatef(r, 1, 1, 0); GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture.getTextureID()); GL11.glTexCoord2f(0, 0); GL11.glVertex2f(x, y); GL11.glTexCoord2f(1, 0); GL11.glVertex2f(x + texture.getTextureWidth(), y); GL11.glTexCoord2f(1, 1); GL11.glVertex2f(x + texture.getTextureWidth(), y + texture.getTextureHeight()); GL11.glTexCoord2f(0, 1); GL11.glVertex2f(x, y + texture.getTextureHeight()); GL11.glPopMatrix(); GL11.glEnd(); It draws the texture perfectly fine at the x and y locations given, but when I pass in a degree, it does not rotate and just draws as if the rotation was zero. Does anyone know what I'm doing wrong? Thank you in advance. Edit: When I run this code with an 'r' of 180 or any other degree. This is what my screen looks like. The red circle image looks exactly like that as a regular un-rotated image.
I know it is a bit egotistical to answer your own questions, but after much research I have finally found my answer. Here is a working method that will rotate a slick-util texture according to an 'r' given in degrees. public static void drawTexture(Texture texture, int x, int y, int r) { int width = texture.getTextureWidth(); int height = texture.getTextureHeight(); GL11.glTranslatef(x + width / 2, y + height / 2, 0); GL11.glRotatef(r, 0, 0, 1); GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture.getTextureID()); GL11.glBegin(GL11.GL_QUADS); GL11.glTexCoord2f(0, 0); GL11.glVertex3f(-width / 2, -height / 2, 0); GL11.glTexCoord2f(1, 0); GL11.glVertex3f(width / 2, -height / 2, 0); GL11.glTexCoord2f(1, 1); GL11.glVertex3f(width / 2, height / 2, 0); GL11.glTexCoord2f(0, 1); GL11.glVertex3f(-width / 2, height / 2, 0); GL11.glEnd(); GL11.glLoadIdentity(); }
Why does gluProject not give the correct screen space coordinates with LWJGL
So I'm using gluProject to take the 3d coordinates and tell me where on the screen they rendered. The problem is I don't get the same coordinates with gluProject and where they actually ended up rendering. The weird part is that if the difference between the x, y, and z of the camera and the point i'm testing are equal (e.g. camera at 5,3,4 and point at 2,0,1) it gives the correct values. I'm using gluLookAt() for camera transforms. I have confirmed that the same matrices that I use for rendering are being passed in to gluProject. Below is my rendering code, camera.look(), and my part with gluProject: Rendering: glEnable(GL_LIGHTING); glEnable(GL_NORMAL_ARRAY); glViewport(0, 0, Display.getHeight(), Display.getHeight()); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(90.0f, 1, .1f, 1000f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); cam.look(); for (Cube cube : cubes) { cube.draw(); } grid.draw(); Camera.look(): void look() { calcPoints(xAng, yAng); gluLookAt(x, y, z, x + dx, y + dy, z + dz, 0, 1, 0); } part with gluProject: glViewport(0, 0, Display.getHeight(), Display.getHeight()); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(90.0f, 1, .1f, 1000f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); cam.look(); modelview = BufferUtils.createFloatBuffer(16); //floatbuffers, defined earlier projection = BufferUtils.createFloatBuffer(16); viewport = BufferUtils.createIntBuffer(16); FloatBuffer result = BufferUtils.createFloatBuffer(3); glGetFloat(GL_MODELVIEW_MATRIX, modelview); glGetFloat(GL_PROJECTION_MATRIX, projection); glGetInteger(GL_VIEWPORT, viewport); gluProject(1f, 0f, 0f, modelview, projection, viewport, result); //Utils.printFloatBuffer(projection); //Utils.printFloatBuffer(modelview); System.out.println(result.get(0) + " " + result.get(1) + " " + result.get(2));
Maybe try having the up vector at a right angle to the camera direction and position instead of (0, 1, 0) constantly.