Picking with an Absolute mouse

Hi there,



First of all, thanks for creating this awesome stuff, really helped alot.

I’ve build a small example based on the test package and reached some problems.



I. If I want to pick an object using an absolute mouse, how can I ever do this? Is there a simple method to calculate my mouse coordinates to world coordinates?



II. I want my text to hover on " top " of my scene object. Is there any way to translate the world coordinates to screen coordinates?



III. While testing my own pick-application I implemented the boundingbox ( basically a copy/paste from the test package.

However, after calling the method updateBoundVolume ( or something like that ) the coordinates do not change ( center x,y,z stay at 0 ). This is very weird, since I copied almost the whole example of picking.



Hope you can help me.



/edit I basically wanted to ask if there already was an easy way to switch from screen to world coordinates and back.



Thanks in advance.

Hi Marius.



Wow, believe it or not, I hadn’t begun worrying about that yet. Not sure why that didn’t cross my mind but it didn’t. There definately needs to be an easy way to calculate the world coordinate of a mouse cursor, and I will be sure to figure out something for you. In the meantime, you are going to have to calculate it yourself. Sorry about that.



Gregg, do you have any ideas about this? Maybe this is similar to your gui widget selection?



I’ll get back to you Marius.

Allright, thanks for the reply!



Here’s how I plan to do this, I would really like to know your opinion.



Spatials are the beginning of everything, so is it possible to give the Spatial class two new methods? Like getWorldCoordinates(float x, float y) and getScreenCoordinates(float x, float y, float z), which both return the wanted coordinates.



The methods basically use gluUnProject and gluProject. Big question for me would be : how do I get the needed parameters - besides the input coordinates - : modelview, projection matrix, viewport.



I hope i made myself a bit clear and eagerly await your response :stuck_out_tongue:

Like getWorldCoordinates(float x, float y) and getScreenCoordinates(float x, float y, float z), which both return the wanted coordinates.


I was thinking along those lines, but I was thinking about going the other way. Specifically, something like:

mouse.getWorldCoordinate() will return a Vector3f object that translates the current mouse position in the world.

Or perhaps even

mouse.getRayProjection() which would return a Ray object with it's origin at (mouse.getWorldCoordinate()) and the direction as the normal of the camera frame projected from the mouse position.

Which would you prefer?

Cool, excactly what I ment :slight_smile:



I think the mouse could indeed have a getRayProjection(), but implementing the getWorldCoordinate/getScreenCoordinate lower-level, also means that I can place a Text-element on the right screen position, based on my world object ( like a space-ship with a healthbar ).

Good idea. It’s on the todo list. :slight_smile: So, I’ll try to get to it as soon as I can. Although I’m going out of town next week, so there may be a bit of a delay. I’d recommend doing your own little hack in the mean time (or heck if your “hack” ends up being good, we might be able to use it). But I will work on it when time allows.

Sure thing. But as said before , I have one problem. I need to gain access to these GL Parameters : modelview, projection matrix, viewport.



Is there any way to get these parameters on a “clean way”. I noticed the

“display.getRenderer()” gains access to the LWJGLrenderer, so if i’m right i have to make some methods like getModelview ( etc. ) within LWJGLrenderer to gain acces.



If there is a faster/better way that would be nice ofcourse.

We will have to work on a nice clean abstracted way for you to obtain that info. Viewport can be obtained from the camera:



display.getRenderer().getCamera().



perhaps the rest should be in camera as well, as it’s what controls the projection.



until then, just call GL.* directly from your code, we can then replace it with the proper jME calls when they are implemented.

Well, I did it!



This version is way not optimal ( considering buffers and vectors ) but I was able to transform screen and world coordinates.



Included is a screenshot of a small test I did. It shows a sphere and some text. The text shows the cube’s screen location (objPos) and the text world’s location (txtPos)



http://www.ziso.net/marius/screenshot.png



I uploaded the altered spatial.java here!



/edit

Tackled a bug when translating screen to world coordinates. It automatically looks at the far plane now. I can actually select thingies with my mouse :slight_smile:



Hope this is any use for anyone.

Great Marius!



I’ll take a look at what you did and try to implement it into jME. Just a matter of getting time.



Thanks!

Feel free to change anything you want :slight_smile: It’s far from perfect.

I updated the hacked Spatial, version available here :http://www.ziso.net/marius/Spatial.java



In order to pick objects with an absolute mouse: Convert the mouse screen coordinates with mouse.getWorldCoordinates(). This will get the mouse coordinates at Z=0. Creating a Ray with these coordinates as origin and the camera’s direction as direction (duh) creates the ray you need. Will try to create an example soon.



[/url]

Sorry about the delay on getting this into the base line. It’s still on my list and I promise I’ll get to it soon. Just wanted to let you know I haven’t forgotten about it.

The following methods have been added to DisplaySystem:


 
    /**
     * Translate world to screen coordinates
     * @param worldPosition Vector3f
     * @return Vector2f
     */
    public abstract Vector2f getScreenCoordinates(Vector3f worldPosition);
 
   
    /**
     * Translate screen to world coordinates.
     * @param screenPosition Vector2f
     * @return Vector3f
     */
    public abstract Vector3f getWorldCoordinates(Vector2f screenPosition);



A version of the methods you put together (updated to work with lwjgl .9) has been implemented in LWJGLDisplaySystem.

Please test this out as I can't be sure it will work due to the changes they made to GLU. (they dropped nio buffers in the unproject and project, weird huh?)

Looks great, I have yet to test this new code but already have one request.



The getWorldCoordinates should take a Z-value so you can create a ray from z=0 to z=1 from the mouse x,y coordinates. This is one feature I added later on in my hacked version. At the moment Z=0 is hard-coded. Shouldn’t be that hard to change :slight_smile:



Anyway, thanks for adding!

Can you calculate the same thing using the camera’s position?

No, since the camera location and direction differs from your mousepointer (as far as I know). To calculate the direction of the ray you need the start point (x,y) and the direction of the ray ( which you get if you substract the far plane position with the near plane position)



Correct me if I’m wrong :slight_smile:





ps. The current mouse picking test does use the camera position. Note that the pointer of the mouse in this example is static (center of the screen) so you can use the camera position and direction to cast a ray.

zPos added to cvs. Let me know how it works!

i get this:



java.lang.UnsupportedOperationException
   at java.nio.IntBuffer.array(IntBuffer.java:903)
   at com.jme.system.lwjgl.LWJGLDisplaySystem.getScreenCoordinates(LWJGLDisplaySystem.java:317)
   at jmetest.effects.lenseflare.TestLenseFlare.update(TestLenseFlare.java:99)
   at com.jme.app.BaseGame.start(BaseGame.java:68)
   at jmetest.effects.lenseflare.TestLenseFlare.main(TestLenseFlare.java:75)




and this is the code i do to get to it:


Vector2f f = display.getScreenCoordinates(currentPos);



is this the way its used?

ps. the currentPos is the same currentPos in the TerrainLighting demo.

Turns out that IntBuffer.array() is an optional method that throws this exception only if the buffer has an accessible backing array. Which apparently our doesn’t. So, I am building an array manually, which is probably inefficient and not the best solution, but we can deal with that later. Test that and let me know.