libgdx drawing rectangulars by mouse click - java

I am trying to work with libgdx or better with OpenGL. I have to deal with Java because of my lecture.
I want to draw a backgroud where I can click around with the mouse and where on the mouse position (when I clicked) a new rectangle is drawn. So the "old" rectangles have to stay there.
This is my code so far:
package com.ru.tgra.lab1;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import java.nio.FloatBuffer;
import com.badlogic.gdx.utils.BufferUtils;
public class Lab1Game extends ApplicationAdapter {
private FloatBuffer vertexBuffer;
private FloatBuffer modelMatrix;
private FloatBuffer projectionMatrix;
private int renderingProgramID;
private int vertexShaderID;
private int fragmentShaderID;
private int positionLoc;
private int modelMatrixLoc;
private int projectionMatrixLoc;
private int colorLoc;
private float position_x;
private float position_y;
private float size_rect = 100;
private int screenWidth;
private int screenHeight;
#Override
public void create () {
String vertexShaderString;
String fragmentShaderString;
vertexShaderString = Gdx.files.internal("shaders/simple2D.vert").readString();
fragmentShaderString = Gdx.files.internal("shaders/simple2D.frag").readString();
vertexShaderID = Gdx.gl.glCreateShader(GL20.GL_VERTEX_SHADER);
fragmentShaderID = Gdx.gl.glCreateShader(GL20.GL_FRAGMENT_SHADER);
Gdx.gl.glShaderSource(vertexShaderID, vertexShaderString);
Gdx.gl.glShaderSource(fragmentShaderID, fragmentShaderString);
Gdx.gl.glCompileShader(vertexShaderID);
Gdx.gl.glCompileShader(fragmentShaderID);
renderingProgramID = Gdx.gl.glCreateProgram();
Gdx.gl.glAttachShader(renderingProgramID, vertexShaderID);
Gdx.gl.glAttachShader(renderingProgramID, fragmentShaderID);
Gdx.gl.glLinkProgram(renderingProgramID);
positionLoc = Gdx.gl.glGetAttribLocation(renderingProgramID, "a_position");
Gdx.gl.glEnableVertexAttribArray(positionLoc);
modelMatrixLoc = Gdx.gl.glGetUniformLocation(renderingProgramID, "u_modelMatrix");
projectionMatrixLoc = Gdx.gl.glGetUniformLocation(renderingProgramID, "u_projectionMatrix");
colorLoc = Gdx.gl.glGetUniformLocation(renderingProgramID, "u_color");
Gdx.gl.glUseProgram(renderingProgramID);
float[] pm = new float[16];
pm[0] = 2.0f / Gdx.graphics.getWidth(); pm[4] = 0.0f; pm[8] = 0.0f; pm[12] = -1.0f;
pm[1] = 0.0f; pm[5] = 2.0f / Gdx.graphics.getHeight(); pm[9] = 0.0f; pm[13] = -1.0f;
pm[2] = 0.0f; pm[6] = 0.0f; pm[10] = 1.0f; pm[14] = 0.0f;
pm[3] = 0.0f; pm[7] = 0.0f; pm[11] = 0.0f; pm[15] = 1.0f;
projectionMatrix = BufferUtils.newFloatBuffer(16);
projectionMatrix.put(pm);
projectionMatrix.rewind();
Gdx.gl.glUniformMatrix4fv(projectionMatrixLoc, 1, false, projectionMatrix);
float[] mm = new float[16];
mm[0] = 1.0f; mm[4] = 0.0f; mm[8] = 0.0f; mm[12] = 0.0f;
mm[1] = 0.0f; mm[5] = 1.0f; mm[9] = 0.0f; mm[13] = 0.0f;
mm[2] = 0.0f; mm[6] = 0.0f; mm[10] = 1.0f; mm[14] = 0.0f;
mm[3] = 0.0f; mm[7] = 0.0f; mm[11] = 0.0f; mm[15] = 1.0f;
modelMatrix = BufferUtils.newFloatBuffer(16);
modelMatrix.put(mm);
modelMatrix.rewind();
Gdx.gl.glUniformMatrix4fv(modelMatrixLoc, 1, false, modelMatrix);
//COLOR IS SET HERE
Gdx.gl.glUniform4f(colorLoc, 0.7f, 0.2f, 0, 1);
//VERTEX ARRAY IS FILLED HERE
float[] array = {-50.0f, -50.0f,
-50.0f, 50.0f,
50.0f, -50.0f,
50.0f, 50.0f};
vertexBuffer = BufferUtils.newFloatBuffer(8);
vertexBuffer.put(array);
vertexBuffer.rewind();
position_x = 300;
position_y = 300;
screenWidth = Gdx.graphics.getWidth();
screenHeight = Gdx.graphics.getHeight();
size_rect = size_rect / 2;
}
private void update()
{
if(Gdx.input.justTouched())
{
position_x = Gdx.input.getX();
position_y = screenHeight - Gdx.input.getY();
vertexBuffer.put(0, position_x - size_rect);
vertexBuffer.put(1, position_y - size_rect);
vertexBuffer.put(2, position_x - size_rect);
vertexBuffer.put(3, position_y + size_rect);
vertexBuffer.put(4, position_x + size_rect);
vertexBuffer.put(5, position_y - size_rect);
vertexBuffer.put(6, position_x + size_rect);
vertexBuffer.put(7, position_y + size_rect);
}
Gdx.gl.glVertexAttribPointer(positionLoc, 2, GL20.GL_FLOAT, false, 0, vertexBuffer);
Gdx.gl.glDrawArrays(GL20.GL_TRIANGLE_STRIP, 0, 4);
}
#Override
public void render () {
Gdx.gl.glClearColor( 0.7f, 1f, 1f, 1f );
Gdx.gl.glClear( GL20.GL_COLOR_BUFFER_BIT );
update();
}
}
Unfortunately I have no idea how to "save" the rectangles (or the coordinates) dynamically..
Does someone have a good tip for me or a short code example of how you can do that?

