package com.ulfben.asteroids.GL; import java.util.HashMap; /** * Created by Ulf Benjaminsson on 2017-03-27, www.ulfben.com * GLFont is a "pixel font" for OpenGL. Each glyph is made up from 1-9 quads, * ready to be put in a vertex-buffer and rendered as geometry. * * Example: https://media.giphy.com/media/11lKO38jQGliuY/giphy.gif * * getString(String) returns an array of GLModels. GLModel is a just glorified vertex buffer * so replace it with whatever you use to pass vertices into OpenGL. */ public class GLFont { public static float height = 25f; public static float width = 25f; public static float lineWidth = 5.0f; private static HashMap glyphMap = new HashMap(); private GLFont(){} public static void init() { final float LW2 = lineWidth*2f; //prepare some common values final float LW3 = lineWidth*3f; final float left = 0f; final float top = height; final float bottom = 0f; final float right = left+width; final float centerY = (top/2f)+(lineWidth/2f); final float centerX = (right/2f)-(lineWidth/2f); final float[] fullLeft = quad(left, top, lineWidth, height); //prepare some common quads final float[] fullRight = quad(right-lineWidth, top, lineWidth, height); final float[] fullTop = quad(left, top, width, lineWidth); final float[] fullBottom = quad(left, bottom+lineWidth, width, lineWidth); final float[] boxOpenLeft = concat(fullLeft, fullTop, fullBottom); //C, E, G, o, 0, 8, Q, 6 final float[] box = concat(boxOpenLeft, fullRight); //o, 0 and 8, Q final float[] centerLineLeft = quad(left+lineWidth, centerY, width-(LW3), lineWidth); //E, F final float[] centerLineRight = quad(left+LW2, centerY, width-LW2, lineWidth); //lip of G, 3 final float[] centerLineCentered = quad(left+lineWidth, centerY, width-LW2, lineWidth); //H, B, A etc final float[] verticalCenter = quad(centerX, top, lineWidth, height);// I, T final float[] shortTop = quad(left, top, width-lineWidth, lineWidth); //B, D, P, R final float[] shortBottom = quad(left, bottom+lineWidth, width-lineWidth, lineWidth); //B, D final float[] a = concat(fullLeft, fullTop, fullRight, centerLineCentered); final float[] b = concat(fullLeft, shortTop, shortBottom, centerLineCentered, quad(right-lineWidth, top-lineWidth, lineWidth, height-LW2)); final float[] c = boxOpenLeft; final float[] d = concat(fullLeft, shortTop, shortBottom, quad(right-lineWidth, top-lineWidth, lineWidth, height-LW2)); final float[] e = concat(boxOpenLeft, centerLineLeft); final float[] f = concat(fullLeft, fullTop, centerLineLeft); final float[] g = concat(boxOpenLeft, quad(right-lineWidth, centerY, lineWidth, bottom+centerY), centerLineRight); final float[] h = concat(fullLeft, fullRight, centerLineCentered); final float[] i = concat(fullTop, fullBottom, verticalCenter); final float[] j = concat(fullRight, fullBottom, quad(left, bottom+LW2, lineWidth, lineWidth)); final float[] k = concat(fullLeft, centerLineLeft, quad(right-LW2, centerY+lineWidth, lineWidth, lineWidth), quad(right-lineWidth, top, lineWidth, lineWidth), quad(right-LW2, centerY-lineWidth, lineWidth, lineWidth), quad(right-lineWidth, bottom+lineWidth, lineWidth, lineWidth) ); final float[] l = concat(fullLeft, fullBottom); final float[] m = concat(fullLeft, verticalCenter, fullRight, fullTop); final float[] n = concat(fullLeft, fullTop, fullRight); final float[] o = box; final float[] p = concat(fullLeft, shortTop, centerLineCentered, quad(right-lineWidth, top-lineWidth, lineWidth, LW2)); final float[] q = concat(fullLeft, fullRight, fullTop, fullBottom, quad(centerX, bottom+LW2, lineWidth, LW3)); final float[] r = concat(fullLeft, shortTop, centerLineCentered, quad(right-lineWidth, top-lineWidth, lineWidth, centerY-lineWidth), quad(right-LW2, centerY-lineWidth, lineWidth, lineWidth), quad(right-lineWidth, bottom+lineWidth, lineWidth, lineWidth) ); final float[] s = concat(fullTop, fullBottom, centerLineCentered, quad(left, top, lineWidth, centerY), quad(right-lineWidth, centerY, lineWidth, centerY)); final float[] t = concat(fullTop, verticalCenter); final float[] u = concat(fullLeft, fullRight, fullBottom); final float[] v = concat(quad(left, top, lineWidth, centerY), quad(right-lineWidth, top, lineWidth, centerY), quad(right-LW2, centerY-lineWidth, lineWidth, lineWidth), quad(left+lineWidth, centerY-lineWidth, lineWidth, lineWidth), quad(centerX, bottom+lineWidth, lineWidth, lineWidth) ); final float[] w = concat(fullLeft, verticalCenter, fullRight, fullBottom); final float[] x = concat( quad(left, top, lineWidth, lineWidth), quad(right-lineWidth, top, lineWidth, lineWidth), quad(left+lineWidth, top-lineWidth, lineWidth, lineWidth), quad(right-LW2, top-lineWidth, lineWidth, lineWidth), quad(left+LW2, top-LW2, lineWidth, lineWidth), //center of x quad(left+lineWidth, bottom+LW2, lineWidth, lineWidth), quad(right-LW2, bottom+LW2, lineWidth, lineWidth), quad(left, bottom+lineWidth, lineWidth, lineWidth), quad(right-lineWidth, bottom+lineWidth, lineWidth, lineWidth) ); final float[] y = concat( quad(left, top, lineWidth, lineWidth), quad(right-lineWidth, top, lineWidth, lineWidth), quad(left+lineWidth, top-lineWidth, lineWidth, lineWidth), quad(right-LW2, top-lineWidth, lineWidth, lineWidth), quad(left+LW2, top-LW2, lineWidth, (LW3)) ); final float[] z = concat(fullTop, fullBottom, quad(right-LW2, top-lineWidth, lineWidth, lineWidth), quad(left+LW2, top-LW2, lineWidth, lineWidth), quad(left+lineWidth, bottom+LW2, lineWidth, lineWidth) ); final float[] zero = box; final float[] one = concat(quad(centerX-lineWidth, top, lineWidth, lineWidth), verticalCenter); final float[] two = concat(fullTop, fullBottom, centerLineCentered, quad(left, centerY, lineWidth, centerY), quad(right-lineWidth, top, lineWidth, centerY)); final float[] three = concat(fullRight, fullTop, centerLineRight, fullBottom); final float[] four = concat(fullRight, centerLineCentered, quad(left, top, lineWidth, centerY)); final float[] five = concat(fullTop, fullBottom, centerLineCentered, quad(left, top, lineWidth, centerY), quad(right-lineWidth, centerY, lineWidth, centerY)); final float[] six = concat(boxOpenLeft, centerLineCentered, quad(right-lineWidth, centerY, lineWidth, centerY)); final float[] seven = concat(fullTop, fullRight); final float[] eight = concat(box, centerLineCentered); final float[] nine = concat(fullRight, fullTop, centerLineCentered, quad(left, top, lineWidth, centerY)); final float[] dot = quad(left, bottom+lineWidth, lineWidth, lineWidth); final float[] dash = quad(left+lineWidth, centerY, width-LW2, lineWidth); final float[] slash = concat(quad(right-lineWidth, top, lineWidth, lineWidth), quad(right-LW2, top-lineWidth, lineWidth, lineWidth), quad(left+LW2, top-LW2, lineWidth, lineWidth), quad(left+lineWidth, bottom+LW2, lineWidth, lineWidth), quad(left, bottom+lineWidth, lineWidth, lineWidth) ); addGlyph("a", a); addGlyph("b", b); addGlyph("c", c); addGlyph("d", d); addGlyph("e", e); addGlyph("f", f); addGlyph("g", g); addGlyph("h", h); addGlyph("i", i); addGlyph("j", j); addGlyph("k", k); addGlyph("l", l); addGlyph("m", m); addGlyph("n", n); addGlyph("o", o); addGlyph("p", p); addGlyph("q", q); addGlyph("r", r); addGlyph("s", s); addGlyph("t", t); addGlyph("u", u); addGlyph("v", v); addGlyph("x", x); addGlyph("y", y); addGlyph("z", z); addGlyph("0", zero); addGlyph("1", one); addGlyph("2", two); addGlyph("3", three); addGlyph("4", four); addGlyph("5", five); addGlyph("6", six); addGlyph("7", seven); addGlyph("8", eight); addGlyph("9", nine); addGlyph(".", dot); addGlyph("-", dash); addGlyph("/", slash); } public static GLModel[] getString(final String s){ int length = s.length(); GLModel[] result = new GLModel[length]; for(int i = 0; i < length; i++){ result[i] = GLFont.getChar(s.substring(i, i+1)); } return result; } public static final GLModel getChar(final String s){ GLModel result = glyphMap.get(s); if(result == null){ return glyphMap.get("."); } return result; } private static float[] quad(float left, float top, float width, float height){ final float z = 0.0f; final float right = left+width; final float bottom = top-height; return new float[]{ left, top, z, left, bottom, z, right, bottom, z, right, top, z, left, top, z, right, bottom, z }; } private static void addGlyph(final String index, final float[] vertices){ glyphMap.put(index, new GLModel(vertices)); } private static float[] concat(final float[]... arrays){ if(arrays == null || arrays.length < 1){ throw new IllegalArgumentException(""); } int length = 0, pos = 0, count = arrays.length; for (float[] a : arrays) { length += a.length; } float[] result = new float[length]; for(int i = 0; i < count; i++){ System.arraycopy(arrays[i], 0, result, pos, arrays[i].length); pos += arrays[i].length; } return result; } }