3
\$\begingroup\$

I've been trying to get LibGDX's viewport and camera unproject() to work and so far none of the tutorials/answers I've found have worked for me. I have a game window of 840x480 units with FitViewport. If the screen resolution matches the aspect ratio of the viewport, the coordinates are unprojected correctly. If it doesn't and the viewport inserts black bars, the transformation is incorrect (see below):

The first screen shows the desired behavior, the second shows the current behavior, i.e. the cursor and the world coordinates are offset.

I'd like for the shape to be drawn where the cursor is, since the current behavior makes touch input on Android absolutely useless...

Furthermore, on Android the viewport doesn't fill the entire screen and just produces a rectangle on the bottom left quarter of my 1920x1080 px display.

Here's the code that produces this:

public class MainScreen extends ApplicationAdapter implements InputProcessor {
OrthographicCamera camera;
Viewport viewport;
Vector3 worldCoordinates = new Vector3();
Shape shape, background;
public ShapeRenderer sr;

@Override
public void create() {
    worldCoordinates = new Vector3();
    camera = new OrthographicCamera(800,480);
    camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
    viewport = new FitViewport(800, 480, camera);
    viewport.apply();
    sr = new ShapeRenderer();
    shape = new Shape(this, 20, 20, 0, 0);
    background = new Shape(this, 800, 480, 0, 0, Color.WHITE);
    Gdx.input.setInputProcessor(this);
}

@Override
public void resize(int width, int height) {
    viewport.update(width, height);
    camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
}

@Override
public void dispose() {

}

@Override
public void pause() {

}

@Override
public void resume() {

}

@Override
public void render() {
    camera.update();

    Gdx.gl.glClearColor(0, 0.1f, 0.1f, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    background.render();
    sr.setProjectionMatrix(camera.combined);

    shape.posX[0] = (int) worldCoordinates.x - shape.sizeX[0] / 2;
    shape.posY[0] = (int) worldCoordinates.y - shape.sizeY[0] / 2;

    shape.render();
}

@Override
public boolean mouseMoved(int screenX, int screenY) {
    worldCoordinates = camera.unproject(new Vector3(screenX, screenY, 0));
    return true;
}

@Override
public boolean keyDown(int keycode) {
    throw new UnsupportedOperationException("Not supported yet.");
}

@Override
public boolean keyUp(int keycode) {
    throw new UnsupportedOperationException("Not supported yet.");
}

@Override
public boolean keyTyped(char character) {
    throw new UnsupportedOperationException("Not supported yet.");
}

@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
    return true;
}

@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
    return true;
}

@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
    return false;
}

@Override
public boolean scrolled(int amount) {
    throw new UnsupportedOperationException("Not supported yet.");
}
}

And the Shape class:

public class Shape extends Element {
public Color background;
ShapeRenderer sr;
public Shape( MainScreen ms, int sizeX, int sizeY, int posX, int posY){
    super(sizeX, sizeY, posX, posY);
    sr=ms.sr;
    sr.setAutoShapeType(true);
    background = new Color();
    background.set(1, 0.533f, 0, 1);
}
public Shape(MainScreen ms, int sizeX, int sizeY, int posX, int posY, Color background){
    super(sizeX, sizeY, posX, posY);
    sr=ms.sr;
    sr.setAutoShapeType(true);
    this.background = background;
}

@Override
public void render(){       
    sr.begin(ShapeRenderer.ShapeType.Filled);
    sr.setColor(background);
    sr.rect(posX[0],posY[0],sizeX[0],sizeY[0]);
    sr.end();
}  
}

I have tried literally every option I could find without any result. Thank you for any help.

\$\endgroup\$
8
\$\begingroup\$

I hope I am understanding your question correctly -- if not let me know.

I believe the following is where you are unprojecting the coordinates:

@Override
public boolean mouseMoved(int screenX, int screenY) {
    worldCoordinates = camera.unproject(new Vector3(screenX, screenY, 0));
    return true;
}

Because you are using a viewport, you must add the viewport's x/y/width/height to unproject as well:

worldCoordinates = camera.unproject(new Vector3(screenX, screenY, 0), viewport.getScreenX(), viewport.getScreenY(), viewport.getScreenWidth(), viewport.getScreenHeight());

And this should hopefully cause a more correct calculation, I hope I was able to help!

\$\endgroup\$
  • \$\begingroup\$ And I've just solved the issue with fullscreen on Android as well (I didn't apply the correct projection matrix to ShapeRenderers). Thank you so much, you wouldn't believe how much time I've spent on this bloody thing... \$\endgroup\$ – LeonhardEuler Jul 23 '15 at 5:10
  • \$\begingroup\$ Wow! Thanks soooo much, I finally solved my problem :))) Upvote! \$\endgroup\$ – Eames Aug 16 '16 at 17:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.