Simply have a variable that stores the start index of the latest rectangle vertex and another variable to hold number of rectangles.
private int m_numRectangles;
private int m_nextRectIndex;
//initialize both above variables to 0
//...
if(Gdx.input.justTouched())
{
m_nextRectIndex = m_numRectangles * 8;
m_numRectangles++;
//save a copy of the old rectangles
vertexBuffer.rewind();
Float[] oldRects = new Float[ vertexBuffer.remaining() ];
vertexBuffer.get(oldRects);
//allocate more memory for old + one more rectangle
vertexBuffer = BufferUtils.newFloatBuffer( m_numRectangles * 8 );
//copy back the old rectangles
vertexBuffer.put( oldbuffer );
vectexBuffer.rewind();
position_x = Gdx.input.getX();
position_y = screenHeight - Gdx.input.getY();
vertexBuffer.put(m_nextRectIndex + 0, position_x - size_rect);
vertexBuffer.put(m_nextRectIndex + 1, position_y - size_rect);
vertexBuffer.put(m_nextRectIndex + 2, position_x - size_rect);
vertexBuffer.put(m_nextRectIndex + 3, position_y + size_rect);
vertexBuffer.put(m_nextRectIndex + 4, position_x + size_rect);
vertexBuffer.put(m_nextRectIndex + 5, position_y - size_rect);
vertexBuffer.put(m_nextRectIndex + 6, position_x + size_rect);
vertexBuffer.put(m_nextRectIndex + 7, position_y + size_rect);
}
Gdx.gl.glVertexAttribPointer(positionLoc, 2, GL20.GL_FLOAT, false, 0, vertexBuffer);
for( int i=0; i<m_numRectangles * 4; i+=4 )
{
Gdx.gl.glDrawArrays(GL20.GL_TRIANGLE_STRIP, i, 4);
}

Related

Java tile map using Libgdx: finding tile at mouse position

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.

terrain collision system returning small height values

