I have a png font, and I can correctly get the row/ column of each letter the problem is what to with that information. Each character is 8 by 8. Here is the code I have so far.
If anyone could give me some help or even just some advice it would be greatly appreciated.
private double xsize, ysize, x, y, rotate, xh, yh;
private int lxpos, lypos;
private Texture texture;
String text;
public TextRenderer(int fontsize, int xlocation, int ylocation,
int rotates, String path, String Text) {
text = Text;
rotate = rotates;
setXsize(fontsize);
ysize = fontsize;
x = xlocation;
y = ylocation;
setXh(getXsize() / 2);
yh = ysize / 2;
try {
texture = TextureLoader.getTexture(".PNG", new FileInputStream(
new File(path)));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
texture.bind();
update();
}
public void update() {
char[] c = text.toCharArray();
int letter;
// 16 collumns 16 rows
for (int i = 0; i < c.length; i++) {
letter = c[i];
System.out.println(c[i]);
lypos = letter % 16;
lypos++;
System.out.println("Collumn :" + lypos);
lxpos = letter / 16;
System.out.println("Row :" + lxpos);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glPushMatrix();
GL11.glTranslated(x, y, 0);
GL11.glTranslatef(10.0f, 10.5f, -0.0f); // back to previous position
GL11.glRotated(rotate, 0.0f, 0.0f, -1.0f); // rotate
GL11.glTranslatef(-10.0f, -10.5f, 0.0f); // to the origin
GL11.glTranslated(-x, -y, 0);
// above is for movement/rotation of text
// 128 px total
lxpos = lxpos * 8;
lxpos = lxpos * 8;
int startx = lxpos * 8;
int starty = lypos * 8;
double endx = startx + 8;
double endy = starty + 8;
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2d(startx, starty);
GL11.glVertex2d(x - getXh(), y - yh);
GL11.glTexCoord2d(startx, endy);
GL11.glVertex2d(x - getXh(), y + yh);
GL11.glTexCoord2d(endx, endy);
GL11.glVertex2d(x + getXh(), y + yh);
GL11.glTexCoord2d(endx, starty);
GL11.glVertex2d(x + getXh(), y - yh);
GL11.glEnd();
GL11.glPopMatrix();
GL11.glDisable(GL11.GL_TEXTURE_2D);
Here is what I did:
public class Fsc {
public static Fsc cA = new Fsc((XCOORDINSHEET), (XCOORDINSHEET), (WIDTHOFCHAR), (HEIGHTOFCHAR));
etc...
public int ix, iy, width, height;
public Fsc(int ixa, int iya, int widtha, int heighta) {
ix = ixa;
iy = iya;
width = widtha;
height = heighta;
}
public void render(int xa, int ya, float scale) {
int x2 = ix + width;
int y2 = iy + height;
glBegin(GL_QUADS);
glTexCoord2f(ix, iy);
glVertex2f(xa, ya);
glTexCoord2f(x2, iy);
glVertex2f(xa + width * scale, ya);
glTexCoord2f(x2, y2);
glVertex2f(xa + width * scale, ya + height * scale);
glTexCoord2f(ix, y2);
glVertex2f(xa, ya + height * scale);
glEnd();
}
}
public class Fontsheet {
public int sheet;
public Fontsheet(String location) {
sheet = ImagingTools.glLoadTextureLinear(location);
}
public void render(int x, int y, float scale, String text) {
glEnable(GL_TEXTURE_RECTANGLE_ARB);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sheet);
float lwidth = 0;
int x2 = x;
for(int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
x2 += lwidth;
switch(c) {
case 'A':
Fsc.cA.render(x2, y2, scale);lwidth = Fsc.cA.width * scale;
break;
case 'B': etc...
}
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
glDisable(GL_TEXTURE_RECTANGLE_ARB);
}
}
Sorry for it not being formatted. I know for a fact that it works because I use it actively. I may have forgot a bit of code when copying it over. If it doesn't work for you, just tell me.
Hope it helps you.
Related
I've looked at several examples of people creating tile maps, and I am unable to get the tile position where my mouse is pointed at.
I am using a spritebatch and GameTile[][] to create the map. Keep in mind that the tiles themselves are isometric and not actually a square.
The method renderMap() is where the map is actually is being rendered. createMap() just sets the initial GameTiles for an empty map.
The map is able to be dragged and zoomed in and out using Ortho camera.
Zooming out gives me an issue as well, the tiles seem to be shifted over on click
public class MapEditor implements GameScene {
private GameContext context;
private SpriteBatch batch;
private OrthographicCamera camera;
public static GameTile[][] tiles; //GameTile.WIDTH = 64 & GameTile.HEIGHT =48
public static final int MAP_WIDTH = 20;
public static final int MAP_HEIGHT = 36;
public MapEditor(GameContext context) {
this.context = context;
tiles = new GameTile[MAP_WIDTH][MAP_HEIGHT];
}
#Override
public void create() {
renderer = new ShapeRenderer();
this.batch = new SpriteBatch();
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
public void createMap() {
// Create the sea tiles
for (int x = 0; x < MAP_WIDTH; x++) {
for (int y = 0; y < MAP_HEIGHT; y++) {
if (y < 3 || y > 32) {
if(tiles[x][y] == null) {
tiles[x][y] = safezone;
}
}
else {
if(tiles[x][y] == null) {
tiles[x][y] = cell;
}
}
}
}
}
#Override
public void update(){
// update the camera
camera.update();
}
#Override
public void render() {
batch.setProjectionMatrix(camera.combined);
batch.begin();
Gdx.gl.glViewport(0,0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
renderMap();
batch.end();
}
public int getTileX(float x, float y) {
/*
* getRegionWidth() = TILE_WIDTH_HALF
* getRegionHeight() = TILE_HEIGHT_HALF
* these are the ones being added to worldCoords.x/y
*/
Vector3 worldCoords = camera.unproject(new Vector3(x, y, 0));
return (int)((TILE_WIDTH_HALF * ((-TILE_HEIGHT_HALF + (worldCoords.y + TILE_HEIGHT_HALF)) /
TILE_HEIGHT_HALF) + (worldCoords.x + TILE_WIDTH_HALF)) / TILE_WIDTH_HALF) / 2;
}
public int getTileY(float x, float y) {
/*
* getRegionWidth() = TILE_WIDTH_HALF
* getRegionHeight() = TILE_HEIGHT_HALF
* these are the ones being added to worldCoords.x/y
*/
Vector3 worldCoords = camera.unproject(new Vector3(x, y, 0));
return (int)(((-TILE_HEIGHT_HALF * (TILE_WIDTH_HALF + (worldCoords.x + TILE_WIDTH_HALF)) /
TILE_WIDTH_HALF) + (worldCoords.y + TILE_HEIGHT_HALF)) / TILE_HEIGHT_HALF) / 2;
}
#Override
public boolean handleClick(float x, float y, int button) {
int tileX = getTileX(x,y);
int tileY = getTileY(x,y);
System.out.println("Tile:"+tileX + ","+tileY);
}
private void renderMap() {
for (int i = 0; i < tiles.length; i++) {
for(int j = 0; j < tiles[i].length; j++) {
TextureRegion region = tiles[i][j].getRegion();
int x = (i * GameTile.TILE_WIDTH / 2) - (j * GameTile.TILE_WIDTH / 2) - region.getRegionWidth() / 2;
int y = (i * GameTile.TILE_HEIGHT / 2) + (j * GameTile.TILE_HEIGHT / 2) - region.getRegionHeight() / 2;
if (canDraw(x, y, GameTile.TILE_WIDTH, GameTile.TILE_HEIGHT)) {
batch.draw(region, x, y);
}
}
}
}
Actual tile before doing anything to it;
Actual:
Desired:
Converting Cartesian coordinates to isometric is (sort of) done like this:
float isometricX = cartesianX - cartesianY;
float isometricY = (cartesianX + cartesianY) * 0.5f;
The formula needs to be scaled by the height-to-width ratio of the tiles as well and I think that is where it's going wrong in your code.
Given an unprojected worldMousePosition you can get the coordinates and tile coordinates like this:
float r = (float) TILE_HEIGHT / (float) TILE_WIDTH;
float mapx = (worldMousePosition.x / TILE_HEIGHT + worldMousePosition.y / (TILE_HEIGHT * r)) * r;
float mapy = (worldMousePosition.y / (TILE_HEIGHT * r) - (worldMousePosition.x / TILE_HEIGHT)) * r;
worldPosition = new Vector2(mapx - 0.5f, mapy + 0.5f); // -.5/+.5 because the drawing isn't aligned to the tile, it's aligned to the image
int tileX = (int) worldPosition.x;
int tileY = (int) worldPosition.y;
Full source code for the example above:
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
public class SandboxGame extends Game {
public static final int TILE_NONE = -1;
public static final int MAP_WIDTH = 20;
public static final int MAP_HEIGHT = 36;
public static final int TILE_WIDTH = 64;
public static final int TILE_HEIGHT = 48;
private SpriteBatch batch;
private OrthographicCamera camera;
private BitmapFont font;
private Vector3 unprojectVector = new Vector3();
private Vector2 worldMousePosition = new Vector2();
private Vector2 worldPosition = new Vector2();
private Texture[] textures;
private int[][] tiles = new int[MAP_WIDTH][MAP_HEIGHT];
#Override
public void create() {
batch = new SpriteBatch();
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
font = new BitmapFont(Gdx.files.internal("default.fnt"), Gdx.files.internal("default.png"), false);
textures = new Texture[] {
new Texture(Gdx.files.internal("tile.png"))
};
for(int x = 0; x < MAP_WIDTH; ++x) {
for(int y = 0; y < MAP_HEIGHT; ++y) {
int rnd = MathUtils.random(10);
if (rnd < 1)
tiles[x][y] = TILE_NONE;
else
tiles[x][y] = 0;
}
}
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
float scrollSpeed = 64;
float zoomSpeed = 2;
float delta = Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.A))
camera.position.x -= delta * scrollSpeed;
if (Gdx.input.isKeyPressed(Input.Keys.D))
camera.position.x += delta * scrollSpeed;
if (Gdx.input.isKeyPressed(Input.Keys.W))
camera.position.y += delta * scrollSpeed;
if (Gdx.input.isKeyPressed(Input.Keys.S))
camera.position.y -= delta * scrollSpeed;
if (Gdx.input.isKeyPressed(Input.Keys.Q))
camera.zoom = Math.min(camera.zoom + zoomSpeed * delta, 8.0f);
if (Gdx.input.isKeyPressed(Input.Keys.E))
camera.zoom = Math.max(camera.zoom - zoomSpeed * delta, 0.5f);
camera.update();
int mx = Gdx.input.getX();
int my = Gdx.input.getY();
camera.unproject(unprojectVector.set(mx, my, 0.0f));
worldMousePosition.set(unprojectVector.x, unprojectVector.y);
float r = (float) TILE_HEIGHT / (float) TILE_WIDTH;
float mapx = (worldMousePosition.x / TILE_HEIGHT + worldMousePosition.y / (TILE_HEIGHT * r)) * r;
float mapy = (worldMousePosition.y / (TILE_HEIGHT * r) - (worldMousePosition.x / TILE_HEIGHT)) * r;
worldPosition = new Vector2(mapx - 0.5f, mapy + 0.5f); // -.5/+.5 because the drawing isn't aligned to the tile, it's aligned to the image
int tileX = (int) worldPosition.x;
int tileY = (int) worldPosition.y;
batch.setProjectionMatrix(camera.combined);
batch.begin();
for (int col = MAP_WIDTH - 1; col >= 0; --col) {
for (int row = MAP_HEIGHT - 1; row >= 0; --row) {
if (tiles[col][row] != TILE_NONE) {
Texture texture = textures[tiles[col][row]];
int x = (col * TILE_WIDTH / 2) - (row * TILE_WIDTH / 2);
int y = (col * TILE_HEIGHT / 2) + (row * TILE_HEIGHT / 2);
batch.setColor(col == tileX && row == tileY ? Color.GRAY : Color.WHITE);
batch.draw(texture, x, y);
}
}
}
if (Gdx.input.isKeyPressed(Input.Keys.SPACE)) {
for (int col = MAP_WIDTH - 1; col >= 0; --col) {
for (int row = MAP_HEIGHT - 1; row >= 0; --row) {
int x = (col * TILE_WIDTH / 2) - (row * TILE_WIDTH / 2);
int y = (col * TILE_HEIGHT / 2) + (row * TILE_HEIGHT / 2);
font.draw(batch, String.format("(%d, %d)", col, row), x, y);
}
}
}
String str = String.format("World position (%.2f, %.2f), Tile (%d, %d)", worldPosition.x, worldPosition.y, (int)worldPosition.x, (int)worldPosition.y);
font.draw(batch, str, worldMousePosition.x, worldMousePosition.y);
batch.end();
}
}
I cant respond to bornander's post, but my tweak would be at
int tileX = (int) Math.Floor(worldPosition.x);
int tileY = (int) Math.Floor(worldPosition.y);
Where simple (int) cast will provide wrong position around 0 with negative values, if there are tiles, while using Math.Floor will work as intended.
I'm trying to always show the front of a 3D font to the user. I tried rotating the font when rotating the camera, but never could get it to work.
I currently have this:
I'm trying to do this (font always faces front):
TrueTypeFont.java
package com.displee.render.font;
import lombok.AllArgsConstructor;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* A TrueType font implementation originally for Slick, edited for Bobjob's Engine
* #original author James Chambers (Jimmy)
* #original author Jeremy Adams (elias4444)
* #original author Kevin Glass (kevglass)
* #original author Peter Korzuszek (genail)
* #new version edited by David Aaron Muhar (bobjob)
*/
public class TrueTypeFont {
public final static int ALIGN_LEFT = 0, ALIGN_RIGHT = 1, ALIGN_CENTER = 2;
/**
* Array that holds necessary information about the font characters
*/
private IntObject[] charArray = new IntObject[256];
/**
* Map of user defined font characters (Character <-> IntObject)
*/
private Map customChars = new HashMap();
/**
* Boolean flag on whether AntiAliasing is enabled or not
*/
private boolean antiAlias;
/**
* Font's size
*/
private int fontSize = 0;
/**
* Font's height
*/
private int fontHeight = 0;
/**
* Texture used to cache the font 0-255 characters
*/
private int fontTextureID;
/**
* Default font texture width
*/
private int textureWidth = 512;
/**
* Default font texture height
*/
private int textureHeight = 512;
/**
* A reference to Java's AWT Font that we create our font texture from
*/
private Font font;
/**
* The font metrics for our Java AWT font
*/
private FontMetrics fontMetrics;
private int correctL = 9, correctR = 8;
private class IntObject {
/**
* Character's width
*/
public int width;
/**
* Character's height
*/
public int height;
/**
* Character's stored x position
*/
public int storedX;
/**
* Character's stored y position
*/
public int storedY;
}
public TrueTypeFont(Font font, boolean antiAlias, char[] additionalChars) {
this.font = font;
this.fontSize = font.getSize() + 3;
this.antiAlias = antiAlias;
createSet(additionalChars);
fontHeight -= 1;
if (fontHeight <= 0) {
fontHeight = 1;
}
}
public TrueTypeFont(Font font, boolean antiAlias) {
this(font, antiAlias, null);
}
public void setCorrection(boolean on) {
if (on) {
correctL = 2;
correctR = 1;
} else {
correctL = 0;
correctR = 0;
}
}
private BufferedImage getFontImage(char ch) {
// Create a temporary image to extract the character's size
BufferedImage tempfontImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) tempfontImage.getGraphics();
if (antiAlias == true) {
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
g.setFont(font);
fontMetrics = g.getFontMetrics();
int charwidth = fontMetrics.charWidth(ch) + 8;
if (charwidth <= 0) {
charwidth = 7;
}
int charheight = fontMetrics.getHeight() + 3;
if (charheight <= 0) {
charheight = fontSize;
}
// Create another image holding the character we are creating
BufferedImage fontImage;
fontImage = new BufferedImage(charwidth, charheight, BufferedImage.TYPE_INT_ARGB);
Graphics2D gt = (Graphics2D) fontImage.getGraphics();
if (antiAlias == true) {
gt.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
gt.setFont(font);
gt.setColor(Color.WHITE);
int charx = 3;
int chary = 1;
gt.drawString(String.valueOf(ch), (charx), (chary) + fontMetrics.getAscent());
//fontImage = ImageUtils.flipVertically(fontImage);
//fontImage = ImageUtils.flipHorizontally(fontImage);
//fontImage = ImageUtils.flipHorizontallyAndVertically(fontImage);
return fontImage;
}
private void createSet(char[] customCharsArray) {
// If there are custom chars then I expand the font texture twice
if (customCharsArray != null && customCharsArray.length > 0) {
textureWidth *= 2;
}
// In any case this should be done in other way. Texture with size 512x512
// can maintain only 256 characters with resolution of 32x32. The texture
// size should be calculated dynamicaly by looking at character sizes.
try {
BufferedImage imgTemp = new BufferedImage(textureWidth, textureHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) imgTemp.getGraphics();
g.setColor(new Color(0, 0, 0, 1));
g.fillRect(0, 0, textureWidth, textureHeight);
int rowHeight = 0;
int positionX = 0;
int positionY = 0;
int customCharsLength = (customCharsArray != null) ? customCharsArray.length : 0;
for (int i = 0; i < 256 + customCharsLength; i++) {
// get 0-255 characters and then custom characters
char ch = (i < 256) ? (char) i : customCharsArray[i - 256];
BufferedImage fontImage = getFontImage(ch);
IntObject newIntObject = new IntObject();
newIntObject.width = fontImage.getWidth();
newIntObject.height = fontImage.getHeight();
if (positionX + newIntObject.width >= textureWidth) {
positionX = 0;
positionY += rowHeight;
rowHeight = 0;
}
newIntObject.storedX = positionX;
newIntObject.storedY = positionY;
if (newIntObject.height > fontHeight) {
fontHeight = newIntObject.height;
}
if (newIntObject.height > rowHeight) {
rowHeight = newIntObject.height;
}
// Draw it here
g.drawImage(fontImage, positionX, positionY, null);
positionX += newIntObject.width;
if (i < 256) { // standard characters
charArray[i] = newIntObject;
} else { // custom characters
customChars.put(new Character(ch), newIntObject);
}
fontImage = null;
}
fontTextureID = loadImage(imgTemp);
//.getTexture(font.toString(), imgTemp);
} catch (Exception e) {
System.err.println("Failed to create font.");
e.printStackTrace();
}
}
private void drawQuad(float drawX, float drawY, float drawX2, float drawY2, float srcX, float srcY, float srcX2, float srcY2, float z) {
float DrawWidth = drawX2 - drawX;
float DrawHeight = drawY2 - drawY;
float TextureSrcX = srcX / textureWidth;
float TextureSrcY = srcY / textureHeight;
float SrcWidth = srcX2 - srcX;
float SrcHeight = srcY2 - srcY;
float RenderWidth = (SrcWidth / textureWidth);
float RenderHeight = (SrcHeight / textureHeight);
GL11.glTexCoord2f(TextureSrcX, TextureSrcY);
GL11.glVertex3f(drawX, drawY, z);
GL11.glTexCoord2f(TextureSrcX, TextureSrcY + RenderHeight);
GL11.glVertex3f(drawX, drawY + DrawHeight, z);
GL11.glTexCoord2f(TextureSrcX + RenderWidth, TextureSrcY + RenderHeight);
GL11.glVertex3f(drawX + DrawWidth, drawY + DrawHeight, z);
GL11.glTexCoord2f(TextureSrcX + RenderWidth, TextureSrcY);
GL11.glVertex3f(drawX + DrawWidth, drawY, z);
}
public int getWidth(String whatchars) {
int totalwidth = 0;
IntObject intObject = null;
int currentChar = 0;
for (int i = 0; i < whatchars.length(); i++) {
currentChar = whatchars.charAt(i);
if (currentChar < 256) {
intObject = charArray[currentChar];
} else {
intObject = (IntObject) customChars.get(new Character((char) currentChar));
}
if (intObject != null) {
totalwidth += intObject.width;
}
}
return totalwidth;
}
public int getHeight() {
return fontHeight;
}
public int getHeight(String HeightString) {
return fontHeight;
}
public int getLineHeight() {
return fontHeight;
}
public void drawString(float x, float y, float z, String whatchars, float scaleX, float scaleY) {
drawString(x, y, z, whatchars, 0, whatchars.length() - 1, scaleX, scaleY, ALIGN_LEFT);
}
public void drawString(float x, float y, float z, String whatchars, float scaleX, float scaleY, int format) {
drawString(x, y, z, whatchars, 0, whatchars.length() - 1, scaleX, scaleY, format);
}
public void drawString(float x, float y, float z, String whatchars, int startIndex, int endIndex, float scaleX, float scaleY, int format) {
IntObject intObject = null;
int charCurrent;
int totalwidth = 0;
int i = startIndex, d, c;
float startY = 0;
switch (format) {
case ALIGN_RIGHT: {
d = -1;
c = correctR;
while (i < endIndex) {
if (whatchars.charAt(i) == '\n') {
startY -= fontHeight;
}
i++;
}
break;
}
case ALIGN_CENTER: {
for (int l = startIndex; l <= endIndex; l++) {
charCurrent = whatchars.charAt(l);
if (charCurrent == '\n') {
break;
}
if (charCurrent < 256) {
intObject = charArray[charCurrent];
} else {
intObject = (IntObject) customChars.get(new Character((char) charCurrent));
}
totalwidth += intObject.width - correctL;
}
totalwidth /= -2;
}
case ALIGN_LEFT:
default: {
d = 1;
c = correctL;
break;
}
}
java.util.List<QuadObject> list = new ArrayList<>(endIndex - startIndex);
while (i >= startIndex && i <= endIndex) {
charCurrent = whatchars.charAt(i);
if (charCurrent < 256) {
intObject = charArray[charCurrent];
} else {
intObject = (IntObject) customChars.get(new Character((char) charCurrent));
}
if (intObject != null) {
if (d < 0) {
totalwidth += (intObject.width - c) * d;
}
if (charCurrent == '\n') {
startY -= fontHeight * d;
totalwidth = 0;
if (format == ALIGN_CENTER) {
for (int l = i + 1; l <= endIndex; l++) {
charCurrent = whatchars.charAt(l);
if (charCurrent == '\n') {
break;
}
if (charCurrent < 256) {
intObject = charArray[charCurrent];
} else {
intObject = (IntObject) customChars.get(new Character((char) charCurrent));
}
totalwidth += intObject.width - correctL;
}
totalwidth /= -2;
}
//if center get next lines total width/2;
} else {
QuadObject quad = new QuadObject((totalwidth + intObject.width) * scaleX + x, startY * scaleY + y, totalwidth * scaleX + x, (startY + intObject.height) * scaleY + y, intObject.storedX + intObject.width, intObject.storedY + intObject.height, intObject.storedX, intObject.storedY, z);
list.add(quad);
if (d > 0) {
totalwidth += (intObject.width - c) * d;
}
}
i += d;
}
}
float centerX = 0;
for(QuadObject quad : list) {
centerX += quad.drawX + (quad.drawX2 - quad.drawX);
}
centerX /= 2.0f;
float centerY = 0;
for(QuadObject quad : list) {
centerY += quad.drawY + (quad.drawY2 - quad.drawY);
}
centerY /= 2.0f;
//GL11.glTranslatef( -centerX, -centerY, -z);
//GL11.glTranslatef(0, 0, -z);
GL11.glRotatef(-Test3DFont.rotation.x, 0.0f, 0.0f, 0.0f);
GL11.glRotatef(-Test3DFont.rotation.y, 0.0f, 1.0f, 0.0f);
//GL11.glRotatef(-Test3DFont.rotation.z, 0.0f, 0.0f, 1.0f);
//GL11.glTranslatef(0, 0, z);
//GL11.glTranslatef(centerX, centerY, z); // M1 - 2nd translation
GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
GL11.glBindTexture(GL11.GL_TEXTURE_2D, fontTextureID);
GL11.glBegin(GL11.GL_QUADS);
for(QuadObject quad : list) {
drawQuad(quad.drawX, quad.drawY, quad.drawX2, quad.drawY2, quad.srcX, quad.srcY, quad.srcX2, quad.srcY2, quad.z);
}
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnd();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
}
public static int loadImage(BufferedImage bufferedImage) {
try {
short width = (short) bufferedImage.getWidth();
short height = (short) bufferedImage.getHeight();
//textureLoader.bpp = bufferedImage.getColorModel().hasAlpha() ? (byte)32 : (byte)24;
int bpp = (byte) bufferedImage.getColorModel().getPixelSize();
ByteBuffer byteBuffer;
DataBuffer db = bufferedImage.getData().getDataBuffer();
if (db instanceof DataBufferInt) {
int intI[] = ((DataBufferInt) (bufferedImage.getData().getDataBuffer())).getData();
byte newI[] = new byte[intI.length * 4];
for (int i = 0; i < intI.length; i++) {
byte b[] = intToByteArray(intI[i]);
int newIndex = i * 4;
newI[newIndex] = b[1];
newI[newIndex + 1] = b[2];
newI[newIndex + 2] = b[3];
newI[newIndex + 3] = b[0];
}
byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(newI);
} else {
byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(((DataBufferByte) (bufferedImage.getData().getDataBuffer())).getData());
}
byteBuffer.flip();
int internalFormat = GL11.GL_RGBA8, format = GL11.GL_RGBA;
IntBuffer textureId = BufferUtils.createIntBuffer(1);
;
GL11.glGenTextures(textureId);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId.get(0));
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL11.GL_UNSIGNED_BYTE, byteBuffer.order(ByteOrder.nativeOrder()));
return textureId.get(0);
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
return -1;
}
public static boolean isSupported(String fontname) {
Font font[] = getFonts();
for (int i = font.length - 1; i >= 0; i--) {
if (font[i].getName().equalsIgnoreCase(fontname)) {
return true;
}
}
return false;
}
public static Font[] getFonts() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
}
public static byte[] intToByteArray(int value) {
return new byte[]{(byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value};
}
public void destroy() {
IntBuffer scratch = BufferUtils.createIntBuffer(1);
scratch.put(0, fontTextureID);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
GL11.glDeleteTextures(scratch);
}
#AllArgsConstructor
private class QuadObject {
private float drawX;
private float drawY;
private float drawX2;
private float drawY2;
private float srcX;
private float srcY;
private float srcX2;
private float srcY2;
private float z;
}
}
Test3DFont.java
package com.displee.render.font;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.util.vector.Vector3f;
import java.awt.*;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.gluPerspective;
public class Test3DFont {
private static final int WIDTH = 800;
private static final int HEIGHT = 600;
private static final float FOV = 45f;
private static final float NEAR = 0.1f;
private static final float FAR = 1000f;
private static boolean mousePressed;
private static Vector3f startCoordinations = new Vector3f();
private static float scale = 0.05f;
public static Vector3f rotation = new Vector3f(0, 0, 0);
private static Vector3f startRotation = new Vector3f();
private static TrueTypeFont font;
private static boolean running = true;
public static void main(String[] args) throws Exception {
initializeDisplay();
font = new TrueTypeFont(new Font("serif", Font.PLAIN, 30), true);
initializeGL();
while(running) {
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
handleMouse();
font.drawString(0, 0, 0, "Test", 0.1f, 0.1f);
loadDefaultRotation();
setViewport();
drawGrid();
Display.sync(60);
Display.update();
if (Display.isCloseRequested()) {
break;
}
}
font.destroy();
Display.destroy();
}
private static void initializeDisplay() throws LWJGLException {
Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
Display.create();
setViewport();
}
public static void set2DMode() {
//GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
GL11.glPushMatrix(); // Store The Projection Matrix
GL11.glLoadIdentity(); // Reset The Projection Matrix
GL11.glOrtho(0, WIDTH, 0, HEIGHT, -1, 1); // Set Up An Ortho Screen
GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
GL11.glPushMatrix(); // Store The Modelview Matrix
GL11.glLoadIdentity(); // Reset The Modelview Matrix
}
public static void set3DMode() {
GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
GL11.glPopMatrix(); // Restore The Old Projection Matrix
GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
GL11.glPopMatrix(); // Restore The Old Projection Matrix
//GL11.glEnable(GL11.GL_DEPTH_TEST);
}
private static void setViewport() {
glViewport(0, 0, WIDTH, HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(FOV, (float) WIDTH / (float) HEIGHT, NEAR, FAR);
glMatrixMode(GL_MODELVIEW);
}
private static void initializeGL() {
glShadeModel(GL_SMOOTH);
glEnable(GL_NORMALIZE);
glEnable(GL_BLEND);
glCullFace(GL_BACK);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
private static void handleMouse() {
scale += Mouse.getDWheel() > 0 ? 0.005f : Mouse.getDWheel() < 0 ? -0.005f : 0;
int x = Mouse.getY();
int y = Mouse.getX();
if (!mousePressed) {
mousePressed = Mouse.isButtonDown(0);
if (mousePressed) {
startCoordinations.set((float) x, (float) y, 0.0f);
startRotation = new Vector3f(rotation);
}
} else if (!Mouse.isButtonDown(0)) {
mousePressed = false;
}
if (!mousePressed) {
return;
}
float differenceX = x - startCoordinations.x;
float differenceY = y - startCoordinations.y;
rotation.set(startRotation.x - (differenceX * 0.5F), startRotation.y + (differenceY * 0.5F), 0);
}
private static void loadDefaultRotation() {
glLoadIdentity();
Vector3f cameraPosition = new Vector3f();
glTranslatef(cameraPosition.x, cameraPosition.y, -10);
glRotatef(rotation.x, 1.0F, 0.0F, 0.0F);
glRotatef(rotation.y, 0.0F, 1.0F, 0.0F);
glRotatef(rotation.z, 0.0F, 0.0F, 1.0F);
glScalef(scale, scale, scale);
}
private static void drawGrid() {
glColor4f(0.7176471f, 0.7176471f, 0.7176471f, 1.0f);
glBegin(GL_LINES);
float size = 50;
float step = 10;
for (float i = -size; i <= size; i += step) {
glVertex3f(i, 0, size);
glVertex3f(i, 0, -size);
glVertex3f(size, 0, i);
glVertex3f(-size, 0, i);
}
glEnd();
}
public static int[] getScreenCoords(double x, double y, double z) {
FloatBuffer screenCoords = BufferUtils.createFloatBuffer(4);
IntBuffer viewport = BufferUtils.createIntBuffer(16);
FloatBuffer modelView = BufferUtils.createFloatBuffer(16);
FloatBuffer projection = BufferUtils.createFloatBuffer(16);
GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelView);
GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);
GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);
boolean result = GLU.gluProject((float) x, (float) y, (float) z, modelView, projection, viewport, screenCoords);
if (result) {
return new int[] { (int) screenCoords.get(0), (int) screenCoords.get(1) };
}
return null;
}
}
Can anyone help me with this? How can I make it so I always see the front of the font?
Update 1:
I've got it almost working by rotating the quads. I've added the following code in the drawString method before enabling texture 2D:
GL11.glRotatef(-Test3DFont.rotation.x, 0.0f, 0.0f, 0.0f);
GL11.glRotatef(-Test3DFont.rotation.y, 0.0f, 1.0f, 0.0f);
I've updated the code. It currently looks like this:
I finally fixed it by pushing a matrix and using the original x, y and z coords in the translation. I also had to subtract 180 from the rotation because that's my starting rotation. Ended up with the following code:
GL11.glPushMatrix();
GL11.glTranslatef(x, y, z);
GL11.glRotatef(180 - rotation.y, 0.0f, 1.0f, 0.0f);
GL11.glTranslatef(-x, -y, -z);
GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
GL11.glBindTexture(GL11.GL_TEXTURE_2D, fontTextureID);
GL11.glBegin(GL11.GL_QUADS);
for(QuadObject quad : list) {
drawQuad(quad.drawX, quad.drawY, quad.drawX2, quad.drawY2, quad.srcX, quad.srcY, quad.srcX2, quad.srcY2, quad.z);
}
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnd();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
GL11.glPopMatrix();
I'm trying to draw a circle in LWJGL, but when I draw I try to draw it, it makes a shape that's more like an oval rather than a circle. Also, when I change my circleVertexCount 350+, the shape like flips out. I'm really not sure how the code works that creates the vertices(I have taken Geometry and I know the basic trig ratios). I haven't really found that good of tutorials on creating circles. Here's my code:
public class Circles {
// Setup variables
private int WIDTH = 800;
private int HEIGHT = 600;
private String title = "Circle";
private float fXOffset;
private int vbo = 0;
private int vao = 0;
int circleVertexCount = 300;
float[] vertexData = new float[(circleVertexCount + 1) * 4];
public Circles() {
setupOpenGL();
setupQuad();
while (!Display.isCloseRequested()) {
loop();
adjustVertexData();
Display.update();
Display.sync(60);
}
Display.destroy();
}
public void setupOpenGL() {
try {
Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
Display.setTitle(title);
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
System.exit(-1);
}
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
public void setupQuad() {
float r = 0.1f;
float x;
float y;
float offSetX = 0f;
float offSetY = 0f;
double theta = 2.0 * Math.PI;
vertexData[0] = (float) Math.sin(theta / circleVertexCount) * r + offSetX;
vertexData[1] = (float) Math.cos(theta / circleVertexCount) * r + offSetY;
for (int i = 2; i < 400; i += 2) {
double angle = theta * i / circleVertexCount;
x = (float) Math.cos(angle) * r;
vertexData[i] = x + offSetX;
}
for (int i = 3; i < 404; i += 2) {
double angle = Math.PI * 2 * i / circleVertexCount;
y = (float) Math.sin(angle) * r;
vertexData[i] = y + offSetY;
}
FloatBuffer vertexBuffer = BufferUtils.createFloatBuffer(vertexData.length);
vertexBuffer.put(vertexData);
vertexBuffer.flip();
vao = glGenVertexArrays();
glBindVertexArray(vao);
vbo = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER,vertexBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
public void loop() {
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLE_FAN, 0, vertexData.length / 2);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
}
public static void main(String[] args) {
new Circles();
}
private void adjustVertexData() {
float newData[] = new float[vertexData.length];
System.arraycopy(vertexData, 0, newData, 0, vertexData.length);
if(Keyboard.isKeyDown(Keyboard.KEY_W)) {
fXOffset += 0.05f;
} else if(Keyboard.isKeyDown(Keyboard.KEY_S)) {
fXOffset -= 0.05f;
}
for(int i = 0; i < vertexData.length; i += 2) {
newData[i] += fXOffset;
}
FloatBuffer newDataBuffer = BufferUtils.createFloatBuffer(newData.length);
newDataBuffer.put(newData);
newDataBuffer.flip();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, newDataBuffer);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
300 Vertex Count(This is my main problem)
400 Vertex Count - I removed this image, it's bugged out, should be a tiny sliver cut out from the right, like a secant
500 Vertex Count
Each 100, it removes more and more of the circle, and so on.
One of your problems is this:
for (int i = 2; i < 400; i += 2) {
double angle = theta * i / circleVertexCount;
x = (float) Math.cos(angle) * r;
vertexData[i] = x + offSetX;
}
for (int i = 3; i < 404; i += 2) {
double angle = Math.PI * 2 * i / circleVertexCount;
y = (float) Math.sin(angle) * r;
vertexData[i] = y + offSetY;
}
You are using a different value for angle for the x and y position of each vertex.
You could try this instead:
for (int i = 0; i <= circleVertexCount; i++) {
double angle = i * theta / circleVertexCount;
x = (float) Math.cos(angle) * r;
y = (float) Math.sin(angle) * r;
vertexData[i * 2] = x + offSetX;
vertexData[i * 2 + 1] = y + offSetY;
}
The reason part of your circle was being cut out at higher vertex counts was the i < 400 in your for loops, so I have changed it to i <= circleVertexCount.
Another problem is that your window is not square, and you are not using a shader (or the deprecated built in matrices) to correct this. This means that one unit up looks a different length than one unit right, resulting in an oval instead of a circle. To fix this you could multiply your vertex x position by your display height divided by your display width, preferably in a shader.
So I am trying to create a tool that can convert a .svg file type to a Java Shape or Some kind of class that will allow me to do .contains(x, y) or .contains(Rectangle2D). However I have been unable to find any methods of doing such. I found this post SVG to Java's Path2d parser this seems to give the answer but doesn’t explicitly describe how. I took a look at the classes and don't see how I would load a file then convert it to a shape. I was originally doing this with any kind of image but it turned out to be impractical and really slow. Code for that:
public static Area toArea(URL url, Color color, int tolerance) {
return toArea(toBufferedImage(url), color, tolerance);
}
public static Area toArea(Image image, Color color, int tolerance) {
return toArea(toBufferedImage(image), color, tolerance);
}
/**
* Creates an Area with PixelPerfect precision
*
* #param image
* #param color The color that is draws the Custom Shape
* #param tolerance The color tolerance
* #return Area
*/
public static Area toArea(BufferedImage image, Color color, int tolerance) {
if (image == null) {
return null;
}
Area area = new Area();
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
Color pixel = new Color(image.getRGB(x, y));
if (isIncluded(color, pixel, tolerance)) {
Rectangle r = new Rectangle(x, y, 1, 1);
area.add(new Area(r));
}
}
}
return area;
}
public static Area toArea(URL url) {
return toArea(toBufferedImage(url));
}
public static Area toArea(Image image) {
return toArea(toBufferedImage(image));
}
public static Area toArea(BufferedImage image) {
//Assumes Black as Shape Color
if (image == null) {
return null;
}
Area area = new Area();
Rectangle r;
int y1, y2;
for (int x = 0; x < image.getWidth(); x++) {
y1 = 99;
y2 = -1;
for (int y = 0; y < image.getHeight(); y++) {
Color pixel = new Color(image.getRGB(x, y));
//-16777216 entspricht RGB(0,0,0)
if (pixel.getRGB() == -16777216) {
if (y1 == 99) {
y1 = y;
y2 = y;
}
if (y > (y2 + 1)) {
r = new Rectangle(x, y1, 1, y2 - y1);
area.add(new Area(r));
y1 = y;
y2 = y;
}
y2 = y;
}
}
if ((y2 - y1) >= 0) {
r = new Rectangle(x, y1, 1, y2 - y1);
area.add(new Area(r));
}
}
return area;
}
private static boolean isIncluded(Color target, Color pixel, int tolerance) {
int rT = target.getRed();
int gT = target.getGreen();
int bT = target.getBlue();
int rP = pixel.getRed();
int gP = pixel.getGreen();
int bP = pixel.getBlue();
return ((rP - tolerance <= rT) && (rT <= rP + tolerance)
&& (gP - tolerance <= gT) && (gT <= gP + tolerance)
&& (bP - tolerance <= bT) && (bT <= bP + tolerance));
}
public static BufferedImage toBufferedImage(Image image) {
BufferedImage buffer = new BufferedImage(image.getHeight(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
buffer.createGraphics().drawImage(image, null, null);
return buffer;
}
public static BufferedImage toBufferedImage(URL url) {
try {
return toBufferedImage(ImageIO.read(url));
} catch (IOException ex) {
return null;
}
}
private ImageShaper() {
}
Basically I am trying to write a function that can load a file that stores an irregular shape like a batman logo and then have it able to run a contains function to see if something hit it.
I have a background image I am drawing with open gl 1.0 es.
The problem is when I draw this small image to the big screen I get this...
The lines / breaks in pattern are not suppose to be there. I have tried a lot of things, I thought maybe my atlas was wrong... doubt it. I draw it from (0, 0, 50, 50) which is (x, y, width, height). Checked this a lot and still get the same result, it is as it should be.
Tried different things with my for loop which is below...
GL10 gl = this.glGraphics.getGL();
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
guiCam.setViewportAndMatrices();
gl.glEnable(GL10.GL_TEXTURE_2D);
// Set background color //
batcher.beginBatch(Assets.mainmenuAtlas);
for(int x = Assets.mmbackgroundPattern.width / 2; x < this.scale.getWidth() + Assets.mmbackgroundPattern.width / 2; x += Assets.mmbackgroundPattern.width) {
for(int y = Assets.mmbackgroundPattern.height / 2; y < this.scale.getHeight() + Assets.mmbackgroundPattern.height / 2; y += Assets.mmbackgroundPattern.height) {
batcher.drawSprite(x, y, Assets.mmbackgroundPattern.width, Assets.mmbackgroundPattern.height, Assets.mmbackgroundPattern);
}
}
The viewport & matrices is:
public void setViewportAndMatrices() {
GL10 gl = glGraphics.getGL();
gl.glViewport(0, 0, glGraphics.getWidth(), glGraphics.getHeight());
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrthof(position.x - frustumWidth * zoom / 2,
position.x + frustumWidth * zoom/ 2,
position.y - frustumHeight * zoom / 2,
position.y + frustumHeight * zoom/ 2,
1, -1);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
When I draw sprites:
public void endBatch() {
vertices.setVertices(verticesBuffer, 0, bufferIndex);
vertices.bind();
vertices.draw(GL10.GL_TRIANGLES, 0, numSprites * 6);
vertices.unbind();
}
public void drawSprite(float x, float y, float width, float height, TextureRegion region) {
float halfWidth = width / 2;
float halfHeight = height / 2;
float x1 = x - halfWidth;
float y1 = y - halfHeight;
float x2 = x + halfWidth;
float y2 = y + halfHeight;
verticesBuffer[bufferIndex++] = x1;
verticesBuffer[bufferIndex++] = y1;
verticesBuffer[bufferIndex++] = region.u1;
verticesBuffer[bufferIndex++] = region.v2;
verticesBuffer[bufferIndex++] = x2;
verticesBuffer[bufferIndex++] = y1;
verticesBuffer[bufferIndex++] = region.u2;
verticesBuffer[bufferIndex++] = region.v2;
verticesBuffer[bufferIndex++] = x2;
verticesBuffer[bufferIndex++] = y2;
verticesBuffer[bufferIndex++] = region.u2;
verticesBuffer[bufferIndex++] = region.v1;
verticesBuffer[bufferIndex++] = x1;
verticesBuffer[bufferIndex++] = y2;
verticesBuffer[bufferIndex++] = region.u1;
verticesBuffer[bufferIndex++] = region.v1;
numSprites++;
}
Here are my texture and texture regions:
public TextureRegion(Texture texture, float x, float y, float width, float height) {
this.u1 = x / texture.width;
this.v1 = y / texture.height;
this.u2 = this.u1 + width / texture.width;
this.v2 = this.v1 + height / texture.height;
this.texture = texture;
this.width = (int) width;
this.height = (int) height;
}
public class Texture {
GLGraphics glGraphics;
FileIO fileIO;
Bitmap img;
String fileName;
int textureId;
int minFilter;
int magFilter;
public int width;
public int height;
public Texture(GLGame glGame, String fileName) {
this.glGraphics = glGame.getGLGraphics();
this.fileIO = glGame.getFileIO();
this.fileName = fileName;
try {
load(BitmapFactory.decodeStream(this.fileIO.readAsset(fileName)));
} catch(Exception e) {
e.printStackTrace();
}
}
public Texture(GLGame glGame, Bitmap img) {
this.glGraphics = glGame.getGLGraphics();
this.fileIO = glGame.getFileIO();
this.img = img;
load(img);
}
private void load(Bitmap bitmap) {
GL10 gl = glGraphics.getGL();
int[] textureIds = new int[1];
gl.glGenTextures(1, textureIds, 0);
textureId = textureIds[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
setFilters(GL10.GL_LINEAR, GL10.GL_LINEAR);
gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
width = bitmap.getWidth();
height = bitmap.getHeight();
bitmap.recycle();
}
public void reload() {
if(fileName.equals(null)) {
load(this.img);
} else {
try {
load(BitmapFactory.decodeStream(this.fileIO.readAsset(fileName)));
} catch(Exception e) {
e.printStackTrace();
}
}
bind();
setFilters(minFilter, magFilter);
glGraphics.getGL().glBindTexture(GL10.GL_TEXTURE_2D, 0);
}
public void setFilters(int minFilter, int magFilter) {
this.minFilter = minFilter;
this.magFilter = magFilter;
GL10 gl = glGraphics.getGL();
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, minFilter);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, magFilter);
}
public void bind() {
GL10 gl = glGraphics.getGL();
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
}
public void dispose() {
GL10 gl = glGraphics.getGL();
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
int[] textureIds = { textureId };
gl.glDeleteTextures(1, textureIds, 0);
}
}
I have tried adding and subtracting from the width added and height added, but makes it look worse.
My question is what would you look at to try and fix this problem, I feel very stumped, but I feel like I may have set something wrong in OPENGL. What could I have setup wrong?
I can always provide more code up top, but not exactly sure what you may need.
The image I am re pasting over the whole screen is:
Also the tool I am using to make atlas is found here and I am using the one under the beta tree which is considered build 4. However, I checked the atlas over and it seems just fine.
public class SpriteBatcher {
final float[] verticesBuffer;
int bufferIndex;
final Vertices vertices;
int numSprites;
public SpriteBatcher(GLGraphics glGraphics, int maxSprites) {
this.verticesBuffer = new float[maxSprites*4*4];
this.vertices = new Vertices(glGraphics, maxSprites*4, maxSprites*6, false, true);
this.bufferIndex = 0;
this.numSprites = 0;
short[] indices = new short[maxSprites*6];
int len = indices.length;
short j = 0;
for (int i = 0; i < len; i += 6, j += 4) {
indices[i + 0] = (short)(j + 0);
indices[i + 1] = (short)(j + 1);
indices[i + 2] = (short)(j + 2);
indices[i + 3] = (short)(j + 2);
indices[i + 4] = (short)(j + 3);
indices[i + 5] = (short)(j + 0);
}
vertices.setIndices(indices, 0, indices.length);
}
public void drawSprite(float x, float y, float width, float height, TextureRegion region, boolean corner) {
if(corner) {
float x1 = x;
float y1 = y;
float x2 = x + width;
float y2 = y + height;
verticesBuffer[bufferIndex++] = x1;
verticesBuffer[bufferIndex++] = y1;
verticesBuffer[bufferIndex++] = region.u1;
verticesBuffer[bufferIndex++] = region.v2;
verticesBuffer[bufferIndex++] = x2;
verticesBuffer[bufferIndex++] = y1;
verticesBuffer[bufferIndex++] = region.u2;
verticesBuffer[bufferIndex++] = region.v2;
verticesBuffer[bufferIndex++] = x2;
verticesBuffer[bufferIndex++] = y2;
verticesBuffer[bufferIndex++] = region.u2;
verticesBuffer[bufferIndex++] = region.v1;
verticesBuffer[bufferIndex++] = x1;
verticesBuffer[bufferIndex++] = y2;
verticesBuffer[bufferIndex++] = region.u1;
verticesBuffer[bufferIndex++] = region.v1;
numSprites++;
} else {
drawSprite(x, y, width, height, region);
}
}
public void present(float deltaTime) {
GL10 gl = this.glGraphics.getGL();
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
guiCam.setViewportAndMatrices();
gl.glEnable(GL10.GL_TEXTURE_2D);
// Set background color //
batcher.beginBatch(Assets.mainmenuAtlas);
for(float x = 0; x < this.scale.getWidth(); x += Assets.mmbackgroundPattern.width) {
for(float y = 0; y < this.scale.getHeight(); y += Assets.mmbackgroundPattern.height) {
batcher.drawSprite(x, y, Assets.mmbackgroundPattern.width, Assets.mmbackgroundPattern.height, Assets.mmbackgroundPattern, true);
}
}
Can you try using GL_NEAREST filtering instead of GL_LINEAR? You may be getting some linear sampling between your edge pixels and the border color.
Specifically here:
setFilters(GL10.GL_LINEAR, GL10.GL_LINEAR);