LWJGL Forum

Programming => OpenGL => Topic started by: geekygenius on March 09, 2012, 06:42:15

Title: glGenLists(256) not working correctly
Post by: geekygenius on March 09, 2012, 06:42:15
So, I am working on a game, where I have a few models, each represented by a display list. Since I need to be able to communicate with my players, I have looked into adding a text to my game. I found that the all famous "NeHe (http://nehe.gamedev.net/tutorial/bitmap_fonts/17002/)" tutorial. I think I have successfully modified the LWJGL port to fit my needs except for one crucial part, generating the display lists. After debugging, I found the problem that the base is 1, which is also the display list ID for another model, overwriting it when I try and create the letter. I don't know why, but the glGenLists(256) is returning 1, when it should be giving me something higher.

I have marked the important line of code with a comment, it's near the bottom. :D
Code:
package geekygenius.nutrality.gui;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

import org.lwjgl.opengl.GL11;

public class FontData {
   private static String fontResource = "resources/font.ttf";
   private static final Color OPAQUE_WHITE = new Color(0xFFFFFFFF, true);
   private static final Color TRANSPARENT_BLACK = new Color(0x00000000, true);

   private Font font;
   private int texture;
   private int base;

   private boolean built;

   public FontData(Font font) {
this.font = font;
built = false;
buildFont();
   }

   public void displayText(String msg) {
displayText(msg, 0, 0);
   }

   public void displayText(String msg, float x, float y) {
GL11.glDisable(GL11.GL_LIGHTING);
if (msg != null) {
   GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
   for (int i = 0; i < msg.length(); i++) {
GL11.glCallList(base + msg.charAt(i));
GL11.glTranslatef(0.05f, 0.0f, 0.0f); // TODO Change this to get
     // the width for non
     // momospaced fonts.
   }
}
GL11.glEnable(GL11.GL_LIGHTING);
   }

