Hey all!
I’m sure most of you hate getting 2D questions, but I’ve done searching for this topic, followed tutorials, etc, and I can’t seem to get it to work! I’m using the LWJGL conversion of NeHe’s tutorial #17 on Bitmap Fonts, but no dice.
Here’s the code for my BitmapFont class (it controls loading of the font and printing it):
package common.gui.font;
import common.gui.texture.*;
import java.awt.Color;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.awt.Graphics2D;
import java.awt.FontMetrics;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.ByteOrder;
import org.lwjgl.opengl.GL11;
public class BitmapFont {
private static final BitmapFont source = new BitmapFont();
private static final Color OPAQUE_WHITE = new Color(0xFFFFFFFF, true);
private static final Color TRANSPARENT_BLACK = new Color(0x00000000, true);
/** The display list id, where each character to print to the screen
* is added to this value. For example, listBase+65 would be the character
* 'A'.*/
private int listBase;
/** The texture for this font */
private Texture texture;
/** The current font */
private String currentFont = "Courier New";
private BitmapFont() {
init();
}
private void init() {
buildFont();
buildDisplayLists();
}
private void buildFont() {
try {
texture = TextureMgr.get().getTexture("res/Font.bmp");
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
private int testid;
/**
* Create the display lists used for drawing characters to the screen.
*/
private void buildDisplayLists() {
listBase = GL11.glGenLists(256); // Storage For 256 Characters
testid = GL11.glGenLists(1);
float x = (float)(texture.getWidth()/2);
float y = (float)(texture.getHeight()/2);
x = 2.0f;
y = 2.0f;
GL11.glNewList(testid, GL11.GL_COMPILE);
texture.bind();
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex3f(x, -y, 0.0f);
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex3f(x, y, 0.0f);
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex3f(-x, y, 0.0f);
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex3f(-x, -y, 0.0f);
GL11.glEnd();
GL11.glEndList();
/* Generate the display lists. One for each character in the standard/extended ASCII chart.
*/
float textureDelta = 1.0f / 16.0f;
for(int i=0;i<256;i++) {
float u = ((float)(i % 16)) / 16.0f;
float v = 1.f - (((float)(i / 16)) / 16.0f);
GL11.glNewList(listBase + i, GL11.GL_COMPILE);
texture.bind();
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(u, v - textureDelta);
GL11.glVertex3f(-0.0450f, -0.0450f, 0.0f);
GL11.glTexCoord2f((u + textureDelta), v - textureDelta);
GL11.glVertex3f(0.0450f, -0.0450f, 0.0f);
GL11.glTexCoord2f((u + textureDelta), v);
GL11.glVertex3f(0.0450f, 0.0450f, 0.0f);
GL11.glTexCoord2f(u, v);
GL11.glVertex3f(-0.0450f, 0.0450f, 0.0f);
GL11.glEnd();
GL11.glEndList();
}
}
public static BitmapFont get() {
return source;
}
/**
* Prepare OpenGL for Orthographic rendering. The method will ensure that
* all states are saved.
*/
private void enterOrtho() {
GL11.glDisable(GL11.GL_DEPTH_TEST);
// Load the projection mode and save it's current state
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPushMatrix();
GL11.glLoadIdentity();
// Set up orthographic projection mode
GL11.glOrtho(0, 800, 0, 600, -1, 1);
// Enter model view mode
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glPushMatrix();
GL11.glLoadIdentity();
}
/**
* Leave Orthographic rendering in OpenGL. Will restore all states saved
* by enterOrtho().
*/
private void leaveOrtho() {
// Restore the state of the projection mode
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPopMatrix();
// Restore the state of the model view mode
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glPopMatrix();
GL11.glEnable(GL11.GL_DEPTH_TEST);
}
public void print(String msg, float x, float y) {
enterOrtho();
GL11.glTranslatef(100.0f, 100.0f, 0.0f);
// Ignore null value
if (msg != null) {
texture.bind();
// Print the characters
for(int i = 0; i < msg.length(); i++) {
GL11.glCallList(listBase + msg.charAt(i));
GL11.glTranslatef(1.0f, 0.0f, 0.0f);
}
}
leaveOrtho();
}
}
You might notice the TextureMgr.get().getTexture(“res/Font.bmp”); bit in there. I basically took the image loading code out of here and put it in another class to make it all nicer. Also, the Texture object here is basically a class to hold the width/height of the image used for the texture, and to hold the texture id generated by the OpenGL engine. The texture.bind() method just calls GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.id);, where this.id is the texture id given by OpenGL.
The wierd thing about the above code is that, if I remove the enterOrtho() and leaveOrtho() methods, the text displays fine! Albeit I have to change the glTranslatef(100.0f, 100.0f, 0.0f); call before the text printing to glTranslatef(0.0f, 0.0f, -4.0f);. I’ve also tried changing the ordering of the parameters in the glOrtho(…) call (i.e. from GL11.glOrtho(0, 800, 0, 600, -1, 1); to GL11.glOrtho(0, 800, 600, 0, -1, 1);), but no dice).
Does anyone have any idea what’s up here? I’m quite flustered at the moment. I decided to ask you guys for help before I threw my monitor out the window haha.
Thanks in advance!
ps: I think I’ve included all the relevant info, if not tho lemme know and I’ll give whatever you need!