Advertisement
ulfben

GLPixelFont.java

Mar 16th, 2019
356
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.74 KB | None | 0 0
  1. // GLPixelFont provides meshes to render basic ASCII characters in OpenGL.
  2. // The font is fixed-width 5x7, and contains [0,9], uppercase [A,Z] and - . : = ?
  3. // Sample: https://giphy.com/gifs/1qh9eAliKnKqaQAGrt
  4. // Ulf Benjaminsson, 2019-03-15, ulfbenjaminsson.com
  5.  
  6. // The actual font definition courtesy of Mikael Fridenfalk at Uppsala University.
  7.  
  8. // UPDATE: GLPixelFont2, using a real bitmap for a 10x memory save, is available here: https://pastebin.com/6EN9s3qN
  9.  
  10. public class GLPixelFont {
  11.     private static final int HEIGHT = 7; //characters are 7 units tall
  12.     private static final int WIDTH = 5; //characters are 5 units wide
  13.     private static final int CHAR_COUNT = 46; //the font definition contains 46 entries
  14.     private static final int OFFSET = 45; //it start at ASCII code 45 "-", and ends at 90 "Z".
  15.     private static final float SCALE = 0.75f; //scale vertex coordinates.
  16.     private Mesh[] _glyphs = new Mesh[CHAR_COUNT]; //a vertex buffer for each glyph, for rendering with OpenGL.
  17.  
  18.     public GLPixelFont() {
  19.         for (int c = 0; c < CHAR_COUNT; c++) {
  20.             _glyphs[c] = null;
  21.         }
  22.     }
  23.  
  24.     public Mesh[] getString(final String s){
  25.         final int count = s.length();
  26.         Mesh[] result = new Mesh[count];
  27.         for(int i = 0; i < count; i++){
  28.             char c = s.charAt(i);
  29.             result[i] = getChar(c);
  30.         }
  31.         return result;
  32.     }
  33.  
  34.     public Mesh getChar(char c){
  35.         c = Character.toUpperCase(c);
  36.         if(c < OFFSET || c >= OFFSET+CHAR_COUNT){
  37.             return null;
  38.         }
  39.         int i = c - OFFSET;
  40.         if(_glyphs[i] == null){
  41.             _glyphs[i] = createMeshForGlyph(c);
  42.         }
  43.         return _glyphs[i];
  44.     }
  45.  
  46.     private Mesh createMeshForGlyph(final char c){
  47.         assert(c >= OFFSET && c < OFFSET+CHAR_COUNT);
  48.         float[] vertices = new float[HEIGHT*WIDTH*Mesh.COORDS_PER_VERTEX];
  49.         final float z = 0;
  50.         final int charIndex = c-OFFSET;
  51.         int i = 0;
  52.         for (int y = 0; y < HEIGHT; y++) {
  53.             for (int x = 0; x < WIDTH; x++) {
  54.                 final int index = (HEIGHT*WIDTH) * charIndex + WIDTH * y + x;
  55.                 if(FONT_DEFINITION.charAt(index) == '0'){ continue; }
  56.                 vertices[i++] =  x*SCALE;
  57.                 vertices[i++] = -y*SCALE; //OpenGL has inverted y-axis.
  58.                 vertices[i++] =  z;
  59.             }
  60.         }
  61.         float[] clean = Arrays.copyOfRange(vertices, 0, i);
  62.         return new Mesh(clean, GLES20.GL_POINTS);
  63.     }
  64.  
  65.     //FONT_DEFINITION contains most of basic ASCII characters 45-90:
  66.     //Specifically: [0,9], uppercase [A,Z] and - . : = ?
  67.     private static final String FONT_DEFINITION =
  68.     /*[ind  asc sym]*/
  69.     /*[0    45  '-']*/      "00000" + "00000" + "00000" + "11111" + "00000" + "00000" + "00000" + //-
  70.     /*[1    46  '.']*/      "00000" + "00000" + "00000" + "00000" + "00000" + "01100" + "01100" + //.
  71.     /*[2    47  '/']*/      "11111" + "11111" + "11111" + "11111" + "11111" + "11111" + "11111" + //
  72.     /*[3    48  '0']*/      "01110" + "10001" + "10011" + "10101" + "11001" + "10001" + "01110" + //0
  73.     /*[4    49  '1']*/      "00100" + "01100" + "00100" + "00100" + "00100" + "00100" + "01110" + //1
  74.     /*[5    50  '2']*/      "01110" + "10001" + "00001" + "00010" + "00100" + "01000" + "11111" + //2
  75.     /*[6    51  '3']*/      "01110" + "10001" + "00001" + "00110" + "00001" + "10001" + "01110" + //3
  76.     /*[7    52  '4']*/      "00010" + "00110" + "01010" + "10010" + "11111" + "00010" + "00111" + //4
  77.     /*[8    53  '5']*/      "11111" + "10000" + "11110" + "00001" + "00001" + "10001" + "01110" + //5
  78.     /*[9    54  '6']*/      "01110" + "10001" + "10000" + "11110" + "10001" + "10001" + "01110" + //6
  79.     /*[10   55  '7']*/      "11111" + "10001" + "00010" + "00010" + "00100" + "00100" + "00100" + //7
  80.     /*[11   56  '8']*/      "01110" + "10001" + "10001" + "01110" + "10001" + "10001" + "01110" + //8
  81.     /*[12   57  '9']*/      "01110" + "10001" + "10001" + "01111" + "00001" + "00001" + "01110" + //9
  82.     /*[13   58  ':']*/      "00000" + "01100" + "01100" + "00000" + "01100" + "01100" + "00000" + //:
  83.     /*[14   59  ';']*/      "11111" + "11111" + "11111" + "11111" + "11111" + "11111" + "11111" + //
  84.     /*[15   60  '<']*/      "11111" + "11111" + "11111" + "11111" + "11111" + "11111" + "11111" + //
  85.     /*[16   61  '=']*/      "00000" + "00000" + "11111" + "00000" + "11111" + "00000" + "00000" + //=
  86.     /*[17   62  '>']*/      "11111" + "11111" + "11111" + "11111" + "11111" + "11111" + "11111" + //
  87.     /*[18   63  '?']*/      "01110" + "10001" + "10001" + "00010" + "00100" + "00000" + "00100" + //?
  88.     /*[19   64  '@']*/      "11111" + "11111" + "11111" + "11111" + "11111" + "11111" + "11111" + //
  89.     /*[20   65  'A']*/      "01110" + "10001" + "10001" + "11111" + "10001" + "10001" + "10001" + //A
  90.     /*[21   66  'B']*/      "11110" + "10001" + "10001" + "11110" + "10001" + "10001" + "11110" + //B
  91.     /*[22   67  'C']*/      "01110" + "10001" + "10000" + "10000" + "10000" + "10001" + "01110" + //C
  92.     /*[23   68  'D']*/      "11110" + "10001" + "10001" + "10001" + "10001" + "10001" + "11110" + //D
  93.     /*[24   69  'E']*/      "11111" + "10000" + "10000" + "11110" + "10000" + "10000" + "11111" + //E
  94.     /*[25   70  'F']*/      "11111" + "10000" + "10000" + "11110" + "10000" + "10000" + "10000" + //F
  95.     /*[26   71  'G']*/      "01110" + "10001" + "10000" + "10111" + "10001" + "10001" + "01110" + //G
  96.     /*[27   72  'H']*/      "10001" + "10001" + "10001" + "11111" + "10001" + "10001" + "10001" + //H
  97.     /*[28   73  'I']*/      "01110" + "00100" + "00100" + "00100" + "00100" + "00100" + "01110" + //I
  98.     /*[29   74  'J']*/      "00001" + "00001" + "00001" + "00001" + "10001" + "10001" + "01110" + //J
  99.     /*[30   75  'K']*/      "10001" + "10010" + "10100" + "11000" + "10100" + "10010" + "10001" + //K
  100.     /*[31   76  'L']*/      "10000" + "10000" + "10000" + "10000" + "10000" + "10000" + "11111" + //L
  101.     /*[32   77  'M']*/      "10001" + "11011" + "10101" + "10101" + "10001" + "10001" + "10001" + //M
  102.     /*[33   78  'N']*/      "10001" + "10001" + "11001" + "10101" + "10011" + "10001" + "10001" + //N
  103.     /*[34   79  'O']*/      "01110" + "10001" + "10001" + "10001" + "10001" + "10001" + "01110" + //O
  104.     /*[35   80  'P']*/      "11110" + "10001" + "10001" + "11110" + "10000" + "10000" + "10000" + //P
  105.     /*[36   81  'Q']*/      "01110" + "10001" + "10001" + "10001" + "10101" + "10010" + "01101" + //Q
  106.     /*[37   82  'R']*/      "11110" + "10001" + "10001" + "11110" + "10100" + "10010" + "10001" + //R
  107.     /*[38   83  'S']*/      "01111" + "10000" + "10000" + "01110" + "00001" + "00001" + "11110" + //S
  108.     /*[39   84  'T']*/      "11111" + "00100" + "00100" + "00100" + "00100" + "00100" + "00100" + //T
  109.     /*[40   85  'U']*/      "10001" + "10001" + "10001" + "10001" + "10001" + "10001" + "01110" + //U
  110.     /*[41   86  'V']*/      "10001" + "10001" + "10001" + "10001" + "10001" + "01010" + "00100" + //V
  111.     /*[42   87  'W']*/      "10001" + "10001" + "10001" + "10101" + "10101" + "10101" + "01010" + //W
  112.     /*[43   88  'X']*/      "10001" + "10001" + "01010" + "00100" + "01010" + "10001" + "10001" + //X
  113.     /*[44   89  'Y']*/      "10001" + "10001" + "10001" + "01010" + "00100" + "00100" + "00100" + //Y
  114.     /*[45   90  'Z']*/      "11111" + "00001" + "00010" + "00100" + "01000" + "10000" + "11111";  //Z
  115. }
  116.  
  117. //Mesh.java, to save your struggles. :)
  118. public class Mesh {
  119.     private static final String TAG = "Mesh";
  120.     public static final int SIZE_OF_FLOAT = Float.SIZE/Byte.SIZE; //32bit/8bit = 4 bytes
  121.     public static final int COORDS_PER_VERTEX = 3; //X, Y, Z
  122.     public static final int VERTEX_STRIDE = COORDS_PER_VERTEX * SIZE_OF_FLOAT; // number of bytes per vertex
  123.  
  124.     public FloatBuffer _vertexBuffer = null;
  125.     public int _vertexCount = 0;
  126.     public int _drawMode = GLES20.GL_TRIANGLES;
  127.  
  128.     public Mesh(final float[] geometry){
  129.         init(geometry, GLES20.GL_TRIANGLES);
  130.     }
  131.     public Mesh(final float[] geometry, final int drawMode){
  132.         init(geometry, drawMode);
  133.     }
  134.     private void init(final float[] geometry, final int drawMode){
  135.         setVertices(geometry);
  136.         setDrawmode(drawMode);
  137.     }
  138.  
  139.     public void setDrawmode(int drawMode){
  140.         assert(drawMode == GLES20.GL_TRIANGLES
  141.                 || drawMode == GLES20.GL_LINES
  142.                 || drawMode == GLES20.GL_POINTS);
  143.         _drawMode = drawMode;
  144.     }
  145.  
  146.     public void setVertices(final float[] geometry){
  147.         // create a floating point buffer from a ByteBuffer
  148.         _vertexBuffer = ByteBuffer.allocateDirect(geometry.length * SIZE_OF_FLOAT)
  149.                 .order(ByteOrder.nativeOrder()) // use the device hardware's native byte order
  150.                 .asFloatBuffer();
  151.         _vertexBuffer.put(geometry); //add the coordinates to the FloatBuffer
  152.         _vertexBuffer.position(0); // set the buffer to read the first coordinate
  153.         _vertexCount = geometry.length / COORDS_PER_VERTEX;
  154.     }
  155. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement