58

LibGDX has a coordinate system where (0,0) is at the bottom-left. (like this image: http://i.stack.imgur.com/jVrJ0.png)

This has me beating my head against a wall, mainly because I'm porting a game I had already made with the usual coordinate system (where 0,0 is in the Top Left Corner).

My question: Is there any simple way of changing this coordinate system?

chown
  • 48,838
  • 16
  • 128
  • 167
Sosavpm
  • 683
  • 1
  • 5
  • 6
  • sure, that's kind of what I'm doing right now. But is there any way to flip the coordinate system. Something like creating a projection matrix with the coordinate system that I want. Or telling the Spritebatch to draw according to a certain coordinate system... I've been looking like crazy, but I can't seem to find anything in particular... (and if so, whats the actual code) – Sosavpm Oct 10 '11 at 04:01
  • 2
    This is indeed a nightmare. Things like SpriteBatch and sprites go from bottomleft. Things like input and textureregion go from top left. Resulting in super awkward coding and turning around things in your mind so often your eyes start to pop out. Anyway, i recommend getting used to it, turning around the camera results in flipped images and then you need to flip everything back, but not everything just most of the things and having them draw expectedly unexpectedly. LibGDX is awesome, but the coordinate system has serious issues. Better get used to it. – Madmenyo Aug 24 '14 at 13:55

6 Answers6

124

If you use a Camera (which you should) changing the coordinate system is pretty simple:

camera= new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

If you use TextureRegions and/or a TextureAtlas, all you need to do in addition to that is call region.flip(false, true).

The reasons we use y-up by default (which you can easily change as illustrated above) are as follows:

  • your simulation code will most likely use a standard euclidian coordinate system with y-up
  • if you go 3D you have y-up
  • The default coordinate system is a right handed one in OpenGL, with y-up. You can of course easily change that with some matrix magic.

The only two places in libgdx where we use y-down are:

  • Pixmap coordinates (top upper left origin, y-down)
  • Touch event coordinates which are given in window coordinates (top upper left origin, y-down)

Again, you can easily change the used coordinate system to whatever you want using either Camera or a tiny bit of matrix math.

badlogic
  • 3,009
  • 1
  • 19
  • 12
  • 19
    An answer from the creator itself. Thanks very useful! – Sosavpm Oct 22 '11 at 16:20
  • 3
    @badlogic you specified that he should use the camera, but which would be the downfall of using just SpriteBatch.draw method and handle the world scrolling and frustum culling myself? I'm developing a top down strategy game. – Pasman Dec 11 '11 at 15:56
  • 2
    I assume there is some reason it was developed the way it is, but what if you're not using any Camera at all and are just drawing Textures/Pixmaps/Fonts/etc using SpriteBatch.draw()? I have Pasman's exact issue. –  Mar 08 '13 at 09:49
  • @Pasman I think you will have to deal directly with OpenGL to set your custom matrix using the `Gdx.gl.glXXX()` functions especially `glLoadMatrixf()` and `glMatrixMode()`. – flawyte May 05 '13 at 09:12
  • 3
    @Pasman, you can use batch.getProjectionMatrix().setToOrtho2D(). – NateS Nov 26 '13 at 16:37
  • Now, probably obvious, my texture is displayed upside down. Is there some other variable i can set to fix this for all textures and possibly fonts? – Madmenyo Jul 17 '14 at 17:05
  • 3
    Everything is upside down! I can flip regions but not texture. – Ali Aug 13 '14 at 18:07
  • Can you guys please update this answer for the current API? OrthographicCamera doesn't have a setToOrtho method anymore. – user3690202 Oct 04 '15 at 00:05
  • @user3690202 Are you sure you're using the right class? I just installed libGDX from the setup jar and I'm using it now exactly how it is shown above. – User Oct 04 '15 at 18:03
9

Just to expand a little on what badlogic said above, if you are using a TextureAtlas (with TextureRegions) you need to flip them, as badlogic said, in addition to the camera work. If you are using a TextureAtlas, you can use this code right after loading your atlas:

String textureFile = "data/textures.txt";  
atlas = new TextureAtlas(Gdx.files.internal(textureFile), Gdx.files.internal("data"));  
// Let's flip all the regions.  Required for y=0 is TOP
Array<AtlasRegion> tr = atlas.getRegions();      
for (int i = 0; i < tr.size; i++) {
  TextureRegion t = tr.get(i);
  t.flip(false, true);
}
gvlasov
  • 14,781
  • 17
  • 61
  • 99
Richard
  • 1,452
  • 16
  • 22
6

If you want to hide the transformation and not think about it after setting it up once, you can make a class that inherits all of the functionalities you need, but first transforms the coordinates before passing it to its parent class's function. Unfortunately, this would take a lot of time.

You could alternatively make a method that does the simple y' = height - y transformation on the whole Coordinate object (or whatever it is you're using), and call it once before each operation.

  • Well, It's not exactly what I wanted. But I did this and it worked fine, And it wasn't much coding either.(Besides, I kept on looking and I think there is no other way) Thanks! – Sosavpm Oct 10 '11 at 22:08
  • Not sure if you meant this, but I don't think a "god" class which does all that is a very good idea, so I'm trying to extend all the classes I need and override the methods as needed. Not a pretty solution either. – User Oct 04 '15 at 06:02
  • Meh, actually I think I'm going to try using that OrthographicCamera class workaround and see how that goes. – User Oct 04 '15 at 06:35
5

Interesting graphics library, I would say. I found this assessment from the link below:

Another issue was that different coordinate systems were used in different parts of Libgdx. Sometimes the origin of the axes was in the bottom left corner with the y-axis pointing upwards and sometimes in the top left corner of the sprite pointing downwards. When drawing Meshes the origin was even in the center of the screen. This caused quite a bit of confusion and extra work to get everything in the correct place on the screen.

http://www.csc.kth.se/utbildning/kandidatexjobb/datateknik/2011/rapport/ahmed_rakiv_OCH_aule_jonas_K11072.pdf

ee.
  • 897
  • 4
  • 5
  • 1
    It's actually a very powerful library for game dev in Android. The only wierd thing is the coordinate handling, as the assesment points out. – Sosavpm Oct 10 '11 at 22:10
  • 1
    So, if you know your way around Camera or Matrices you can have whatever coordinate system you want really. :) – badlogic Oct 13 '11 at 08:04
  • 3
    But if you're not using a Camera, it seems you're out of luck and need to wrap the API in a facade to change this. Arrrgh..why use anything other than the absurdly common standard top-left coordinate system? WHYYYYYYYYYYYYYYY? :( –  Mar 08 '13 at 09:43
  • 2
    @Perce, because math. – NateS Nov 26 '13 at 16:37
  • Heh. So the other 9,999 libraries out there which use a top-left coordinate system didn't utilize math. Interesting. :p – User Oct 04 '15 at 05:29
1

I just made a class that extends SpriteBatch that overides certain methods adding y = Gdx.graphics.getHeight() - y - height. Simple but effective.

Ajay
  • 417
  • 6
  • 19
0

I was able to get textures and fonts rendering correctly using the suggested flipped coordinate system via OrthographicCamera. Here's what I did:

private SpriteBatch batch;
private BitmapFont font;
private OrthographicCamera cam;
private Texture tex;

@Override
public void create () {
    batch = new SpriteBatch();
    
    font = new BitmapFont(true);
    font.setColor(Color.WHITE);
    
    cam = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    cam.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    tex = new Texture("badlogic.jpg");
}

@Override
public void dispose() {
    batch.dispose();
    font.dispose();
    tex.dispose();
}

@Override
public void render () {
    cam.update();
    batch.setProjectionMatrix(cam.combined);
    
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    batch.begin();
    
    font.draw(batch, "Test", 50, 50);
    batch.draw(tex, 100, 100, tex.getWidth(), tex.getHeight(), 0, 0, tex.getWidth(), tex.getHeight(), false, true);
    
    batch.end();
}

Important things to notice are:

  • The BitmapFont constructor, the boolean flips the font
  • For batch.draw() you need to use all those parameters because you need a boolean flipY at the end to flip the texture (I may extend SpriteBatch or make a utility method to avoid passing so many parameters all the time.)
  • Notice batch.setProjectionMatrix(cam.combined); in render()

Now we will see if I am back here later tonight doing edits to fix any other issues or discoveries with doing all this.

Willi Mentzel
  • 21,499
  • 16
  • 88
  • 101
User
  • 293
  • 3
  • 17