Related
So I'm using LWJGL3 and I'm trying to render a cube, however I have 2 issues:
The orthographic camera is too close and I tried increasing/decreasing the values in the parameters but none achieve the effect I want which is to eventually show lots of cubes stacked side-by-side so it needs to be zoomed out,
The cube renders in 2D, I would like it to initially look 2D but then I will use keys to rotate the camera so you can get a 3D view also.
Here is the code I have so far:
package io.ryankshah;
import io.ryankshah.util.Constants;
import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;
import java.nio.*;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;
public class Window
{
// Create a keycallback to check for key actions
private static GLFWKeyCallback keyCallback = new GLFWKeyCallback()
{
#Override
public void invoke(long window, int key, int scancode, int action, int mods) {
// If ESC is pressed, close the window
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
};
private static long window;
private static void init() {
glfwSetErrorCallback(Constants.ERROR_CALLBACK);
// Initialize GLFW
if(!glfwInit()) throw new IllegalStateException("Failed to initialize GLFW");
// Create window
window = glfwCreateWindow(Constants.WINDOW_WIDTH, Constants.WINDOW_HEIGHT,
Constants.WINDOW_TITLE, 0, 0);
if(window == 0) {
glfwTerminate();
throw new RuntimeException("Failed to create the GLFW window");
}
// Center the window
GLFWVidMode vm = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window, (vm.width() - Constants.WINDOW_WIDTH) / 2,
(vm.height() - Constants.WINDOW_HEIGHT) / 2);
// Create OpenGL context
glfwMakeContextCurrent(window);
GL.createCapabilities();
// Enbale vsync
glfwSwapInterval(1);
// Set key callback
glfwSetKeyCallback(window, keyCallback);
}
private static void render() {
/* Declare buffers for using inside the loop */
IntBuffer width = MemoryUtil.memAllocInt(1);
IntBuffer height = MemoryUtil.memAllocInt(1);
/* Loop until window gets closed */
while (!glfwWindowShouldClose(window)) {
float ratio;
/* Get width and height to calcualte the ratio */
glfwGetFramebufferSize(window, width, height);
ratio = width.get() / (float) height.get();
/* Rewind buffers for next get */
width.rewind();
height.rewind();
/* Set viewport and clear screen */
glViewport(0, 0, width.get(), height.get());
glClear(GL_COLOR_BUFFER_BIT);
/* Set ortographic projection */
float zoom = 50.0f;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-ratio, ratio, -1f, 1f, 1f, -1f);
glMatrixMode(GL_MODELVIEW);
/* Rotate matrix */
glLoadIdentity();
glRotatef((float) glfwGetTime() * 50f, 0f, 0f, 1f);
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_COLOR_BUFFER_BIT);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glColor3f(1, 0, 0);
GL11.glBegin(GL11.GL_QUADS);
GL11.glColor3f(0.0f,1.0f,0.0f); // Set The Color To Green
GL11.glVertex3f( 1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Top)
GL11.glVertex3f(-1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Top)
GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Quad (Top)
GL11.glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Quad (Top)
GL11.glColor3f(1.0f,0.5f,0.0f); // Set The Color To Orange
GL11.glVertex3f( 1.0f,-1.0f, 1.0f); // Top Right Of The Quad (Bottom)
GL11.glVertex3f(-1.0f,-1.0f, 1.0f); // Top Left Of The Quad (Bottom)
GL11.glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Bottom)
GL11.glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Bottom)
GL11.glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
GL11.glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Front)
GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Front)
GL11.glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Left Of The Quad (Front)
GL11.glVertex3f( 1.0f,-1.0f, 1.0f); // Bottom Right Of The Quad (Front)
GL11.glColor3f(1.0f,1.0f,0.0f); // Set The Color To Yellow
GL11.glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Back)
GL11.glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Back)
GL11.glVertex3f(-1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Back)
GL11.glVertex3f( 1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Back)
GL11.glColor3f(0.0f,0.0f,1.0f); // Set The Color To Blue
GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Left)
GL11.glVertex3f(-1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Left)
GL11.glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Left)
GL11.glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Right Of The Quad (Left)
GL11.glColor3f(1.0f,0.0f,1.0f); // Set The Color To Violet
GL11.glVertex3f( 1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Right)
GL11.glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Right)
GL11.glVertex3f( 1.0f,-1.0f, 1.0f); // Bottom Left Of The Quad (Right)
GL11.glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Right)
GL11.glEnd();
GL11.glLoadIdentity();
/* Swap buffers and poll Events */
glfwSwapBuffers(window);
glfwPollEvents();
/* Flip buffers for next loop */
width.flip();
height.flip();
}
MemoryUtil.memFree(width);
MemoryUtil.memFree(height);
}
private static void loop() {
render();
}
public static void main(String[] args) {
init();
loop();
glfwDestroyWindow(window);
keyCallback.free();
glfwTerminate();
Constants.ERROR_CALLBACK.free();
}
}
Also if anyone has pointers as to the way I have structured my program or any calls that are unnecessary, would be great to have some sort of boiler-plate knowledge of how I should structure my lwjgl program.
I am trying to create a cube, because that is the thing to do in OpenGl 2.9. However, I had a cube rendering originally, but I am trying to make my design a little better, but I am unable to see my cube now. Help me see my cube. The code will be below. I am not getting any errors, just unable to see my cube.
import java.awt.*;
import org.lwjgl.*;
import javax.swing.*;
public class Scene
{
private static boolean run = false;
private static int width = 640;
private static int height = 480;
long lastFrame; //time at last frame
int fps;
long lastFPS;
/** position of quad */
float x = 1, y = 1, z = 1; //400,300,400
/** angle of quad rotation */
float rotation = 0;
public void start()
{
try
{
Display.setDisplayMode(new DisplayMode(width, height));
Display.create();
} catch (LWJGLException e)
{
e.printStackTrace();
System.exit(0);
}
initGL(); // init OpenGL
getDelta(); // call once before loop to initialise lastFrame
lastFPS = getTime(); // call before loop to initialise fps timer
while (run == true)
{
int delta = getDelta();
update(delta);
renderGL();
Display.update();
Display.sync(60); // cap fps to 60fps
if (Keyboard.isKeyDown(Keyboard.KEY_Q))
{
break;
}
}
Display.destroy();
System.exit(0);
}
public void update(int delta) {
// rotate quad
rotation += 0.15f * delta;
if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) x -= 0.35f * delta;
if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) x += 0.35f * delta;
if (Keyboard.isKeyDown(Keyboard.KEY_UP)) y -= 0.35f * delta;
if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) y += 0.35f * delta;
// keep quad on the screen
if (x < 0) x = 0;
if (x > 800) x = 800;
if (y < 0) y = 0;
if (y > 600) y = 600;
updateFPS(); // update FPS Counter
}
public void renderGL() {
// Clear The Screen And The Depth Buffer
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glColor3f(1, 0, 0);
// draw quad
GL11.glPushMatrix();
GL11.glTranslatef(x, y, z);
GL11.glRotatef(rotation, 0f, 0f, 1f);
GL11.glTranslatef(-x, -y, z);
GL11.glBegin(GL11.GL_QUADS);
GL11.glColor3f(0.0f,1.0f,0.0f); // Set The Color To Green
GL11.glVertex3f( x, y,-z); // Top Right Of The Quad (Top)
GL11.glVertex3f(-x, y,-z); // Top Left Of The Quad (Top)
GL11.glVertex3f(-x, y, z); // Bottom Left Of The Quad (Top)
GL11.glVertex3f( x, y, z); // Bottom Right Of The Quad (Top)
GL11.glColor3f(1.0f,0.5f,0.0f); // Set The Color To Orange
GL11.glVertex3f( x, -y, z); // Top Right Of The Quad (Bottom)
GL11.glVertex3f(-x, -y, z); // Top Left Of The Quad (Bottom)
GL11.glVertex3f(-x, -y,-z); // Bottom Left Of The Quad (Bottom)
GL11.glVertex3f( x,-y,-z); // Bottom Right Of The Quad (Bottom)
GL11.glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
GL11.glVertex3f( x, y, z); // Top Right Of The Quad (Front)
GL11.glVertex3f(-x, y, z); // Top Left Of The Quad (Front)
GL11.glVertex3f(-x,-y, z); // Bottom Left Of The Quad (Front)
GL11.glVertex3f( x,-y, z); // Bottom Right Of The Quad (Front)
GL11.glColor3f(1.0f,1.0f,0.0f); // Set The Color To Yellow
GL11.glVertex3f( x,-y,-z); // Bottom Left Of The Quad (Back)
GL11.glVertex3f(-x,-y,-z); // Bottom Right Of The Quad (Back)
GL11.glVertex3f(-x, y,-z); // Top Right Of The Quad (Back)
GL11.glVertex3f( x, y,-z); // Top Left Of The Quad (Back)
GL11.glColor3f(0.0f,0.0f,1.0f); // Set The Color To Blue
GL11.glVertex3f(-x, y, z); // Top Right Of The Quad (Left)
GL11.glVertex3f(-x, y,-z); // Top Left Of The Quad (Left)
GL11.glVertex3f(-x,-y,-z); // Bottom Left Of The Quad (Left)
GL11.glVertex3f(-x,-y, z); // Bottom Right Of The Quad (Left)
GL11.glColor3f(1.0f,0.0f,1.0f); // Set The Color To Violet
GL11.glVertex3f( x, y,-z); // Top Right Of The Quad (Right)
GL11.glVertex3f( x, y, z); // Top Left Of The Quad (Right)
GL11.glVertex3f( x,-y, z); // Bottom Left Of The Quad (Right)
GL11.glVertex3f( x,-y,-z); // Bottom Right Of The Quad (Right)
// GL11.glVertex2f(x - 50, y - 50);
// GL11.glVertex2f(x + 50, y - 50);
// GL11.glVertex2f(x + 50, y + 50);
// GL11.glVertex2f(x - 50, y + 50);
GL11.glEnd();
GL11.glPopMatrix();
}
/**
* Calculate how many milliseconds have passed
* since last frame.
*
* #return milliseconds passed since last frame
*/
public int getDelta() {
long time = getTime();
int delta = (int) (time - lastFrame);
lastFrame = time;
return delta;
}
/**
* Calculate the FPS and set it in the title bar
*/
public void updateFPS() {
if (getTime() - lastFPS > 1000) {
Display.setTitle("FPS: " + fps);
fps = 0;
lastFPS += 1000;
}
fps++;
}
/**
* Get the accurate system time
*
* #return The system time in milliseconds
*/
public long getTime() {
return (Sys.getTime() * 1000) / Sys.getTimerResolution();
}
public void initGL() {
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 800, 0, 600, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
}
public static void main(String[] Args)
{
final JFrame info = new JFrame();
JButton button = new JButton();
JLabel infoText1 = new JLabel();
JLabel infoText2 = new JLabel();
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
button.setText("Acknowledge");
button.setSize(20, 10);
infoText1.setText("Press Q to quit");
infoText2.setText("Click Acknowledge to start simulation");
info.setTitle("Operator's Manual");
info.setLayout(new FlowLayout());
info.add(infoText1);
info.add(infoText2);
info.setSize(240, 120);
info.setLocation(dim.width/2-info.getSize().width/2, dim.height/2-info.getSize().height/2);
info.add(button);
info.setVisible(true);
button.addActionListener(new java.awt.event.ActionListener()
{
#Override
public void actionPerformed(java.awt.event.ActionEvent acknowledge)
{
run = true;
Scene sceneStart = new Scene();
sceneStart.start();
}
});
}
}
EDIT: Your near and far values for glOrtho are backwards. Note that your later translate of 7 z-units will also move your object outside of the volume defined by glOrtho, which will cause it not to be drawn.
You are undoing your own translate in your model view matrix.
GL11.glTranslatef(1.5f, 0.0f, -7.0f);
GL11.glLoadIdentity(); // << reloads identity matrix, overriding the translate.
Correct is:
// Ensure model view matrix is starting is nice fresh state.
GL11.glLoadIdentity();
// Put the quad where you want it.
GL11.glTranslatef(1.5f, 0.0f, -7.0f);
I am running into an issue here. I set up a square projectile with a velocity x an y, and draw the actual square to the location, by setting the vertex positions there like so.
Code:
vertices.put(new float[] { x1, y1, 1, 1, 1, 1, 0.0f, 1.0f,
x2, y2, 1, 1, 1, 1, 1.0f, 1.0f,
x3, y3, 1, 1, 1, 1, 1.0f, 0.0f,
x4, y4, 1, 1, 1, 1, 0.0f, 0.0f });
// x y r g b A u|s v|t
where all the x's are locations of corners that i pass in.
I then move this rectangle (l2rArrow) along the x & y axis, and have the screen follow it:
boolean hasTranslated = false;
if (!l2rArrow.isFired) { // if the arrow has not yet been fired we render it thus
gl.glPushMatrix(); //save our state
gl.glTranslatef(l2rArrow.GetToOriginX, l2rArrow.GetToOriginY, 0f); // translate to origin 0,0,0
gl.glRotatef(LBow.getAngle(), 0f, 0f, 1f); //rotate
gl.glTranslatef(-l2rArrow.GetToOriginX, -l2rArrow.GetToOriginY, 0f); // translate to where we want to draw it
texture.bind(gl, Texture.TEXTURE_L2RARROW);
mRect = new MeshRect(l2rArrow.getMyRect());
mRect.Draw(GL10.GL_TRIANGLES, gl);
gl.glPopMatrix(); //return to saved state
} else { // the arrow has been fired so we need to render it like this and have the "camera" follow it
hasTranslated = true;
gl.glPushMatrix();
gl.glLoadIdentity();
float camX = (float) ((l2rArrow.startX - l2rArrow.PosX));
float camY = (float) ((l2rArrow.startY - l2rArrow.PosY));
if (camY > 0) { camY = 0;}
if (camX < -4800) { camX = -4800;}
gl.glTranslatef(camX, camY,0f);
l2rArrow.Update(deltaTime);
texture.bind(gl, Texture.TEXTURE_L2RARROW);
mRect = new MeshRect(l2rArrow.getMyRect());
mRect.Draw(GL10.GL_TRIANGLES, gl);
if (l2rArrow.hasCollided) {
//run collision code for detecting a hit and ending turn
}
}
this works as well. When the projectile is fired we will follow it perfectly. Now though I want the arrow head to point at the angle the arrow is traveling. So I need to rotate the arrow to in mid flight. I tried translating this arrow back to 0,0 rotating it, and the putting it back but when i put the arrow back it draws on the coordinates of a rotated plane.
} else {
hasTranslated = true;
gl.glPushMatrix();
gl.glLoadIdentity();
float camX = (float) ((l2rArrow.startX - l2rArrow.PosX));
float camY = (float) ((l2rArrow.startY - l2rArrow.PosY));
if (camY > 0) { camY = 0;}
if (camX < -4800) { camX = -4800;}
gl.glTranslatef(camX, camY,0f);
gl.glPushMatrix();
gl.glTranslatef(l2rArrow.GetToOriginX, l2rArrow.GetToOriginY, 0f); // translate to origin 0,0,0
gl.glRotatef((float) l2rArrow.getAngle(), 0f, 0f, 1f); //rotate
gl.glTranslatef(-l2rArrow.GetToOriginX, -l2rArrow.GetToOriginY, 0f);
l2rArrow.Update(deltaTime);
texture.bind(gl, Texture.TEXTURE_L2RARROW);
mRect = new MeshRect(l2rArrow.getMyRect());
mRect.Draw(GL10.GL_TRIANGLES, gl);
gl.glPopMatrix();
if (l2rArrow.hasCollided) {
//run collision code for detecting a hit and ending turn
}
}
I understand this. How do I rotate the arrow, and then move it back into position on a non-rotated plane?
The arrow rests when it comes to Y=0, and as of right now Y=0 runs at the angle of the rotation.
After much research and deliberation I decided to switch the way I place objects in my world.
I now use what seems to be the Normal method which is to glTranslate them into place.
Everything now works perfectly.
Apparently the way I was doing it before was getting screwed up because drawing the vertex directly into the space you want it (not drawing it at the origin and then translating it) can get pretty messy.
I got this code for billboarding I created (With the help of others, and a nehe tutorial), but it seems that when I move my sprites from 0,0,0 it stops working correctly, for example the closer I get to a sprite that's at 50,0,50 the more sideways it gets.
Any idea how to make the sprites billboard properly when not on 0,0,0?
Here is the code:
public void drawBillBoardSprite(Texture texture, Vector3f sprPos, float r, float g, float b, int sprWidth, int sprHeight){
// store the current model matrix
GL11.glPushMatrix();
// bind to the appropriate texture for this sprite
texture.bind();
Vector3f look = new Vector3f(0,0,0);
Vector3f.sub(player.pos, sprPos, look);
look.normalise();
Vector3f right = new Vector3f(0,0,0);
Vector3f.cross(new Vector3f(0,1,0) /* <-- default up vector */, look, right);
right.normalise();
Vector3f up = new Vector3f(0,0,0);
Vector3f.cross(look, right, up);
up.normalise();
Matrix4f m = new Matrix4f();
m.m00 = right.x;
m.m01 = right.y;
m.m02 = right.z;
m.m03 = 0;
m.m10 = up.x;
m.m11 = up.y;
m.m12 = up.z;
m.m13 = 0;
m.m20 = look.x;
m.m21 = look.y;
m.m22 = look.z;
m.m23 = 0;
m.m30 = sprPos.x;
m.m31 = sprPos.y;
m.m32 = sprPos.z;
m.m33 = 1;
java.nio.FloatBuffer fb = BufferUtils.createFloatBuffer(32);
m.store(fb);
fb.flip();
GL11.glMultMatrix(fb);
// draw a quad textured to match the sprite
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0,0); GL11.glVertex3f( - (sprWidth/2), (sprHeight/2), 0); // Top left Of The Quad (Left)
GL11.glTexCoord2f(texture.getWidth(), 0); GL11.glVertex3f( + (sprWidth/2), (sprHeight/2), 0); // Top right Of The Quad (Left)
GL11.glTexCoord2f(texture.getWidth(), texture.getHeight()); GL11.glVertex3f( + (sprWidth/2), -(sprHeight/2), 0); // Bottom right Of The Quad (Left)
GL11.glTexCoord2f(0, texture.getHeight()); GL11.glVertex3f( - (sprWidth/2), -(sprHeight/2), 0); // Bottom left Of The Quad (Left)
GL11.glEnd();
// restore the model view matrix to prevent contamination
GL11.glPopMatrix();
}
Edit: tried this code based on Knetic's answer, but it didn't even rotate the sprites towards the camera. Here is the code I used:
public void drawBillBoardSprite(Texture texture, Vector3f sprPos, float r, float g, float b, int sprWidth, int sprHeight){
// store the current model matrix
GL11.glPushMatrix();
FloatBuffer tempViewBuf = BufferUtils.createFloatBuffer(16);
GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, tempViewBuf);
float[] tempView = new float[16];
for(int i = 0; i < 16; i++){
tempView[i] = tempViewBuf.get(i);
}
float[] modelView = new float[6];
modelView[0] = tempView[0] - tempView[1];
modelView[1] = tempView[0] + tempView[1];
modelView[2] = tempView[4] - tempView[5];
modelView[3] = tempView[4] + tempView[5];
modelView[4] = tempView[8] - tempView[9];
modelView[5] = tempView[8] + tempView[9];
// bind to the appropriate texture for this sprite
texture.bind();
// draw a quad textured to match the sprite
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0,0); GL11.glVertex3f( - (sprWidth/2) + modelView[1], (sprHeight/2) + modelView[3], 0 + modelView[5]); // Top left Of The Quad (Left)
GL11.glTexCoord2f(texture.getWidth(), 0); GL11.glVertex3f( + (sprWidth/2) + modelView[0], (sprHeight/2) + modelView[2], 0 + modelView[4]); // Top right Of The Quad (Left)
GL11.glTexCoord2f(texture.getWidth(), texture.getHeight()); GL11.glVertex3f( + (sprWidth/2) + modelView[1], -(sprHeight/2)+ modelView[3], 0 + modelView[5]); // Bottom right Of The Quad (Left)
GL11.glTexCoord2f(0, texture.getHeight()); GL11.glVertex3f( - (sprWidth/2) + modelView[0], -(sprHeight/2)+ modelView[2], 0 + modelView[4]); // Bottom left Of The Quad (Left)
GL11.glEnd();
// restore the model view matrix to prevent contamination
GL11.glPopMatrix();
}
I dug up an old project of mine which had billboarded particles, and my solution was this.
static float[] tempView;
// ...additional render stuff up here
// If there's anything that needs billboarding
if(getParticleTop() > 0)
{
glGetFloatv(GL_MODELVIEW_MATRIX, tempView);
modelView[0] = tempView[0] - tempView[1];
modelView[1] = tempView[0] + tempView[1];
modelView[2] = tempView[4] - tempView[5];
modelView[3] = tempView[4] + tempView[5];
modelView[4] = tempView[8] - tempView[9];
modelView[5] = tempView[8] + tempView[9];
// ... render each particle
}
And in the individual particle renders
float* modelView = renderer->getModelView();
glBegin(GL_QUADS);
{
glTexCoord2f(0, 1);
glVertex3f(owner->x - (modelView[1] * scale), owner->y - (modelView[3] * scale), owner->z - (modelView[5] * scale));
glTexCoord2f(0, 0);
glVertex3f(owner->x + (modelView[0] * scale), (owner->y + modelView[2] * scale), owner->z + (modelView[4] * scale));
glTexCoord2f(1, 0);
glVertex3f(owner->x + (modelView[1] * scale), owner->y + (modelView[3] * scale), owner->z + (modelView[5] * scale));
glTexCoord2f(1, 1);
glVertex3f(owner->x - (modelView[0] * scale), owner->y + (modelView[2] * scale), owner->z - (modelView[4] * scale));
}
glEnd();
Looking on it now, i see that i wasn't precaching scalar calculation and was using GL_QUADS instead of unrolling it myself, but i do know this works with all angles and all sizes.
I remember going through NeHe's tutorial and finding the same problem, this solution gave up on NeHe and googled out someone else who suggested the GL modelview method, which saves calculations (and time, if your video architecture is close enough to your processor).
I hope this helps.
EDIT; I should have mentioned, but the layout i used in this project was to have the entity class separate from model classes, so each entity could switch or share models as required; so this is a billboard model class, and owner->x/y/z refer to the entity who owns that model's position.
Just had to use a different way of billboarding:
public void drawBillBoardSprite(Texture texture, Vector3f sprPos, float r, float g, float b, int sprWidth, int sprHeight){
// store the current model matrix
GL11.glPushMatrix();
GL11.glTranslatef(sprPos.x, 0, sprPos.z);
// bind to the appropriate texture for this sprite
texture.bind();
FloatBuffer modelview = BufferUtils.createFloatBuffer(16);
// get the current modelview matrix
GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelview);
// Note that a row in the C convention is a column
// in OpenGL convention (see the red book, pg.106 in version 1.2)
// right vector is [1,0,0] (1st column)
// lookAt vector is [0,0,1] (3d column)
// leave the up vector unchanged (2nd column)
// notice the increment in i in the first cycle (i+=2)
for(int i=0; i<3; i+=2 )
for(int j=0; j<3; j++ ) {
if ( i==j )
modelview.put(i*4+j, 1.0f);
else
modelview.put(i*4+j, 0.0f);
}
// set the modelview matrix
GL11.glLoadMatrix(modelview);
// draw a quad textured to match the sprite
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0,0); GL11.glVertex3f( - (sprWidth/2), (sprHeight/2), 0); // Top left Of The Quad (Left)
GL11.glTexCoord2f(texture.getWidth(), 0); GL11.glVertex3f( + (sprWidth/2), (sprHeight/2), 0); // Top right Of The Quad (Left)
GL11.glTexCoord2f(texture.getWidth(), texture.getHeight()); GL11.glVertex3f( + (sprWidth/2), -(sprHeight/2), 0); // Bottom right Of The Quad (Left)
GL11.glTexCoord2f(0, texture.getHeight()); GL11.glVertex3f( - (sprWidth/2), -(sprHeight/2), 0); // Bottom left Of The Quad (Left)
GL11.glEnd();
// restore the model view matrix to prevent contamination
GL11.glPopMatrix();
}
When I try to display text on my 3d scene it doesn't display the rest of the scene. What do I have to do to fix this? I tried the answer here: Opengl drawing a 2d overlay on a 3d scene problem but it didn't work for me. Here is my code:
public class GunCraft {
private boolean done = false;
Texture texture;
Camera cam;
private float yspeed;
float legAngle;
float playerX = 0;
float playerZ = 0;
float playerSpeed = 0.01f;
float enemyX = 0;
float enemyZ = 0;
private TrueTypeFont font2;
public static void main(String args[]) {
GunCraft gc = new GunCraft();
gc.run();
}
public void run() {
try {
init();
while (!done) {
mainloop();
render();
Display.update();
}
cleanup();
}
catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
/**
* Very basic for first lesson. Just check for escape key or user
* clicking to close the window.
*/
private void mainloop() {
if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) { // Exit if Escape is pressed
done = true;
}
if(Display.isCloseRequested()) { // Exit if window is closed
done = true;
}
}
/**
* For rendering all objects to the screen
* #return boolean for success or not
*/
private void render() {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
font2.drawString(100, 100, "NICE LOOKING FONTS!", Color.green);
loadIdentity();
//GL11.glRotatef(yspeed,0.0f,1.0f,0.0f);
drawRect(texture, 1f, 1f, 1f);
}
public void loadIdentity(){
GL11.glLoadIdentity();
GL11.glMatrixMode(GL11.GL_MODELVIEW);
float camAngle = (float) Math.atan2(playerX, playerZ);
float radius = 5;
GLU.gluLookAt(playerX + (float)(Math.sin(camAngle) * radius), 0, playerZ + (float)(Math.cos(camAngle) * radius), 0, 0, 0, 0, 1, 0);
//GL11.glGetMatrix();
}
public void drawRect(Texture texture, float width, float height, float depth){
texture.bind();
GL11.glBegin(GL11.GL_QUADS); // Start Drawing Quads
// Front Face
GL11.glNormal3f( 0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3f(-width, -height, depth); // Point 1 (Front)
GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3f( width, -height, depth); // Point 2 (Front)
GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3f( width, height, depth); // Point 3 (Front)
GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3f(-width, height, depth); // Point 4 (Front)
// Back Face
GL11.glNormal3f( 0.0f, 0.0f,-1.0f); // Normal Pointing Away From Viewer
GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3f(-width, -height, -depth); // Point 1 (Back)
GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3f(-width, height, -depth); // Point 2 (Back)
GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3f( width, height, -depth); // Point 3 (Back)
GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3f( width, -height, -depth); // Point 4 (Back)
// Top Face
GL11.glNormal3f( 0.0f, 1.0f, 0.0f); // Normal Pointing Up
GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3f(-width, height, -depth); // Point 1 (Top)
GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3f(-width, height, depth); // Point 2 (Top)
GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3f( width, height, depth); // Point 3 (Top)
GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3f( width, height, -depth); // Point 4 (Top)
// Bottom Face
GL11.glNormal3f( 0.0f,-1.0f, 0.0f); // Normal Pointing Down
GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3f(-width, -height, -depth); // Point 1 (Bottom)
GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3f( width, -height, -depth); // Point 2 (Bottom)
GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3f( width, -height, depth); // Point 3 (Bottom)
GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3f(-width, -height, depth); // Point 4 (Bottom)
// Right face
GL11.glNormal3f( 1.0f, 0.0f, 0.0f); // Normal Pointing Right
GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3f( width, -height, -depth); // Point 1 (Right)
GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3f( width, height, -depth); // Point 2 (Right)
GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3f( width, height, depth); // Point 3 (Right)
GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3f( width, -height, depth); // Point 4 (Right)
// Left Face
GL11.glNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left
GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3f(-width, -height, -depth); // Point 1 (Left)
GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3f(-width, -height, depth); // Point 2 (Left)
GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3f(-width, height, depth); // Point 3 (Left)
GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3f(-width, height, -depth); // Point 4 (Left)
GL11.glEnd(); // Done Drawing The Quad
}
/**
* Create a window for all display
* #throws Exception
*/
private void createWindow() throws Exception {
Display.setFullscreen(false);
Display.setDisplayMode(new DisplayMode(640, 480));
Display.setTitle("GunCraft - By William Starkovich");
Display.create();
}
/**
* Initialize the environment
* #throws Exception
*/
private void init() throws Exception {
createWindow();
try{
FileInputStream fis;
fis = new FileInputStream(new File("font.ttf"));
Font awtFont2 = Font.createFont(Font.TRUETYPE_FONT, fis);
awtFont2 = awtFont2.deriveFont(24f); // set font size
font2 = new TrueTypeFont(awtFont2, false);
} catch (Exception e) {
e.printStackTrace();
}
initGL(640,480);
}
/**
* Initialize OpenGL
*
*/
private void initGL(int width, int height) {
GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
GL11.glShadeModel(GL11.GL_SMOOTH); // Enable Smooth Shading
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background
GL11.glClearDepth(1.0); // Depth Buffer Setup
GL11.glEnable(GL11.GL_DEPTH_TEST); // Enables Depth Testing
GL11.glDepthFunc(GL11.GL_LEQUAL); // The Type Of Depth Testing To Do
GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
GL11.glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
GLU.gluPerspective(
45.0f,
(float) Display.getDisplayMode().getWidth() / (float) Display.getDisplayMode().getHeight(),
0.1f,
100.0f);
//GLU.gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz)
GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
// Really Nice Perspective Calculations
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
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, width, height, 0, -1000, 1000);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glDisable(GL11.GL_CULL_FACE);
try {
texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("tex.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Cleanup all the resources.
*
*/
private void cleanup() {
Display.destroy();
}
}
You should really review how OpenGL work you have a bunch of truncated statements in your code that get overwritten a few lines later. You have to get what "OpenGL is a state machine" means. If you don't want to deal with that you should find a more abstract game engine that handles all the draw-calls.
I just copypastad your render() and loadIdentity() methods into something working but this is not the real solution. (Recreating the Projection matrices each frame instead of saving/loading them is not smart). Also OpenGL 1.1 is terribly deprecated and using immediate mode is strongly discouraged.
private void render() {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
loadIdentity();
GL11.glRotatef(yspeed++,0.0f,1.0f,0.0f);
drawRect(texture, 1f, 1f, 1f);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 640, 480, 0, -1000, 1000);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
font2.drawString(100, 100, "NICE LOOKING FONTS!", Color.green);
}
public void loadIdentity(){
GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
GL11.glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
GLU.gluPerspective(
45.0f,
(float) Display.getDisplayMode().getWidth() / (float) Display.getDisplayMode().getHeight(),
0.1f,
100.0f);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
float camAngle = (float) Math.atan2(playerX, playerZ);
float radius = 5;
GLU.gluLookAt(playerX + (float)(Math.sin(camAngle) * radius), 0, playerZ + (float)(Math.cos(camAngle) * radius), 0, 0, 0, 0, 1, 0);
//GL11.glGetMatrix();
}