I'm trying to make a simple terrain collision system for my game, but
it's just returning small values ranging from 0.3 - 1, nothing higher or lower, and my character just stays at the same height.
I've been trying to fix this for hours, but I haven't found the solution yet.
Here is the code for collisions:
package terrain;
public float getHeightOfTerrain(float worldx,float worldz)
{
float terrainX = worldx - this.x;
float terrainZ = worldz - this.z;
float gridSquareSize = size - (float)(heights.length -1f);
int gridx = (int)Math.floor(terrainX/gridSquareSize);
int gridz = (int)Math.floor(terrainZ/gridSquareSize);
if(gridx >= heights.length - 1 || gridz >= heights.length -1 || gridx<0||gridz<0)
{
return 0;
}
float xCoord = (terrainX % gridSquareSize)/gridSquareSize;
float zCoord = (terrainZ % gridSquareSize)/gridSquareSize;
float answer;
if (xCoord <= (1-zCoord))
{
answer = Mathc
.barryCentric(new Vector3f(0, heights[gridx][gridz], 0), new Vector3f(1,
heights[gridx + 1][gridz], 0), new Vector3f(0,
heights[gridx][gridz + 1], 1), new Vector2f(xCoord, zCoord));
} else
{
answer = Mathc
.barryCentric(new Vector3f(1, heights[gridx + 1][gridz], 0), new Vector3f(1,
heights[gridx + 1][gridz + 1], 1), new Vector3f(0,
heights[gridx][gridz + 1], 1), new Vector2f(xCoord, zCoord));
}
return answer;
}
private RawModel generateTerrain(Loader loader,String heightMap)
{
BufferedImage image = null;
try
{
image = ImageIO.read(new File("res/"+heightMap+".png"));
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
int vertex_count = image.getHeight();
heights = new float[vertex_count][vertex_count];
int count = vertex_count * vertex_count;
float[] vertices = new float[count * 3];
float[] normals = new float[count * 3];
float[] textureCoords = new float[count*2];
int[] indices = new int[6*(vertex_count-1)*(vertex_count-1)];
int vertexPointer = 0;
for(int i=0;i<vertex_count;i++){
for(int j=0;j<vertex_count;j++){
vertices[vertexPointer*3] = (float)j/((float)vertex_count - 1) * size;
float height = getheight(j,i,image);
heights[j][i] = height;
vertices[vertexPointer*3+1] = height;
vertices[vertexPointer*3+2] = (float)i/((float)vertex_count - 1) * size;
Vector3f normal = calculateNormal(j,i,image);
normals[vertexPointer*3] = normal.x;
normals[vertexPointer*3+1] = normal.y;
normals[vertexPointer*3+2] = normal.z;
textureCoords[vertexPointer*2] = (float)j/((float)vertex_count - 1);
textureCoords[vertexPointer*2+1] = (float)i/((float)vertex_count - 1);
vertexPointer++;
}
}
int pointer = 0;
for(int gz=0;gz<vertex_count-1;gz++){
for(int gx=0;gx<vertex_count-1;gx++){
int topLeft = (gz*vertex_count)+gx;
int topRight = topLeft + 1;
int bottomLeft = ((gz+1)*vertex_count)+gx;
int bottomRight = bottomLeft + 1;
indices[pointer++] = topLeft;
indices[pointer++] = bottomLeft;
indices[pointer++] = topRight;
indices[pointer++] = topRight;
indices[pointer++] = bottomLeft;
indices[pointer++] = bottomRight;
}
}
return loader.loadToVAO(vertices, textureCoords, normals, indices);
}
private float getheight(int x,int z,BufferedImage image)
{
if(x<=0 || x>= image.getHeight()||z<=0||z>=image.getHeight())
{
return 0;
}
float height = image.getRGB(x,z);
height += maxPixelColor/2f;
height /= maxPixelColor/2f;
height *= maxHeight;
return height;
}
}

Camera rotation bug

this uses the lwjgl library.
in this 3D engine, I created a camera, it moves around fine, but the rotation is really bad. First off, left and right move diagonally down left or right, and up and down make the object stretch.
all of my rotation code to do with the camera:
public Vector3f rotate(float angle, Vector3f axis)
{
float sinHalfAngle = (float)Math.sin(Math.toRadians(angle / 2));
float cosHalfAngle = (float)Math.cos(Math.toRadians(angle / 2));
float rX = axis.getX() * sinHalfAngle;
float rY = axis.getY() * sinHalfAngle;
float rZ = axis.getZ() * sinHalfAngle;
float rW = cosHalfAngle;
Quaternion rotation = new Quaternion(rX, rY, rZ, rW);
Quaternion conjugate = rotation.conjugate();
Quaternion w = rotation.mul(this).mul(conjugate);
x = w.getX();
y = w.getY();
z = w.getZ();
return this;
}
can't remember if this has to do with rotation, but it's for the camera
public Matrix4f ititProjection(float fov, float width, float height, float zNear, float zFar)
{
float ar = width/height;
float tanHalfFOV = (float)Math.tan(Math.toRadians(fov / 2));
float zRange = zNear - zFar;
m[0][0] = 1.0f / (tanHalfFOV * ar); m[0][1] = 0; m[0][2] = 0; m[0][3] = 0;
m[1][0] = 0; m[1][1] = 1.0f / tanHalfFOV; m[1][2] = 0; m[1][3] = 0;
m[2][0] = 0; m[2][1] = 0; m[2][2] = (-zNear - zFar)/zRange; m[2][3] = 2 * zFar * zNear / zRange;
m[3][0] = 0; m[3][1] = 0; m[3][2] = 1; m[3][3] = 0;
return this;
}
public Matrix4f initCamera(Vector3f forward, Vector3f up)
{
Vector3f f = forward;
f.normalize();
Vector3f r = up;
r.normalize();
r = r.cross(f);
Vector3f u = f.cross(r);
m[0][0] = r.getX(); m[0][1] = r.getY(); m[0][2] = r.getZ(); m[0][3] = 0;
m[1][0] = u.getX(); m[1][1] = u.getY(); m[1][2] = r.getZ(); m[1][3] = 0;
m[2][0] = f.getX(); m[2][1] = f.getY(); m[2][2] = f.getZ(); m[2][3] = 0;
m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
return this;
}

