[Libgdx] Screen coordinates -> Isometric world coordinates

I made this little thingy, which display kinda isometric floor. Here is how it looks without rotating the matrices.

As expected, finding on which tile mouse is currently at is really easy. Just divide mouse coordinates by tile size…

Here is the image of how it looks when I do my ‘isometric’ rotations (not sure if this is called isometric :D)

Here is the code for making this ‘isometric’ ground.


Matrix4 projectionMatrix = new Matrix4();
		projectionMatrix.setToOrtho(0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), 0, -1, 1);
		
		Matrix4 modelviewMatrix = new Matrix4();
		modelviewMatrix.rotate(1, 0, 0, 35);
		modelviewMatrix.rotate(0, 0, 1, 45);

		projectionMatrix.tra();
		modelviewMatrix.tra();
		
		isoShader.setUniformMatrix(isoShader.getUniformLocation("u_projectionMatrix"), projectionMatrix, false);
		isoShader.setUniformMatrix(isoShader.getUniformLocation("u_modelViewMatrix"), modelviewMatrix, false);

How do I transform screen mouse coordinates to these world coordinates?


		float x = Gdx.input.getX();
		float y = Gdx.input.getY();
		float[] vec = { x, y, 0 };

		Matrix4 transformationMatrix = projectionMatrix.cpy();
		transformationMatrix.mul(modelviewMatrix);

		Matrix4.mulVec(transformationMatrix.val, vec);

		System.out.println(vec[0] + "  " + vec[1]);

I tried this code, and in my head, it should work. But it gives not correct values… As I point along the horizontal axis of the map, the Y is increasing…

Can somebody give me a medal? I managed to come up with a question that no one on this forum can answer :smiley:

Since the projection matrix takes screen coordinates to world coordinates, you need the inverse of the projection matrix to invert the process.

More info here: http://webglfactory.blogspot.com/2011/05/how-to-convert-world-to-screen.html

I’m just a noobie to matrices, but this is the only information I found a long time ago on isometric mouse coordinates;

Also, if you just need to know which of the tiles, and perhaps which of the objects, has been touched you can do something like give each tile a bounding box and check which the screen ray passes through first. You can also give your entities their own bounding boxes for this. There are many optimizations, such as if you know which tiles are being shown (Such as if you track which of your tiles are being culled during projection).

What you get? If you rotate your screen you use the same method of checking. If you make it a 2.5d game where there is a Z component for objects (Such as hills) you will get the ‘higher’ tiles if you click on them rather than the tiles behind them.


public Tile getTileTouched(float screenX, float screenY) {
	Ray pickRay = camera.getPickRay(screenX, screenY);
	
	Vector3 intersection = new Vector3();
	Tile closestTile = null;
	boolean distance = Float.MAX_NUMBER;
	for(int i = 0; i < tiles.size; i++) {
		if(Intersector.intersectRayBounds(pickRay, tile.get(i).boundingBox, intersection)) {
			if(intersection.dst2(ray.origin) < distance) {
				distance = intersection.dst2(ray.origin);
				closestTile = tile.get(i);
			}
		}
	}
	return closestTile;
}

This thread may also help…

Edit: thanks matheus23, silly tablet auto correct…

FTFY :slight_smile: