Camera.getWorldPosition(Vector2f screenPos, float zPos) ... what does it do?

The example apps show screen picking Looking into it, I see that Camera.getWorldPosition() is wholly undocumented with two variants referring the reader to the other one.



The example code shows it being used with the screenPos being InputManager.getCursorPosition() – which returns 0,0 for me no matter where the cursor is, so I get mouse picking working by using getX() and getY() from a MouseButtonEvent when the user clicks on the mouse, but even here things are screwy… I need to use Vector2f(mbe.getX(), app.getHeight() - mbe.getY()) to get picking to work correctly, ala this working code:



Vector2f cursorPos = new Vector2f(mbe.getX(), Sim.getHeight() - mbe.getY());

Vector3f rayOrigin = cam.getWorldCoordinates(cursorPos, 0f);

Vector3f dir = cam.getWorldCoordinates(cursorPos, 1f).subtractLocal(rayOrigin).normalizeLocal();



Ray ray = new Ray(rayOrigin, dir);

int num = Sim.get().getRootNode().collideWith(ray, results);



What is zPos doing here? Does it interpolate between near and far clip planes through values 0 and 1?



I’m going crazy with an app full of vectors which are negated from what they should be to make something work, and with cameras that are yawed 180 degrees so they actually face frontward.

Camera.getWorldPosition(Vector2f screenPos, float zPos) … what does it do?


It returns the camera world position xD. the screenPos param gives you the camera x,y position. The zPos gives you the z position towards the camera. Look at the "TestMousePick.java".

since the screen is a 2d surface you can never describe the depth of a point in the space that is “behind” that 2d surface, so you need to specify the z depth.

A little experimentation seems to show that zPos is actually as I was thinking it might be – it drives the depth from near to far clip plane as zPos varies from 0 to 1



I’d really like to help improve the Javadocs… I had trouble finding the contributor handbook due to web issue yesterday. I will look again.



tone

1 Like

The issue is that the Javadoc punts ont he opportunity to explain how zPos is interpreted, which has nearly infinite possibilities. It happens that the variable moves the depth between near and far clip planes as its value varies from 0 to 1.



The Javadoc right now for this says, entirely, as follows:



/**

  • @see Camera#getWorldCoordinates

    */

    public Vector3f getWorldCoordinates(Vector2f screenPos, float zPos) {

    return getWorldCoordinates(screenPos, zPos, null);

    }



    /**
  • @see Camera#getWorldCoordinates

    */

    public Vector3f getWorldCoordinates(Vector2f screenPosition,

    float zPos, Vector3f store) {

1 Like

hey dulcet tone!



I agree the function getWorldCoordinates() is confusing! I’ve read lots of posts saying that the argument zPos specifies the distance (depth) from the camera to the point of interest (along a line perpendicular to the screen plane). But I think you are right, it’s not a distance, its a function of the near and far clip planes.



To test this i added the following code:



System.out.println("Cam is at location: "+cam.getLocation());

System.out.println("Point 10 units away from the screen, in line with the centre of the screen is at: "+cam.getWorldCoordinates(new Vector2f(cam.getWidth()/2,cam.getHeight()/2), 10));

System.out.println(“Near clip plane is at:”+cam.getFrustumNear());

System.out.println("far clip plane is at: "+cam.getFrustumFar());



into the simpleupdateloop of a SimpleApplication. Expecting to see something like:



Cam is at location (50,15,50)

Point 10 units away from the screen in line with the centre of the screen is at (60,15,50)


> for facing the cam in the x-direction

but instead i got:

Cam is at location: (50.0, 15.0, 50.0)
Point 10 units away from the screen, in line with the centre of the screen is at: (49.030193, 14.935577, 49.728764)
Near clip plane is at:1.0
far clip plane is at: 1000.0

Do you have any idea how i could work out (possibly in terms of the near and far clip planes), how to find the worldCoordinates at a specified depth?

Thanks
Adam

found the answer on wikipedia…



private float convertZ(float zMeters){

float f = cam.getFrustumFar();

float n = cam.getFrustumNear();

return (f+ n)/(f-n) + ((-1fn)/(f-n))/zMeters;

}



if you use the output of the above function as the argument zPos in getWorldCoordinates(), then you should get the world coordinates one would expect.

I’m curious, why do you want to do that?

To translate between a screen coordinate and a world coordinate. The reason I need to do it is because I have a robot who has a depth-cam (Kinect), so each pixel in the depth image is the depth of that pixel from the robots sensor. So to translate those values into world space, you need the above function… right?

Yes, and no. There are other ways you can do it… they are all fraught with the same basic issues, though. You will have to match the eye-ball to screen view distance between the two images, ie: the distance between point of convergence and the artificial plane that the pixels are drawn on.



…but doing the way you are is probably the more straight forward of approaches. The other approach is to take two getWorldPositions() one at z = 0 and one at z = 1 and then turn that into a normalized direction vector… multiplying that vector by a distance from the camera location. It gets rid of any artificial “screen distance” but that may also be a bad thing.



All of that is really fuzzy in my brain since it’s been over 6 years since I played with depth images in this way… and given your use case, none of that may matter anyway.