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.
I'm making a game in Java using LWJGL and slick_util recently I'm trying to implement a health bar that will hover on top of the player's head. Problem is, it is not positioning correctly. The health bar's bottom left corner(from where OpenGL starts drawing) always appears at the top right corner of the player's rectangle, and when the player moves in either x or y or both, the health bar moves away from the player in the same direction. I think it might be a problem with the glTranslatef or perhaps something silly that I missed.
Render method of Player:
protected void render() {
Draw.rect(x, y, 32, 32, tex); //Player texture drawn
Draw.rect(x, y + 33, 32, 15, 1, 0, 0); //Health bar drawn. x is the same as player's, but y is +33 because I want it to hover on top
}
Draw class:
package rpgmain;
import static org.lwjgl.opengl.GL11.*;
import org.newdawn.slick.opengl.*;
/**
*
* #author Samsung
*/
public class Draw {
public static void rect(float x, float y, float width, float height, Texture tex) {
glEnable(GL_TEXTURE_2D);
glTranslatef(x, y, 0);
glColor4f(1f, 1f, 1f, 1f);
tex.bind();
glBegin(GL_QUADS); //Specifies to the program where the drawing code begins. just to keep stuff neat. GL_QUADS specifies the type of shape you're going to be drawing.
{
//PNG format for images
glTexCoord2f(0,1); glVertex2f(0, 0); //Specify the vertices. 0, 0 is on BOTTOM LEFT CORNER OF SCREEN.
glTexCoord2f(0,0); glVertex2f(0, height); //2f specifies the number of args we're taking(2) and the type (float)
glTexCoord2f(1,0); glVertex2f(width, height);
glTexCoord2f(1,1); glVertex2f(width, 0);
}
glEnd();
glDisable(GL_TEXTURE_2D);
}
public static void rect(float x, float y, float width, float height, float r, float g, float b) {
glDisable(GL_TEXTURE_2D);
glTranslatef(x, y, 0);
glColor3f(r, g, b);
glBegin(GL_QUADS); //Specifies to the program where the drawing code begins. just to keep stuff neat. GL_QUADS specifies the type of shape you're going to be drawing.
{
glVertex2f(0, 0); //Specify the vertices. 0, 0 is on BOTTOM LEFT CORNER OF SCREEN.
glVertex2f(0, height); //2f specifies the number of args we're taking(2) and the type (float)
glVertex2f(width, height);
glVertex2f(width, 0);
}
glEnd();
glEnable(GL_TEXTURE_2D);
}
}
I think your problem is with matrices. When you call glTranslatef, you are transforming the OpenGL ModelView matrix. However, since OpenGL is a state-based machine, this transformation is preserved for further drawing events. The second rectangle will be translated twice. What you want to do is use the OpenGL matrix stack. I'll rewrite one of the draw methods here:
public static void rect(float x, float y, float width, float height, Texture tex) {
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(x, y, 0);
glColor4f(1f, 1f, 1f, 1f);
tex.bind();
glBegin(GL_QUADS);
{
glTexCoord2f(0,1); glVertex2f(0, 0);
glTexCoord2f(0,0); glVertex2f(0, height);
glTexCoord2f(1,0); glVertex2f(width, height);
glTexCoord2f(1,1); glVertex2f(width, 0);
}
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
The line glPushMatrix() will add a new matrix to the top of the stack. All transformations from this point on will be applied to the newly added matrix. Then, when you call glPopMatrix(), the matrix is discarded and the stack is returned to it's previous state.
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.
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);
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.