ulfben icon

GLPixelFont2.java

ulfben | PRO | 03/16/19 11:56:11 PM UTC | 0 ⭐ | 967 👁️ | Never ⏰ | []
Java |

7.49 KB

|

None

|

0 👍

/

0 👎

// GLPixelFont2 provides meshes to render basic ASCII characters in OpenGL.
// The font is fixed-width 5x7, and contains [0,9], uppercase [A,Z] and - . : = ?
// Sample: https://giphy.com/gifs/text-opengl-pixelfont-BZiUFIQN3gGlnS7fie
// Ulf Benjaminsson, 2019-03-15, ulfbenjaminsson.com
 
// The first GLPixelFont stored "pixels" as char '1' / '0'. A char is 2 bytes in Java, so: 
//      46 (characters) * 7 (height) * 5 (width) * 16 (bits) = 25760 bit, or 3220 bytes
//      See: https://pastebin.com/MA7ZuB6Q
// Version 2 stores "pixels" as bits in a byte array, so:
//      46 (characters) * 7 (height) * 8 (width) * 1 (bits) = 2576 bit, or 322 byte
//      Ergo: 10x less memory. 
 
public class GLPixelFont2 {
    private static final int HEIGHT = 7; //characters are 7 units tall
    private static final int WIDTH = 8; //characters are 8 units wide
    private static final int CHAR_COUNT = 46; //the font definition contains 46 entries
    private static final int OFFSET = 45; //it start at ASCII code 45 "-", and ends at 90 "Z".
    private static final float SCALE = 0.75f; //scale vertex coordinates.
    private final Mesh[] _glyphs = new Mesh[CHAR_COUNT]; //a vertex buffer for each glyph, for rendering with OpenGL.
 
    public GLPixelFont2() {
        for (int c = 0; c < CHAR_COUNT; c++) {
            _glyphs[c] = null;
        }
    }
    //invalid characters will be null - make sure your renderer skips those!
    public Mesh[] getString(final String s){
        final int count = s.length();
        final Mesh[] result = new Mesh[count];
        for(int i = 0; i < count; i++){
            result[i] = getChar(s.charAt(i));
        }
        return result;
    }
 
    public Mesh getChar(char c){
        c = Character.toUpperCase(c);
        if(c < OFFSET || c >= OFFSET+CHAR_COUNT){
            return null;
        }
        final int i = c - OFFSET;
        if(_glyphs[i] == null){
            _glyphs[i] = createMeshForGlyph(c);
        }
        return _glyphs[i];
    }
 
    private Mesh createMeshForGlyph(final char c){
        assert(c >= OFFSET && c < OFFSET+CHAR_COUNT);
        final int charIndex = c-OFFSET;
        final float z = 0;
        final float[] vertices = new float[HEIGHT*WIDTH*Mesh.COORDS_PER_VERTEX];
        int i = 0;
        for (int y = 0; y < HEIGHT; y++) {
            for (int x = 0; x < WIDTH; x++) {
                final int posByte = HEIGHT * charIndex + (x/WIDTH) + y; //thank Bog for Wolfram Alpha!
                final int posBit = x;
                final int bit = (BITMAP[posByte] >> (7-posBit) & 0x01);
                if((BITMAP[posByte] >> (7-posBit) & 0x01) == 0){continue;}
                vertices[i++] =  x*SCALE;
                vertices[i++] = -y*SCALE; //OpenGL has inverted y-axis.
                vertices[i++] =  z;
            }
        }
        final float[] clean = Arrays.copyOfRange(vertices, 0, i);
        return new Mesh(clean, GLES20.GL_POINTS);
    }
 
