'World to screen coordinates in LibGDX

I am trying to present a map on the screen and place pins on the map at certain coordinates that are predefined. currently the issue is when the screen size changes say from device to device or when running on a desktop when the window size changes the position of all the pins moves when the map is scaled to fit the screen. I'm sure there is an obvious was to make the positions dependent on the map size or something. Could someone point me in the right direction in terms of making the objects appear in the same locations when the screen scales?



Solution 1:[1]

You need to unproject your coordinates with your camera.

Let's say that your coordinates that you want to transform to 'screen' coordinates are called screenX and screenY.

Vector3 vec=new Vector3(screenX,screenY,0);
camera.unproject(vec);

Now you can use your vec.x and vec.y values.

Solution 2:[2]

This is how you do it correctly

    public static Vector3 MultiplyPoint(Matrix4 m, Vector3 point)
{
    Vector3 result = new Vector3(0, 0, 0);
    result.x = m.val[Matrix4.M00] * point.x + m.val[Matrix4.M01] * point.y +  m.val[Matrix4.M02]* point.z +  m.val[Matrix4.M03];
    result.y = m.val[Matrix4.M10] * point.x + m.val[Matrix4.M11] * point.y + m.val[Matrix4.M12] * point.z + m.val[Matrix4.M13];
    result.z = m.val[Matrix4.M20] * point.x + m.val[Matrix4.M21] * point.y + m.val[Matrix4.M22] * point.z + m.val[Matrix4.M23];
    float num = m.val[Matrix4.M30] * point.x + m.val[Matrix4.M31] * point.y + m.val[Matrix4.M32] * point.z + m.val[Matrix4.M33];
    num = 1f / num;
    result.x *= num;
    result.y *= num;
    result.z *= num;
    return result;
}

public static Vector2 WorldToScreenPoint(float x, float y)
{
    Matrix4 V = Constants.Camera.view;
    Matrix4 P = Constants.Camera.projection;
    
    Matrix4 MVP = P.mul(V); // Skipping M, point in world coordinates
    Vector3 screenPos = MultiplyPoint(MVP, new Vector3(x, y, 0));
    
    Vector3 screenPoint = new Vector3(screenPos.x + 1f, screenPos.y + 1f, screenPos.z + 1f).scl(0.5f); // returns x, y in [0, 1] internal. 
    
    return new Vector2(screenPoint.x * Constants.GlobalWidth, screenPoint.y * Constants.GlobalHeight); // multiply by viewport width and height to get the actual screen coordinates.
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Boldijar Paul
Solution 2 GabeTheApe