ulfben

GLPixelFont2.java

Mar 16th, 2019
130
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // GLPixelFont2 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/text-opengl-pixelfont-BZiUFIQN3gGlnS7fie
  4. // Ulf Benjaminsson, 2019-03-15, ulfbenjaminsson.com
  5.  
  6. // The first GLPixelFont stored "pixels" as char '1' / '0'. A char is 2 bytes in Java, so:
  7. //      46 (characters) * 7 (height) * 5 (width) * 16 (bits) = 25760 bit, or 3220 bytes
  8. //      See: https://pastebin.com/MA7ZuB6Q
  9. // Version 2 stores "pixels" as bits in a byte array, so:
  10. //      46 (characters) * 7 (height) * 8 (width) * 1 (bits) = 2576 bit, or 322 byte
  11. //      Ergo: 10x less memory.
  12.  
  13. public class GLPixelFont2 {
  14.     private static final int HEIGHT = 7; //characters are 7 units tall
  15.     private static final int WIDTH = 8; //characters are 8 units wide
  16.     private static final int CHAR_COUNT = 46; //the font definition contains 46 entries
  17.     private static final int OFFSET = 45; //it start at ASCII code 45 "-", and ends at 90 "Z".
  18.     private static final float SCALE = 0.75f; //scale vertex coordinates.
  19.     private final Mesh[] _glyphs = new Mesh[CHAR_COUNT]; //a vertex buffer for each glyph, for rendering with OpenGL.
  20.  
  21.     public GLPixelFont2() {
  22.         for (int c = 0; c < CHAR_COUNT; c++) {
  23.             _glyphs[c] = null;
  24.         }
  25.     }
  26.     //invalid characters will be null - make sure your renderer skips those!
  27.     public Mesh[] getString(final String s){
  28.         final int count = s.length();
  29.         final Mesh[] result = new Mesh[count];
  30.         for(int i = 0; i < count; i++){
  31.             result[i] = getChar(s.charAt(i));
  32.         }
  33.         return result;
  34.     }
  35.  
  36.     public Mesh getChar(char c){
  37.         c = Character.toUpperCase(c);
  38.         if(c < OFFSET || c >= OFFSET+CHAR_COUNT){
  39.             return null;
  40.         }
  41.         final int i = c - OFFSET;
  42.         if(_glyphs[i] == null){
  43.             _glyphs[i] = createMeshForGlyph(c);
  44.         }
  45.         return _glyphs[i];
  46.     }
  47.  
  48.     private Mesh createMeshForGlyph(final char c){
  49.         assert(c >= OFFSET && c < OFFSET+CHAR_COUNT);
  50.         final int charIndex = c-OFFSET;
  51.         final float z = 0;
  52.         final float[] vertices = new float[HEIGHT*WIDTH*Mesh.COORDS_PER_VERTEX];
  53.         int i = 0;
  54.         for (int y = 0; y < HEIGHT; y++) {
  55.             for (int x = 0; x < WIDTH; x++) {
  56.                 final int posByte = HEIGHT * charIndex + (x/WIDTH) + y; //thank Bog for Wolfram Alpha!
  57.                 final int posBit = x;
  58.                 final int bit = (BITMAP[posByte] >> (7-posBit) & 0x01);
  59.                 if((BITMAP[posByte] >> (7-posBit) & 0x01) == 0){continue;}
  60.                 vertices[i++] =  x*SCALE;
  61.                 vertices[i++] = -y*SCALE; //OpenGL has inverted y-axis.
  62.                 vertices[i++] =  z;
  63.             }
  64.         }
  65.         final float[] clean = Arrays.copyOfRange(vertices, 0, i);
  66.         return new Mesh(clean, GLES20.GL_POINTS);
  67.     }
  68.  
  69.     private static final byte[] BITMAP = {
  70.         /*[ind  asc sym]*/
  71.         /*[0    45  '-']*/  0x0, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x0,
  72.         /*[1    46  '.']*/  0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xc,
  73.         /*[2    47  '/']*/  0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
  74.         /*[3    48  '0']*/  0xe, 0x11, 0x13, 0x15, 0x19, 0x11, 0xe,
  75.         /*[4    49  '1']*/  0x4, 0xc, 0x4, 0x4, 0x4, 0x4, 0xe,
  76.         /*[5    50  '2']*/  0xe, 0x11, 0x1, 0x2, 0x4, 0x8, 0x1f,
  77.         /*[6    51  '3']*/  0xe, 0x11, 0x1, 0x6, 0x1, 0x11, 0xe,
  78.         /*[7    52  '4']*/  0x2, 0x6, 0xa, 0x12, 0x1f, 0x2, 0x7,
  79.         /*[8    53  '5']*/  0x1f, 0x10, 0x1e, 0x1, 0x1, 0x11, 0xe,
  80.         /*[9    54  '6']*/  0xe, 0x11, 0x10, 0x1e, 0x11, 0x11, 0xe,
  81.         /*[10   55  '7']*/  0x1f, 0x11, 0x2, 0x2, 0x4, 0x4, 0x4,
  82.         /*[11   56  '8']*/  0xe, 0x11, 0x11, 0xe, 0x11, 0x11, 0xe,
  83.         /*[12   57  '9']*/  0xe, 0x11, 0x11, 0xf, 0x1, 0x1, 0xe,
  84.         /*[13   58  ':']*/  0x0, 0xc, 0xc, 0x0, 0xc, 0xc, 0x0,
  85.         /*[14   59  ';']*/  0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
  86.         /*[15   60  '<']*/  0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
  87.         /*[16   61  '=']*/  0x0, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x0,
  88.         /*[17   62  '>']*/  0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
  89.         /*[18   63  '?']*/  0xe, 0x11, 0x11, 0x2, 0x4, 0x0, 0x4,
  90.         /*[19   64  '@']*/  0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
  91.         /*[20   65  'A']*/  0xe, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11,
  92.         /*[21   66  'B']*/  0x1e, 0x11, 0x11, 0x1e, 0x11, 0x11, 0x1e,
  93.         /*[22   67  'C']*/  0xe, 0x11, 0x10, 0x10, 0x10, 0x11, 0xe,
  94.         /*[23   68  'D']*/  0x1e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1e,
  95.         /*[24   69  'E']*/  0x1f, 0x10, 0x10, 0x1e, 0x10, 0x10, 0x1f,
  96.         /*[25   70  'F']*/  0x1f, 0x10, 0x10, 0x1e, 0x10, 0x10, 0x10,
  97.         /*[26   71  'G']*/  0xe, 0x11, 0x10, 0x17, 0x11, 0x11, 0xe,
  98.         /*[27   72  'H']*/  0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11,
  99.         /*[28   73  'I']*/  0xe, 0x4, 0x4, 0x4, 0x4, 0x4, 0xe,
  100.         /*[29   74  'J']*/  0x1, 0x1, 0x1, 0x1, 0x11, 0x11, 0xe,
  101.         /*[30   75  'K']*/  0x11, 0x12, 0x14, 0x18, 0x14, 0x12, 0x11,
  102.         /*[31   76  'L']*/  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1f,
  103.         /*[32   77  'M']*/  0x11, 0x1b, 0x15, 0x15, 0x11, 0x11, 0x11,
  104.         /*[33   78  'N']*/  0x11, 0x11, 0x19, 0x15, 0x13, 0x11, 0x11,
  105.         /*[34   79  'O']*/  0xe, 0x11, 0x11, 0x11, 0x11, 0x11, 0xe,
  106.         /*[35   80  'P']*/  0x1e, 0x11, 0x11, 0x1e, 0x10, 0x10, 0x10,
  107.         /*[36   81  'Q']*/  0xe, 0x11, 0x11, 0x11, 0x15, 0x12, 0xd,
  108.         /*[37   82  'R']*/  0x1e, 0x11, 0x11, 0x1e, 0x14, 0x12, 0x11,
  109.         /*[38   83  'S']*/  0xf, 0x10, 0x10, 0xe, 0x1, 0x1, 0x1e,
  110.         /*[39   84  'T']*/  0x1f, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,
  111.         /*[40   85  'U']*/  0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0xe,
  112.         /*[41   86  'V']*/  0x11, 0x11, 0x11, 0x11, 0x11, 0xa, 0x4,
  113.         /*[42   87  'W']*/  0x11, 0x11, 0x11, 0x15, 0x15, 0x15, 0xa,
  114.         /*[43   88  'X']*/  0x11, 0x11, 0xa, 0x4, 0xa, 0x11, 0x11,
  115.         /*[44   89  'Y']*/  0x11, 0x11, 0x11, 0xa, 0x4, 0x4, 0x4,
  116.         /*[45   90  'Z']*/  0x1f, 0x1, 0x2, 0x4, 0x8, 0x10, 0x1f
  117.     };
  118. }
  119.  
  120. //Mesh.java, to save your struggles. :)
  121. public class Mesh {
  122.     private static final String TAG = "Mesh";
  123.     public static final int SIZE_OF_FLOAT = Float.SIZE/Byte.SIZE; //32bit/8bit = 4 bytes
  124.     public static final int COORDS_PER_VERTEX = 3; //X, Y, Z
  125.     public static final int VERTEX_STRIDE = COORDS_PER_VERTEX * SIZE_OF_FLOAT; // number of bytes per vertex
  126.  
  127.     public FloatBuffer _vertexBuffer = null;
  128.     public int _vertexCount = 0;
  129.     public int _drawMode = GLES20.GL_TRIANGLES;
  130.  
  131.     public Mesh(final float[] geometry){
  132.         init(geometry, GLES20.GL_TRIANGLES);
  133.     }
  134.     public Mesh(final float[] geometry, final int drawMode){
  135.         init(geometry, drawMode);
  136.     }
  137.     private void init(final float[] geometry, final int drawMode){
  138.         setVertices(geometry);
  139.         setDrawmode(drawMode);
  140.     }
  141.  
  142.     public void setDrawmode(int drawMode){
  143.         assert(drawMode == GLES20.GL_TRIANGLES
  144.                 || drawMode == GLES20.GL_LINES
  145.                 || drawMode == GLES20.GL_POINTS);
  146.         _drawMode = drawMode;
  147.     }
  148.  
  149.     public void setVertices(final float[] geometry){
  150.         // create a floating point buffer from a ByteBuffer
  151.         _vertexBuffer = ByteBuffer.allocateDirect(geometry.length * SIZE_OF_FLOAT)
  152.                 .order(ByteOrder.nativeOrder()) // use the device hardware's native byte order
  153.                 .asFloatBuffer();
  154.         _vertexBuffer.put(geometry); //add the coordinates to the FloatBuffer
  155.         _vertexBuffer.position(0); // set the buffer to read the first coordinate
  156.         _vertexCount = geometry.length / COORDS_PER_VERTEX;
  157.     }
  158. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×