    private static final byte[] BITMAP = {
        /*[ind  asc sym]*/
        /*[0    45  '-']*/  0x0, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x0,
        /*[1    46  '.']*/  0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xc,
        /*[2    47  '/']*/  0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
        /*[3    48  '0']*/  0xe, 0x11, 0x13, 0x15, 0x19, 0x11, 0xe,
        /*[4    49  '1']*/  0x4, 0xc, 0x4, 0x4, 0x4, 0x4, 0xe,
        /*[5    50  '2']*/  0xe, 0x11, 0x1, 0x2, 0x4, 0x8, 0x1f,
        /*[6    51  '3']*/  0xe, 0x11, 0x1, 0x6, 0x1, 0x11, 0xe,
        /*[7    52  '4']*/  0x2, 0x6, 0xa, 0x12, 0x1f, 0x2, 0x7,
        /*[8    53  '5']*/  0x1f, 0x10, 0x1e, 0x1, 0x1, 0x11, 0xe,
        /*[9    54  '6']*/  0xe, 0x11, 0x10, 0x1e, 0x11, 0x11, 0xe,
        /*[10   55  '7']*/  0x1f, 0x11, 0x2, 0x2, 0x4, 0x4, 0x4,
        /*[11   56  '8']*/  0xe, 0x11, 0x11, 0xe, 0x11, 0x11, 0xe,
        /*[12   57  '9']*/  0xe, 0x11, 0x11, 0xf, 0x1, 0x1, 0xe,
        /*[13   58  ':']*/  0x0, 0xc, 0xc, 0x0, 0xc, 0xc, 0x0,
        /*[14   59  ';']*/  0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
        /*[15   60  '<']*/  0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
        /*[16   61  '=']*/  0x0, 0x0, 0x1f, 0x0, 0x1f, 0x0, 0x0,
        /*[17   62  '>']*/  0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
        /*[18   63  '?']*/  0xe, 0x11, 0x11, 0x2, 0x4, 0x0, 0x4,
        /*[19   64  '@']*/  0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
        /*[20   65  'A']*/  0xe, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11,
        /*[21   66  'B']*/  0x1e, 0x11, 0x11, 0x1e, 0x11, 0x11, 0x1e,
        /*[22   67  'C']*/  0xe, 0x11, 0x10, 0x10, 0x10, 0x11, 0xe,
        /*[23   68  'D']*/  0x1e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1e,
        /*[24   69  'E']*/  0x1f, 0x10, 0x10, 0x1e, 0x10, 0x10, 0x1f,
        /*[25   70  'F']*/  0x1f, 0x10, 0x10, 0x1e, 0x10, 0x10, 0x10,
        /*[26   71  'G']*/  0xe, 0x11, 0x10, 0x17, 0x11, 0x11, 0xe,
        /*[27   72  'H']*/  0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11,
        /*[28   73  'I']*/  0xe, 0x4, 0x4, 0x4, 0x4, 0x4, 0xe,
        /*[29   74  'J']*/  0x1, 0x1, 0x1, 0x1, 0x11, 0x11, 0xe,
        /*[30   75  'K']*/  0x11, 0x12, 0x14, 0x18, 0x14, 0x12, 0x11,
        /*[31   76  'L']*/  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1f,
        /*[32   77  'M']*/  0x11, 0x1b, 0x15, 0x15, 0x11, 0x11, 0x11,
        /*[33   78  'N']*/  0x11, 0x11, 0x19, 0x15, 0x13, 0x11, 0x11,
        /*[34   79  'O']*/  0xe, 0x11, 0x11, 0x11, 0x11, 0x11, 0xe,
        /*[35   80  'P']*/  0x1e, 0x11, 0x11, 0x1e, 0x10, 0x10, 0x10,
        /*[36   81  'Q']*/  0xe, 0x11, 0x11, 0x11, 0x15, 0x12, 0xd,
        /*[37   82  'R']*/  0x1e, 0x11, 0x11, 0x1e, 0x14, 0x12, 0x11,
        /*[38   83  'S']*/  0xf, 0x10, 0x10, 0xe, 0x1, 0x1, 0x1e,
        /*[39   84  'T']*/  0x1f, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,
        /*[40   85  'U']*/  0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0xe,
        /*[41   86  'V']*/  0x11, 0x11, 0x11, 0x11, 0x11, 0xa, 0x4,
        /*[42   87  'W']*/  0x11, 0x11, 0x11, 0x15, 0x15, 0x15, 0xa,
        /*[43   88  'X']*/  0x11, 0x11, 0xa, 0x4, 0xa, 0x11, 0x11,
        /*[44   89  'Y']*/  0x11, 0x11, 0x11, 0xa, 0x4, 0x4, 0x4,
        /*[45   90  'Z']*/  0x1f, 0x1, 0x2, 0x4, 0x8, 0x10, 0x1f
    };
}
 
//Mesh.java, to save your struggles. :)
public class Mesh {
    private static final String TAG = "Mesh";
    public static final int SIZE_OF_FLOAT = Float.SIZE/Byte.SIZE; //32bit/8bit = 4 bytes
    public static final int COORDS_PER_VERTEX = 3; //X, Y, Z
    public static final int VERTEX_STRIDE = COORDS_PER_VERTEX * SIZE_OF_FLOAT; // number of bytes per vertex
 
    public FloatBuffer _vertexBuffer = null;
    public int _vertexCount = 0;
    public int _drawMode = GLES20.GL_TRIANGLES;
 
    public Mesh(final float[] geometry){
        init(geometry, GLES20.GL_TRIANGLES);
    }
    public Mesh(final float[] geometry, final int drawMode){
        init(geometry, drawMode);
    }
    private void init(final float[] geometry, final int drawMode){
        setVertices(geometry);
        setDrawmode(drawMode);
    }
 
    public void setDrawmode(int drawMode){
        assert(drawMode == GLES20.GL_TRIANGLES
                || drawMode == GLES20.GL_LINES
                || drawMode == GLES20.GL_POINTS);
        _drawMode = drawMode;
    }
 
    public void setVertices(final float[] geometry){
        // create a floating point buffer from a ByteBuffer
        _vertexBuffer = ByteBuffer.allocateDirect(geometry.length * SIZE_OF_FLOAT)
                .order(ByteOrder.nativeOrder()) // use the device hardware's native byte order
                .asFloatBuffer();
        _vertexBuffer.put(geometry); //add the coordinates to the FloatBuffer
        _vertexBuffer.position(0); // set the buffer to read the first coordinate
        _vertexCount = geometry.length / COORDS_PER_VERTEX;
    }
}

Comments

  • Gyqizv icon
    04/02/26 06:22:40 PM UTC
    text |

    0 B

    |

    0 👍

    /

    0 👎

    Best t33n active cpx link daily updates!
     Copy and paste the link in a new browser tab and then hit enter!
     https://crazyporn.@xxx/members/157354/?asgtbndr=1&play=true&spon=adworld&zone=400
     Remove the @ 
  • Yuizcko icon
    05/18/26 01:05:33 PM UTC
    text |

    0 B

    |

    0 👍

    /

    0 👎

    Best t33n active cpx link daily updates!
     Copy and paste the link in a new browser tab and then hit enter!
     https://crazyporn.xxx/members/157354/?asgtbndr=1&play=true&spon=adworld&zone=400