   public void buildFont() {
if (!built) {
   destroy();
}
built = true;

BufferedImage fontImage;                        // image for creating the bitmap
int bitmapSize = 512;                           // set the size for the bitmap texture
boolean sizeFound = false;
boolean directionSet = false;
int delta = 0;
float fontSize = 24;

//Allocate Memory
int width;
int height;
int lineWidth;
// Find the size
while (!sizeFound) {
   font = font.deriveFont(fontSize);
   // use BufferedImage.TYPE_4BYTE_ABGR to allow alpha blending
   fontImage = new BufferedImage(bitmapSize, bitmapSize, BufferedImage.TYPE_4BYTE_ABGR);
   Graphics2D g = (Graphics2D) fontImage.getGraphics();
   g.setFont(font);
   FontMetrics fm = g.getFontMetrics();
   width = fm.stringWidth("W");
   height = fm.getHeight();
   lineWidth = (width > height) ? width * 16 : height * 16;
   if (!directionSet) {
if (lineWidth > bitmapSize) {
   delta = -2;
} else {
   delta = 2;
}
directionSet = true;
   }
   if (delta > 0) {
if (lineWidth < bitmapSize) {
   fontSize += delta;
} else {
   sizeFound = true;
   fontSize -= delta;
}
   } else if (delta < 0) {
if (lineWidth > bitmapSize) {
   fontSize += delta;
} else {
   sizeFound = true;
   fontSize -= delta;
}
   }
}


/*
* Now that a font size has been determined, create the final image, set
* the font and draw the
* standard/extended ASCII character set for that font.
*/
// use BufferedImage.TYPE_4BYTE_ABGR to allow alpha blending
fontImage = new BufferedImage(bitmapSize, bitmapSize, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g = (Graphics2D) fontImage.getGraphics();
g.setFont(font);
g.setColor(OPAQUE_WHITE);
g.setBackground(TRANSPARENT_BLACK);
FontMetrics fm = g.getFontMetrics();
for (int i = 0; i < 256; i++) {
   int x = i % 16;
   int y = i / 16;
   char ch[] = { (char) i };
   String temp = new String(ch);
   g.drawString(temp, (x * 32) + 1, (y * 32) + fm.getAscent());
}

/*
* The following code is taken directly for the LWJGL example code.
* It takes a Java Image and converts it into an OpenGL texture.
* This is a very powerful feature as you can use this to generate
* textures on the fly out
* of anything.
*/
// Flip Image
AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
tx.translate(0, -fontImage.getHeight(null));
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
fontImage = op.filter(fontImage, null);

// Put Image In Memory
ByteBuffer scratch = ByteBuffer.allocateDirect(4 * fontImage.getWidth() * fontImage.getHeight());

byte data[] = (byte[]) fontImage.getRaster().getDataElements(0, 0, fontImage.getWidth(), fontImage.getHeight(),
null);
scratch.clear();
scratch.put(data);
scratch.rewind();

// Create A IntBuffer For Image Address In Memory
IntBuffer buf = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
GL11.glGenTextures(buf); // Create Texture In OpenGL

GL11.glBindTexture(GL11.GL_TEXTURE_2D, buf.get(0));
// Typical Texture Generation Using Data From The Image

// Linear Filtering
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
// Linear Filtering
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
// Generate The Texture
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, fontImage.getWidth(), fontImage.getHeight(), 0,
GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, scratch);

texture = buf.get(0);                           // Return Image Address In Memory

base = GL11.glGenLists(256);                    // Storage For 256 Characters

//Important Line of code ^^ ============================================================

/*
* 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 < 128; i++) {
   float u = ((float) (i % 16)) / 16.0f;
   float v = 1.f - (((float) (i / 16)) / 16.0f);
   GL11.glNewList(base + i, GL11.GL_COMPILE);
   GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
   GL11.glBegin(GL11.GL_QUADS);
   GL11.glTexCoord2f(u, v);
   GL11.glVertex3f(-0.0450f, 0.0450f, 0.0f);
   GL11.glTexCoord2f((u + textureDelta), v);
   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, v - textureDelta);
   GL11.glVertex3f(-0.0450f, -0.0450f, 0.0f);
   GL11.glEnd();
   GL11.glEndList();
}
   }

   public void destroy() {
GL11.glDeleteLists(base, 256);
GL11.glDeleteTextures(texture);
   }
}

This is set up in orthographic mode as follows:
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, 1280, 0, 720, -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

The 2D rendering does work with some basic quads I used for testing.

What am I doing wrong, and how can I fix it?
Title: Re: glGenLists(256) not working correctly
Post by: geekygenius on March 16, 2012, 06:27:17
Any ideas?
Title: Re: glGenLists(256) not working correctly
Post by: Fool Running on March 16, 2012, 12:52:25
Does it work if you just generate one list at a time (i.e. call GL11.glGenLists(1) 256 times)? Are you absolutely sure that the display list for the other model is 1? Are you sure you haven't deleted the display list for that model? Are you getting any OpenGL errors?
Title: Re: glGenLists(256) not working correctly
Post by: geekygenius on March 16, 2012, 20:18:44
So, I tried generating the lists individually, but that didn't work. This is for rendering text on the HUD, which is above the main map, where as of now, I have three display lists, one for a tree, one for a town, and one for the whole map, which contains calls to the tree and town display lists. In debug mode, I found that the base was always returning as 1, which happened to be the same ID as the tree. When the map renders, the map is shown, but instead of showing trees and cities, it shows parts of the font, telling me that the display list was overwritten.
Title: Re: glGenLists(256) not working correctly
Post by: Fool Running on March 19, 2012, 12:49:28
That's very strange. Are you sure you aren't getting any OpenGL errors?
Are you possibly using multiple contexts (i.e. creating the tree in one context and creating the text with another)?
Are you re-initializing the display between the times you create the display lists for the trees, cities and the time you create the display lists for the font?
If you don't do anything with the font, do you see the tree and cities?

If possible, more of your code would help.