getWorldCoordinates - what it does exactly?

Hello everyone,



So I needed for my character to face the mouse all the time, and I found

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:mouse_picking?s[]=getworldcoordinates

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:beginner:hello_picking?s[]=getworldcoordinates

where it shows how to convert mouse coordinates to world coordinates. But it does only that, it shows the code, doesn’t explain it and I want to understand what am I doing exactly…



so could anyone explain the method (link)

[java]

Vector3f getWorldCoordinates(Vector2f screenPosition, float zPos)

[/java]



I’ve take a look at the source code but right now I’m not that comfortable with projections to understand it without spending the whole day/week of research.



The method call with zPos zero returns x [-0.71 … 0.71] and y [-0.41 … 0.41] … depending on resolution. What is it?

What point in 3d space is it? Right in front of the camera as in on the near plane? First I though it will give me 3d point as if you were projecting from screen into plane at “zPos”, but that’s not the case.



Tnx… I hope the method will get documented as well.

Pretty sure zPos is relative to the near and far clipping planes. So zPos = 0 is on the near clip and zPos = 1 is the far clip.



I’m not sure. You may want to explain more about what you are trying to do because getWorldCoordinates() sounds like it might be the wrong approach.

oh 0 and 1 … that makes sense. I’ve tried in units, as if location units only.



I solved my problem, it works with the source code in the tutorials. I just want to know what it does, I want to understand it.



My game is tow-down, camera looking at XY plane. I needed to rotate player towards the mouse, it works like this:



[java] Vector2f mousePositionScreen = inputManager.getCursorPosition();

Vector3f mousePosition3d = cam.getWorldCoordinates(mousePositionScreen, 0).clone();

Vector3f dir = cam.getWorldCoordinates(mousePositionScreen, 1f).subtractLocal(mousePosition3d).normalizeLocal();

Ray ray = new Ray(mousePosition3d, dir);

Plane plane = new Plane(Vector3f.UNIT_Z, 0);

Vector3f mousePositionWorld = new Vector3f();

ray.intersectsWherePlane(plane, mousePositionWorld);

mousePositionWorld.z = 0;



Quaternion rotation = new Quaternion();

rotation.lookAt(mousePositionWorld.subtract(soldier.getLocalTranslation()), Vector3f.UNIT_Z);

soldier.setLocalRotation(rotation);

[/java]



I though I don’t need “dir” vector as I know direction is (0, 0, -1), but it doesn’t work with it.

If it’s top down then is the soldier only looking in x,y or does z matter for the solider look?



If z doesn’t matter then you could calculate a new direction just in screen space and not bother with all of that other stuff. Get the screen position of the soldier, subtract that from the mouse cursor position, normalize it… and you have a direction vector.

Vecto2f dir = cursorPosition.subtract( soldierScreenPos );



Pretty easy to get the right rotation from that.

1 Like
@pspeed said:
Get the screen position of the soldier, subtract that from the mouse cursor position, normalize it... and you have a direction vector.


Yes, z dimension doesn't matter.
How do I get screen position from world position? I'll go look for it now...

Edit:
well it's obviusly Camera.getScreenPosition() ... :)
So that will work thank you, I could either convert screen position of mouse to world position or the other way.

Still I'm gonna need convert screen position to world position sooner or later and my main question is still ... what getWorldCoordinates() does exactly? I think I should have asked this in documentation section.

http://hub.jmonkeyengine.org/javadoc/com/jme3/renderer/Camera.html#getScreenCoordinates(com.jme3.math.Vector3f)

@Kova said:
Still I'm gonna need convert screen position to world position sooner or later and my main question is still ... what getWorldCoordinates() does exactly? I think I should have asked this in documentation section.


It basically projects a ray out from the camera, piercing the screen coordinate and stopping at zPos... which is relative to near/far clip as mentioned.

The thing is, beyond the picking example, this function is almost never the right way to go. So, on the one hand, better documentation would be nice, but on the other, in this case it means we would have had several days more misused concepts to roll back to get you back to something usable. :) Presuming you worked the math to get the info you wanted.

Still curious when you'd need to convert screen position to world coordinates other than constructing a ray (zPos=0 to zPos=1) for picking...
1 Like

You should just be able to use the intersection point of the ray with the plane. That will be a 3d co-ordinate in world space that you can then look the guy towards.



I notice you are creating a new Plane every time (among other stuff) for better performance you should try to re-use objects.

@zarch said:
I notice you are creating a new Plane every time (among other stuff) for better performance you should try to re-use objects.

If you're not on android (and I hope it gets better there too) then creating objects in situations that would be like the stack in C isn't really expensive, they get cleaned quickly and efficiently. So while there might be a bit of performance to gain there I think these kinds of optimizations should be done fairly late when all code works properly. Compared to the picking itself creating the plane is completely dwarfed for example. Not trying to smartass here just trying to give you some freedom from the "hunt for object reuse" ;)
@pspeed said:
It basically projects a ray out from the camera, piercing the screen coordinate and stopping at zPos... which is relative to near/far clip as mentioned.


Yes this is correct! :) Thank you... just tested it.

@pspeed said:
The thing is, beyond the picking example, this function is almost never the right way to go.
Still curious when you'd need to convert screen position to world coordinates other than constructing a ray (zPos=0 to zPos=1) for picking...


What do you mean "never the right way to go"? It does just what it's meant for.. to transform mouse position to 3d world position. I don't know either how it could be used in another context.

@zarch
yes the whole thing works... I wouldn't even need that manual raycasting if I stick to mouse > world coords, I could just use Camera.getWorldCoordinates(mousePos, 1) as the plane the gameplay is on is camera far plane. Also I'm not too worried now about performance, just want to learn the basics and eventually rewrite my 2d game (slick2d engine) to JME.

Thaks guys.
@Kova said:
What do you mean "never the right way to go"? It does just what it's meant for.. to transform mouse position to 3d world position. I don't know either how it could be used in another context.


I said "almost never the right way to go". Meaning that if someone is using it for something other than creating a ray for picking then there is almost always a better way to do whatever it is they are really trying to do. Almost always... not always.