2D fonts using Ortho - text doesn't display

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!

hi again!

I ended up finding code similar to mine that worked - looks like the problem was that my quads were built for a non-orthographic surface (they were iddy-bitty), so they didn’t display in Ortho mode! yeesh. I’m pretty sure I grew a few grays with this one.

Anywho, in case anyone runs into this problem like me, make those suckers bigger!!