Font work
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2024-02-28 21:21:05 -05:00
parent 4671a295f5
commit 9407c13217
15 changed files with 577 additions and 132 deletions

BIN
assets/Fonts/Tuffy_Bold.ttf Normal file

Binary file not shown.

View File

@ -1,3 +1,3 @@
#maven.buildNumber.plugin properties file
#Mon Feb 26 10:41:04 EST 2024
buildNumber=22
#Wed Feb 28 20:29:21 EST 2024
buildNumber=26

99
docs/src/fonts/Fonts.md Normal file
View File

@ -0,0 +1,99 @@
# Fonts
## High Level Overview
The font loading mechanism loads all fonts at engine startup. It leverages java.awt.Font to read font data from ttf files on disk, render them to a bitmap, and then display appropriately.
Globals has a font manager that can be leveraged to get fonts based on identification strings.
## Major Usage Notes
## Main Classes
[Font.java](@ref #electrosphere.renderer.ui.font.Font) - Holds all the data about a font: the glyphs and metadata about them, as well as the material containing the actual bitmap
[FontManager.java](@ref #electrosphere.renderer.ui.font.FontManager) - Keeps track of all fonts loaded into the engine.
[FontUtils.java](@ref #electrosphere.renderer.ui.font.FontUtils) - Utilities to load fonts from disk
[BitmapCharacter.java](@ref #electrosphere.renderer.ui.font.bitmapchar.BitmapCharacter) - The main rendering component for text. Renders a single character of text based on a given font, font size, and character.
## Code Organization and Best Practices
#### Startup
#### Usage
## Terminology
## Known Bugs To Fix
## Future Goals
- Scan assets/fonts and load all fonts automatically
- Ability to specify font for a given label (currently it's always hard-set to "default")

View File

@ -57,8 +57,7 @@ import electrosphere.renderer.shader.ShaderOptionMap;
import electrosphere.renderer.texture.TextureMap;
import electrosphere.renderer.ui.ElementManager;
import electrosphere.renderer.ui.elements.ImagePanel;
import electrosphere.renderer.ui.font.FontUtils;
import electrosphere.renderer.ui.font.RawFontMap;
import electrosphere.renderer.ui.font.FontManager;
import electrosphere.script.ScriptEngine;
import electrosphere.server.ai.AIManager;
import electrosphere.server.content.ServerContentManager;
@ -231,6 +230,9 @@ public class Globals {
public static String particleBillboardModel;
public static ShaderOptionMap shaderOptionMap;
//manages all loaded fonts
public static FontManager fontManager;
@ -435,9 +437,10 @@ public class Globals {
materialDefault.set_diffuse("Textures/default_diffuse.png");
materialDefault.set_specular("Textures/default_specular.png");
//create default lights
//create font manager
fontManager = new FontManager();
fontManager.loadFonts();
assetManager.registerModelToSpecificString(RenderUtils.createBitmapCharacter(), AssetDataStrings.BITMAP_CHARACTER_MODEL);
RawFontMap fontMap = FileUtils.loadObjectFromAssetPath("Textures/Fonts/myFont2Map.json", RawFontMap.class);
FontUtils.setFontDataMap(fontMap);
//particle billboard model
particleBillboardModel = assetManager.registerModel(RenderUtils.createParticleModel());
//black texture for backgrouns

View File

@ -515,7 +515,21 @@ public class Model {
this.textureMap = textureMask;
}
/**
* Sets the shader program to use drawing the modal
* @param program The shader program
*/
public void setProgram(ShaderProgram program){
this.program = program;
}
/**
* Utility method to attempt overwriting the model's meshes with a new material
* @param material The material
*/
public void tryOverwriteMaterial(Material material){
for(Mesh mesh : meshes){
mesh.setMaterial(material);
}
}
}

View File

@ -717,7 +717,10 @@ public class RenderUtils {
/**
* Creates a model to use to show bitmap characters
* @return The model
*/
public static Model createBitmapCharacter(){
Model rVal = new Model();
@ -798,14 +801,6 @@ public class RenderUtils {
m.parent = rVal;
m.nodeID = AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME;
Material uiMat = new Material();
Globals.assetManager.addTexturePathtoQueue("/Textures/Fonts/myfont2.png");
uiMat.set_diffuse("/Textures/Fonts/myfont2.png");
uiMat.set_specular("/Textures/Fonts/myfont2.png");
m.setMaterial(uiMat);
rVal.materials = new ArrayList<Material>();
rVal.materials.add(uiMat);
rVal.meshes.add(m);
return rVal;

View File

@ -33,7 +33,7 @@ public class Texture {
String path = "";
public Texture(){
private Texture(){
}
@ -41,6 +41,73 @@ public class Texture {
this.texturePointer = pointer;
}
/**
* Creates an in engine texture object from a java bufferedimage object
* @param bufferedImage The java bufferedimage object
*/
public Texture(BufferedImage bufferedImage){
texturePointer = glGenTextures();
//bind the new texture
glBindTexture(GL_TEXTURE_2D, texturePointer);
//how are we gonna wrap the texture??
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
//set the border color to black
float borderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
//set magnification and minification operation sampling strategies
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//load the image here
ByteBuffer data;
width = 1;
height = 1;
BufferedImage image_data = bufferedImage;
if (
image_data.getType() == BufferedImage.TYPE_3BYTE_BGR ||
image_data.getType() == BufferedImage.TYPE_INT_RGB
){
hasTransparency = false;
} else if(
image_data.getType() == BufferedImage.TYPE_4BYTE_ABGR ||
image_data.getType() == BufferedImage.TYPE_INT_ARGB
){
hasTransparency = true;
}
width = image_data.getWidth();
height = image_data.getHeight();
if(hasTransparency){
data = BufferUtils.createByteBuffer(width * height * 4);
} else {
data = BufferUtils.createByteBuffer(width * height * 3);
}
for(int y = height - 1; y > -1; y--){
for(int x = 0; x < width; x++){
Color temp = new Color(image_data.getRGB(x, y), true);
data.put((byte)temp.getRed());
data.put((byte)temp.getGreen());
data.put((byte)temp.getBlue());
if(hasTransparency){
data.put((byte)temp.getAlpha());
}
}
}
data.flip();
//call if width != height so opengl figures out how to unpack it properly
if(width != height){
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}
//buffer the texture information
if(hasTransparency){
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
} else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
}
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
}
public Texture(String path){
this.path = path;
if(!Globals.HEADLESS){

View File

@ -10,6 +10,7 @@ import electrosphere.renderer.debug.DebugRendering;
import electrosphere.renderer.ui.DrawableElement;
import electrosphere.renderer.ui.Element;
import electrosphere.renderer.ui.events.Event;
import electrosphere.renderer.ui.font.Font;
import electrosphere.renderer.ui.font.FontUtils;
import electrosphere.renderer.ui.font.bitmapchar.BitmapCharacter;
@ -39,12 +40,15 @@ public class Label implements DrawableElement {
List<BitmapCharacter> childrenElements = new LinkedList<BitmapCharacter>();
static final Vector3f windowDrawDebugColor = new Vector3f(1.0f,1.0f,1.0f);
Font font;
public Label(int x, int y, float fontSize){
this.positionX = x;
this.positionY = y;
this.width = 0;
this.height = (int)(FontUtils.getFontHeight() * fontSize);
this.font = Globals.fontManager.getFont("default");
this.height = (int)(font.getFontHeight() * fontSize);
this.fontSize = fontSize;
}
@ -53,8 +57,8 @@ public class Label implements DrawableElement {
int rollingOffset = 0;
for(int i = 0; i < text.length(); i++){
char toDraw = text.charAt(i);
Vector3f bitMapDimension = FontUtils.getDimensionOfCharacterDiscrete(toDraw);
BitmapCharacter newLetter = new BitmapCharacter((int)(rollingOffset * fontSize) + positionX, positionY, (int)(bitMapDimension.x * fontSize), this.height, toDraw);
Vector3f bitMapDimension = this.font.getDimensionOfCharacterDiscrete(toDraw);
BitmapCharacter newLetter = new BitmapCharacter(this.font,(int)(rollingOffset * fontSize) + positionX, positionY, (int)(bitMapDimension.x * fontSize), this.height, toDraw);
rollingOffset += (int)bitMapDimension.x;
childrenElements.add(newLetter);
}
@ -64,7 +68,7 @@ public class Label implements DrawableElement {
this.text = text;
textPixelWidth = 0;
for(int i = 0; i < text.length(); i++){
Vector3f bitMapDimension = FontUtils.getDimensionOfCharacterDiscrete(text.charAt(i));
Vector3f bitMapDimension = this.font.getDimensionOfCharacterDiscrete(text.charAt(i));
textPixelWidth = textPixelWidth + (int)bitMapDimension.x;
}
generateLetters();

View File

@ -5,6 +5,7 @@ import java.util.List;
import org.joml.Vector3f;
import electrosphere.engine.Globals;
import electrosphere.renderer.ui.DrawableElement;
import electrosphere.renderer.ui.Element;
import electrosphere.renderer.ui.FocusableElement;
@ -15,6 +16,7 @@ import electrosphere.renderer.ui.events.FocusEvent;
import electrosphere.renderer.ui.events.MenuEvent;
import electrosphere.renderer.ui.events.ValueChangeEvent;
import electrosphere.renderer.ui.events.MenuEvent.MenuEventType;
import electrosphere.renderer.ui.font.Font;
import electrosphere.renderer.ui.font.FontUtils;
import electrosphere.renderer.ui.font.bitmapchar.BitmapCharacter;
@ -46,12 +48,15 @@ public class StringCarousel implements DrawableElement, MenuEventElement, Focusa
float fontSize = 1.0f;
List<BitmapCharacter> childrenElements = new LinkedList<BitmapCharacter>();
Font font;
public StringCarousel(int x, int y, float fontSize){
this.positionX = x;
this.positionY = y;
this.width = 0;
this.height = (int)(FontUtils.getFontHeight() * fontSize);
this.font = Globals.fontManager.getFont("default");
this.height = (int)(font.getFontHeight() * fontSize);
this.fontSize = fontSize;
}
@ -82,8 +87,8 @@ public class StringCarousel implements DrawableElement, MenuEventElement, Focusa
int rollingOffset = 0;
for(int i = 0; i < textCurrent.length(); i++){
char toDraw = textCurrent.charAt(i);
Vector3f bitMapDimension = FontUtils.getDimensionOfCharacterDiscrete(toDraw);
BitmapCharacter newLetter = new BitmapCharacter((int)(rollingOffset * fontSize) + positionX, positionY, (int)(bitMapDimension.x * fontSize), this.height, toDraw);
Vector3f bitMapDimension = this.font.getDimensionOfCharacterDiscrete(toDraw);
BitmapCharacter newLetter = new BitmapCharacter(this.font,(int)(rollingOffset * fontSize) + positionX, positionY, (int)(bitMapDimension.x * fontSize), this.height, toDraw);
rollingOffset += (int)bitMapDimension.x;
childrenElements.add(newLetter);
}
@ -93,7 +98,7 @@ public class StringCarousel implements DrawableElement, MenuEventElement, Focusa
this.textCurrent = text;
textPixelWidth = 0;
for(int i = 0; i < text.length(); i++){
Vector3f bitMapDimension = FontUtils.getDimensionOfCharacterDiscrete(text.charAt(i));
Vector3f bitMapDimension = this.font.getDimensionOfCharacterDiscrete(text.charAt(i));
textPixelWidth = textPixelWidth + (int)bitMapDimension.x;
}
generateLetters();

View File

@ -14,6 +14,7 @@ import electrosphere.renderer.ui.KeyEventElement;
import electrosphere.renderer.ui.events.Event;
import electrosphere.renderer.ui.events.FocusEvent;
import electrosphere.renderer.ui.events.KeyboardEvent;
import electrosphere.renderer.ui.font.Font;
import electrosphere.renderer.ui.font.FontUtils;
import electrosphere.renderer.ui.font.bitmapchar.BitmapCharacter;
@ -54,12 +55,15 @@ public class TextInput implements DrawableElement, FocusableElement, KeyEventEle
float fontSize = 1.0f;
List<BitmapCharacter> childrenElements = new LinkedList<BitmapCharacter>();
Font font;
public TextInput(int x, int y, float fontSize){
this.positionX = x;
this.positionY = y;
this.width = 0;
this.height = (int)(FontUtils.getFontHeight() * fontSize);
this.font = Globals.fontManager.getFont("default");
this.height = (int)(this.font.getFontHeight() * fontSize);
this.fontSize = fontSize;
this.color = new Vector3f(1,1,1);
}
@ -69,8 +73,8 @@ public class TextInput implements DrawableElement, FocusableElement, KeyEventEle
int rollingOffset = 0;
for(int i = 0; i < text.length(); i++){
char toDraw = text.charAt(i);
Vector3f bitMapDimension = FontUtils.getDimensionOfCharacterDiscrete(toDraw);
BitmapCharacter newLetter = new BitmapCharacter((int)(rollingOffset * fontSize) + positionX, positionY, (int)(bitMapDimension.x * fontSize), this.height, toDraw);
Vector3f bitMapDimension = this.font.getDimensionOfCharacterDiscrete(toDraw);
BitmapCharacter newLetter = new BitmapCharacter(this.font,(int)(rollingOffset * fontSize) + positionX, positionY, (int)(bitMapDimension.x * fontSize), this.height, toDraw);
newLetter.setColor(color);
rollingOffset += (int)bitMapDimension.x;
childrenElements.add(newLetter);
@ -81,7 +85,7 @@ public class TextInput implements DrawableElement, FocusableElement, KeyEventEle
this.text = text;
textPixelWidth = 0;
for(int i = 0; i < text.length(); i++){
Vector3f bitMapDimension = FontUtils.getDimensionOfCharacterDiscrete(text.charAt(i));
Vector3f bitMapDimension = this.font.getDimensionOfCharacterDiscrete(text.charAt(i));
textPixelWidth = textPixelWidth + (int)bitMapDimension.x;
}
generateLetters();

View File

@ -0,0 +1,143 @@
package electrosphere.renderer.ui.font;
import java.util.HashMap;
import java.util.List;
import org.joml.Vector3f;
import electrosphere.renderer.Material;
/**
* A font
*/
public class Font {
//the font image
Material fontMaterial;
//the list of glyphs for the font
public List<Glyph> glyphs;
//dimensions of the font image
public int imageWidth;
public int imageHeight;
//the map of character->position in the image
HashMap<Character,Vector3f> positionMap = new HashMap<Character,Vector3f>();
//the map of character->dimension of the character in pixels
HashMap<Character,Vector3f> dimensionMap = new HashMap<Character,Vector3f>();
/**
* Creates the font object
* @param fontMaterial
* @param glyphs
* @param imageWidth
* @param imageHeight
*/
protected Font(
Material fontMaterial,
List<Glyph> glyphs,
int imageWidth,
int imageHeight
){
this.fontMaterial = fontMaterial;
this.glyphs = glyphs;
this.imageHeight = imageHeight;
this.imageWidth = imageWidth;
}
/**
* Data about a single glyph in the font
*/
public static class Glyph {
public String symbol;
public int startX;
public int startY;
public int width;
public int height;
}
/**
* Gets the position of a given character
* @param character The character
* @return the position
*/
public Vector3f getPositionOfCharacter(char character){
Vector3f position;
if((position = positionMap.get(character))!=null){
position = new Vector3f(position);
position.x = position.x / imageWidth;
position.y = position.y / imageHeight;
} else {
position = new Vector3f();
}
return position;
}
/**
* Gets the dimensions of a given character
* @param character the character
* @return the dimensions
*/
public Vector3f getDimensionOfCharacter(char character){
Vector3f dimension;
if((dimension = dimensionMap.get(character))!=null){
dimension = new Vector3f(dimension);
dimension.x = dimension.x / imageWidth;
dimension.y = dimension.y / imageHeight;
} else {
dimension = new Vector3f(0.5f,0.5f,0f);
}
return dimension;
}
/**
* Gets the dimensions of a given character in discrete pixels
* @param character The character
* @return the dimensions in pixels
*/
public Vector3f getDimensionOfCharacterDiscrete(char character){
Vector3f dimension;
if((dimension = dimensionMap.get(character))!=null){
dimension = new Vector3f(dimension);
} else {
dimension = new Vector3f(12,14,0f);
}
return dimension;
}
/**
* Gets the height of the font
* @return the height
*/
public int getFontHeight(){
return imageHeight;
}
/**
* Processes the glyphs into structures that will contain instantly lookup-able data
*/
protected void process(){
for(Glyph glyph : glyphs){
char charVal = glyph.symbol.charAt(0);
Vector3f position = new Vector3f(glyph.startX,glyph.startY,0);
positionMap.put(charVal,position);
}
//fill dimension map
dimensionMap.clear();
for(Glyph glyph : glyphs){
char charVal = glyph.symbol.charAt(0);
Vector3f dimension = new Vector3f(glyph.width,glyph.height,0);
dimensionMap.put(charVal,dimension);
}
}
/**
* Gets the material for the font
* @return The material
*/
public Material getMaterial(){
return fontMaterial;
}
}

View File

@ -0,0 +1,55 @@
package electrosphere.renderer.ui.font;
import java.awt.FontFormatException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.Material;
import electrosphere.util.FileUtils;
/**
* Manages all fonts loaded into the engine
*/
public class FontManager {
//the default font
Font defaultFont;
//maps names of fonts to font objects
Map<String,Font> fontMap = new HashMap<String,Font>();
/**
* Gets a font based on an identifying string
* @param identifier the identifying string
* @return The font if it exists or null
*/
public Font getFont(String identifier){
return fontMap.get(identifier);
}
/**
* Loads fonts at engine startup during the init graphics resource phase
*/
public void loadFonts(){
java.awt.Font font = null;
try {
font = java.awt.Font.createFont(java.awt.Font.TRUETYPE_FONT, FileUtils.getAssetFileAsStream("Fonts/Tuffy_Bold.ttf"));
font = font.deriveFont(24f);
} catch (FontFormatException e) {
LoggerInterface.loggerEngine.ERROR("Failed to load a font!", e);
} catch (IOException e) {
LoggerInterface.loggerEngine.ERROR("Failed to load a font!", e);
}
if(font==null){
font = new java.awt.Font(java.awt.Font.MONOSPACED, java.awt.Font.PLAIN, 16);
}
if(font!=null){
defaultFont = FontUtils.loadFont(font, false);
fontMap.put("default",defaultFont);
}
}
}

View File

@ -1,87 +1,162 @@
package electrosphere.renderer.ui.font;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.renderer.Model;
import electrosphere.renderer.ModelUtils;
import electrosphere.renderer.actor.ActorUtils;
import electrosphere.renderer.ui.font.RawFontMap.Glyph;
import java.util.HashMap;
import org.joml.Vector3f;
import org.joml.Vector3i;
import electrosphere.renderer.Material;
import electrosphere.renderer.texture.Texture;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.awt.RenderingHints;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.util.LinkedList;
import java.util.List;
import javax.imageio.ImageIO;
/**
*
* @author amaterasu
* Utilities for loading fonts
*/
public class FontUtils {
static RawFontMap rawFontMap;
static HashMap<Character,Vector3f> positionMap = new HashMap<Character,Vector3f>();
static HashMap<Character,Vector3f> dimensionMap = new HashMap<Character,Vector3f>();
static int width = 10;
static int height = 10;
public static Vector3f getPositionOfCharacter(char character){
Vector3f position;
if((position = positionMap.get(character))!=null){
position = new Vector3f(position);
position.x = position.x / rawFontMap.imageWidth;
position.y = position.y / rawFontMap.imageHeight;
} else {
position = new Vector3f();
/**
* Renders a single character to a buffered image
* @param font The java font object
* @param c the character
* @param antiAlias whether to antialias the font or not
* @return The buffered image with the rendered font
*/
private static BufferedImage createCharImage(java.awt.Font font, char c, boolean antiAlias) {
//get the size of the character
BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
if(antiAlias){
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
return position;
g.setFont(font);
FontMetrics metrics = g.getFontMetrics();
g.dispose();
int charWidth = metrics.charWidth(c);
int charHeight = metrics.getHeight();
//return 0 width characters
if (charWidth == 0) {
return null;
}
//render character to a properly sized buffered image
image = new BufferedImage(charWidth, charHeight, BufferedImage.TYPE_INT_ARGB);
g = image.createGraphics();
if (antiAlias) {
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
g.setFont(font);
g.setPaint(java.awt.Color.WHITE);
g.drawString(String.valueOf(c), 0, metrics.getAscent());
g.dispose();
return image;
}
public static Vector3f getDimensionOfCharacter(char character){
Vector3f dimension;
if((dimension = dimensionMap.get(character))!=null){
dimension = new Vector3f(dimension);
dimension.x = dimension.x / rawFontMap.imageWidth;
dimension.y = dimension.y / rawFontMap.imageHeight;
} else {
dimension = new Vector3f(0.5f,0.5f,0f);
/**
* Loads a java font object into an engine font object
* @param font The java font object
* @param antiAlias if true, antialias, otherwise dont
* @return The engine font object
*/
protected static Font loadFont(java.awt.Font font, boolean antiAlias) {
int imageWidth = 0;
int imageHeight = 0;
//data for parsing characters out of the font image
List<Font.Glyph> glyphs = new LinkedList<Font.Glyph>();
//iterate through ascii codes
for(int i = 32; i < 256; i++){
if(i == 127){
//skip del character
continue;
}
char c = (char)i;
BufferedImage ch = createCharImage(font, c, antiAlias);
if(ch == null){
//skip characters with no images
continue;
}
imageWidth += ch.getWidth();
imageHeight = Math.max(imageHeight, ch.getHeight());
}
return dimension;
}
public static Vector3f getDimensionOfCharacterDiscrete(char character){
Vector3f dimension;
if((dimension = dimensionMap.get(character))!=null){
dimension = new Vector3f(dimension);
} else {
dimension = new Vector3f(12,14,0f);
int fontHeight = imageHeight;
//create font bitmap
BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
int x = 0;
//loop through ascii codes
for (int i = 32; i < 256; i++) {
if (i == 127) {
//skip del character command
continue;
}
char c = (char) i;
BufferedImage charImage = createCharImage(font, c, antiAlias);
if (charImage == null) {
//don't render if the character is blank
continue;
}
int charWidth = charImage.getWidth();
int charHeight = charImage.getHeight();
//draw the glyph to the image
g.drawImage(charImage, x, 0, null);
//create glyph and push it into the array
Font.Glyph glyph = new Font.Glyph();
glyph.height = charHeight;
glyph.width = charWidth;
glyph.startX = x;
glyph.startY = 0;
glyph.symbol = (char)i + "";
glyphs.add(glyph);
//increment image
x += charWidth;
}
return dimension;
}
public static int getFontHeight(){
return height;
}
public static void setFontDataMap(RawFontMap map){
rawFontMap = map;
width = map.imageWidth;
height = map.imageHeight;
//fill position map
positionMap.clear();
for(Glyph glyph : rawFontMap.glyphs){
char charVal = glyph.symbol.charAt(0);
Vector3f position = new Vector3f(glyph.startX,glyph.startY,0);
positionMap.put(charVal,position);
}
//fill dimension map
dimensionMap.clear();
for(Glyph glyph : rawFontMap.glyphs){
char charVal = glyph.symbol.charAt(0);
Vector3f dimension = new Vector3f(glyph.width,glyph.height,0);
dimensionMap.put(charVal,dimension);
//uncomment if you need to flip the font
// AffineTransform transform = AffineTransform.getScaleInstance(1f, -1f);
// transform.translate(0, -image.getHeight());
// AffineTransformOp operation = new AffineTransformOp(transform, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
// image = operation.filter(image, null);
try {
ImageIO.write(image, "png", Files.newOutputStream(new File("C:/users/satellite/Pictures/testimg.png").toPath()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//create material with new font image
Material uiMat = new Material();
Texture texture = new Texture(image);
uiMat.setTexturePointer(texture.getTexturePointer());
//construct final font object and return
Font rVal = new Font(uiMat,glyphs,imageWidth,imageHeight);
rVal.process();
return rVal;
}

View File

@ -1,27 +0,0 @@
package electrosphere.renderer.ui.font;
import java.util.HashMap;
import java.util.List;
import org.joml.Vector3f;
/**
*
* @author amaterasu
*/
public class RawFontMap {
public List<Glyph> glyphs;
public int imageWidth;
public int imageHeight;
public class Glyph {
public String symbol;
public int startX;
public int startY;
public int width;
public int height;
}
}

View File

@ -2,10 +2,12 @@ package electrosphere.renderer.ui.font.bitmapchar;
import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.renderer.Material;
import electrosphere.renderer.Model;
import electrosphere.renderer.ui.DrawableElement;
import electrosphere.renderer.ui.events.Event;
import electrosphere.renderer.ui.font.FontUtils;
import electrosphere.renderer.ui.font.Font;
// import electrosphere.renderer.ui.font.FontUtils;
import org.joml.Vector3f;
/**
@ -17,15 +19,18 @@ public class BitmapCharacter implements DrawableElement {
String text;
Vector3f color = new Vector3f(0,0,0);
Font font;
public BitmapCharacter(int posX, int posY, int width, int height, char toDraw){
public BitmapCharacter(Font font, int posX, int posY, int width, int height, char toDraw){
this.positionX = posX;
this.positionY = posY;
this.width = width;
this.height = height;
this.text = "" + toDraw;
this.font = font;
}
@ -56,13 +61,16 @@ public class BitmapCharacter implements DrawableElement {
char toDraw = text.charAt(0);
Vector3f characterPosition = new Vector3f(ndcX,ndcY,0);
Vector3f characterDimensions = new Vector3f(ndcWidth,ndcHeight,0);
Vector3f bitMapPosition = FontUtils.getPositionOfCharacter(toDraw);
Vector3f bitMapDimension = FontUtils.getDimensionOfCharacter(toDraw);
Vector3f bitMapPosition = this.font.getPositionOfCharacter(toDraw);
Vector3f bitMapDimension = this.font.getDimensionOfCharacter(toDraw);
// bitMapDimension.y = 1;
// System.out.println(bitMapPosition);
// System.out.println(bitMapDimension);
// System.out.println("\n\n");
//load model and try overwriting with font material
Model charModel = Globals.assetManager.fetchModel(AssetDataStrings.BITMAP_CHARACTER_MODEL);
Material mat = this.font.getMaterial();
charModel.tryOverwriteMaterial(mat);
if(charModel != null && toDraw != ' '){
charModel.pushUniformToMesh(AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME, "mPosition", characterPosition);
charModel.pushUniformToMesh(AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME, "mDimension", characterDimensions);