Android Open GL ES z-buffer not working on GL_POINTS(?)

I'm beginning to think the z-buffer in GL ES (Android) doesn't work on GL_POINTS(?) but I cant find anything in the docs.
Im looking to make a cube primative out of points and render them to a scene using the Z buffer - I have a similar class (Triangle) which renders and does use the z-buffer?
PS: I know my code is messy (I'm getting annoyed with this) I've had a bit of a tidy to post this.
Code listed bellow:
class MyGLRenderer implements GLSurfaceView.Renderer {
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"uniform float vSpatical;" +
"uniform vec3 vCamPos;" +
"float vDistance;" +
"float vDisX;" +
"float vDisY;" +
"float vDisZ;" +
"float vA;" +
"void main() {" +
" gl_Position = vPosition * uMVPMatrix;" +
" vDisX = vCamPos.x-vPosition.x;" +
" vDisY = vCamPos.y-vPosition.y;" +
" vDisZ = vCamPos.z-vPosition.z;" +
" vA = 3.14159265359 * (vSpatical*vSpatical);" +
" vDistance = sqrt((vDisX*vDisX) + (vDisY*vDisY) + (vDisZ*vDisZ));" +
" gl_PointSize = 1.0 * vA / (vDistance*vDistance);" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
float[] mCamPos = {0f, 0f, 6f};
Triangle mTriangle;
Cube mCube;
int mProgram;
float mAngle = 0;
#Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glLinkProgram(mProgram);
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
mTriangle = new Triangle();
mCube = new Cube();
GLES20.glClearColor(0.0f, 0.4f, 0.4f, 1.0f);
GLES20.glClearDepthf(1.0f);
GLES20.glEnable(GL10.GL_DEPTH_TEST);
GLES20.glDepthFunc(GL10.GL_LEQUAL);
GLES20.glDepthMask(true);
GLES20.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
GLES10.glShadeModel(GL10.GL_SMOOTH);
}
#Override
public void onDrawFrame(GL10 unused) {
float[] scratch = new float[16];
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.setLookAtM(mViewMatrix, 0, mCamPos[0], mCamPos[1], mCamPos[2], 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0f, 1.0f, 1.0f);
mAngle += 0.09f;
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
mTriangle.draw(mProgram, scratch);
mCube.draw(mProgram, scratch, mCamPos);
}
#Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
public static int loadShader(int type, String shaderCode){
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
}
class Cube {
private final FloatBuffer vertexBuffer, vBuff2, vBuff3;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
private int vertexCount;
private final int vertexStride = COORDS_PER_VERTEX * 4;
private float mSpaticalExtent[];
static final int COORDS_PER_VERTEX = 3;
static float triangleCoords[];
static float sides[];
static float topbottom[];
float color[] = { 0.93671875f, 0.46953125f, 0.22265625f, 1.0f };
float color2[] = { 0.43671875f, 0.96953125f, 0.22265625f, 1.0f };
float color3[] = { 0.33671875f, 0.46953125f, 0.82265625f, 1.0f };
public Cube() {
MakeCube(0, 0, 0, 10);
ByteBuffer bb = ByteBuffer.allocateDirect(
triangleCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(triangleCoords);
vertexBuffer.position(0);
ByteBuffer bb2 = ByteBuffer.allocateDirect(
sides.length * 4);
bb2.order(ByteOrder.nativeOrder());
vBuff2 = bb2.asFloatBuffer();
vBuff2.put(sides);
vBuff2.position(0);
ByteBuffer bb3 = ByteBuffer.allocateDirect(
topbottom.length * 4);
bb3.order(ByteOrder.nativeOrder());
vBuff3 = bb3.asFloatBuffer();
vBuff3.put(topbottom);
vBuff3.position(0);
}
private void MakeCube(float x, float y, float z, float width) {
triangleCoords = new float[(int)width*(int)width*6]; // Width * Width * 6 Points * 3 Float per point
sides = new float[(int)width*(int)width*6];
topbottom = new float[(int)width*(int)width*6];
vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
mSpaticalExtent = new float[1];
mSpaticalExtent[0] = width;
x -= width/2f;
y -= width/2f;
z -= width/2f;
int currentArrayPoint = 0;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < width; j++)
{
// FRONT AND BACK WALLS- X AND Y CHANGE Z DOESN'T
//
triangleCoords[currentArrayPoint++] = (x + j) / width;
triangleCoords[currentArrayPoint++] = (y + i) / width;
triangleCoords[currentArrayPoint++] = z / width;
//
triangleCoords[currentArrayPoint++] = (x + j) / width;
triangleCoords[currentArrayPoint++] = (y + i) / width;
triangleCoords[currentArrayPoint++] = (z + width) / width;
}
}
currentArrayPoint = 0;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < width; j++)
{
// SIDE WALLS, Y AND Z CHANGE X DOESN'T
//
sides[currentArrayPoint++] = x / width;
sides[currentArrayPoint++] = (y + i) / width;
sides[currentArrayPoint++] = (z + j) / width;
//
sides[currentArrayPoint++] = (x + width) / width;
sides[currentArrayPoint++] = (y + i) / width;
sides[currentArrayPoint++] = (z + j) / width;
}
}
currentArrayPoint = 0;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < width; j++)
{
// TOP AND BOTTOM WALLS, X AND Z CHANGE Y DOESN'T
//
topbottom[currentArrayPoint++] = (z + j) / width;
topbottom[currentArrayPoint++] = (y) / width;
topbottom[currentArrayPoint++] = (x + i) / width;
//
topbottom[currentArrayPoint++] = (z + j) / width;
topbottom[currentArrayPoint++] = (y + width) / width;
topbottom[currentArrayPoint++] = (x + i) / width;
}
}
}
public void draw(int mProgram, float[] mvpMatrix, float[] mCamPos) {
GLES20.glUseProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
int mCamHandle = GLES20.glGetUniformLocation(mProgram, "vCamPos");
GLES20.glUniform3fv(mCamHandle, 1, mCamPos, 0);
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
int mSpaticalHandle = GLES20.glGetUniformLocation(mProgram, "vSpatical");
GLES20.glUniform1fv(mSpaticalHandle, 1, mSpaticalExtent, 0);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, vertexCount);
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vBuff2);
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
GLES20.glUniform4fv(mColorHandle, 1, color2, 0);
mSpaticalHandle = GLES20.glGetUniformLocation(mProgram, "vSpatical");
GLES20.glUniform1fv(mSpaticalHandle, 1, mSpaticalExtent, 0);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, vertexCount);
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vBuff3);
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
GLES20.glUniform4fv(mColorHandle, 1, color3, 0);
mSpaticalHandle = GLES20.glGetUniformLocation(mProgram, "vSpatical");
GLES20.glUniform1fv(mSpaticalHandle, 1, mSpaticalExtent, 0);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, vertexCount);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
After looking at your shaders, I noticed the following:
gl_Position = vPosition * uMVPMatrix; // D3D convention
This is completely wrong for OpenGL (which uses column-major matrices and post-multiplication).
It should be:
gl_Position = uMVPMatrix * vPosition; // OpenGL convention
I checked the code you use to send your MVP matrix, and it does not transpose the matrix, so your shader is what is backwards.
You could also solve this by setting the transpose parameter in GLES20.glUniformMatrix4fv to true, but it is best to stick with traditional OpenGL convention and use column-major matrices. It is much easier to diagnose these sorts of things if you do.

Getting lines from GL10 drawing images next to one another, solution?

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);

Categories

Resources