[help] interactive on screen UI

OK so I’ve started a project to make a mini 3d sketching application using JME3 just to play around, I’ve gotten the camera working in that it rotates around the XYZ axis, zooms in and out, next I need to be able to move the xyz axis up, down,left and right with respect to the view of the camera. If you watch the video, in the bottom right corner I have a mini arrow representation of the axis and its view related to the camera, this is attached to the guiNode, my idea was to detect which arrow I was clicking and move the node holding the axis in the direction of that arrow. How do I find what I’m clicking on the guiNode?

Youtube video showing UI so far

http://wiki.jmonkeyengine.org/doku.php/jme3:beginner:hello_picking

I already have that implemented, when the rotating axis is attached to the rootnode it works fine, I can detect which arrow is selected, but when its attached to the guinode it doesnt work, I only have it attached to the guinode so as to have it follow along with the camera.

Well, without seeing the code I can only guess in a hundred ways… but most likely, you are still creating a Ray for intersecting the world instead of a Ray for intersecting the screen.

…else I don’t know how we can find the problem with your code if we can’t see it…

this is the code I’m using, it works fine relatively when the arrows are attached to rootnode, just getting it to stay with the camera and keep the correct orientation fails, that why I’ve attached it to the guiNode, it gets the effect I desire, you mentioned creating a ray to intersect the screen? How would I go about doing that? I couldnt find anything in the docs about selecting and identifying clicks on items attached to the guiNode?

 if (binding.equals("move"))
        {
            if (isPressed)
            {
                    // Reset results list.
                    CollisionResults results = new CollisionResults();
                    // Convert screen click to 3d position
                    Vector2f click2d = inputManager.getCursorPosition();
                    Vector3f click3d = OrbitCamera.cam.getWorldCoordinates(
                            new Vector2f(click2d.getX(), click2d.getY()), 0f);
                    Vector3f dir = OrbitCamera.cam.getWorldCoordinates(
                            new Vector2f(click2d.getX(), click2d.getY()), 1f).subtractLocal(click3d);
                    // Aim the ray from the clicked spot forwards.
                    Ray ray = new Ray(click3d, dir);
                    // Collect intersections between ray and all nodes in results list.
                    Canvas.n.collideWith(ray, results);
                    // (Print the results so we see what is going on:)
                    Vector3f pt = null;
                    for (int i = 0; i < results.size(); i++)
                    {
                        // (For each “hit”, we know distance, impact point, geometry.)
                        float dist = results.getCollision(i).getDistance();
                        pt = results.getCollision(i).getContactPoint();
                        String target = results.getCollision(i).getGeometry().getName();
                        //   System.out.println("Selection #" + i + ": " + target + " at " + pt + ", " + dist + " WU away.");
                    }
                    // Use the results -- we rotate the selected geometry.
                    if (results.size() > 0)
                    {
                        // The closest result is the target that the player picked:
                        Geometry target = null;
                        target = results.getClosestCollision().getGeometry();
                        System.out.println(target.getName() + pt);
                        
                        if(target.getName().equals("moveX+"))
                        {
                            
                             Main.sceneNode.move(Main.sceneNode.getLocalTranslation().add(0.1f, 0, 0));
                       
                        }
                        if(target.getName().equals("moveY+"))
                        {
                            
                            Main.sceneNode.move(Main.sceneNode.getLocalTranslation().add(0,0.1f, 0));
                        }
                        if(target.getName().equals("moveZ+"))
                        {
                           
                            Main.sceneNode.move(Main.sceneNode.getLocalTranslation().add(0,0,0.1f));
                        }
                        if(target.getName().equals("moveX-"))
                        {
                            
                             Main.sceneNode.move(Main.sceneNode.getLocalTranslation().add(-0.1f, 0, 0));
                       
                        }
                        if(target.getName().equals("moveY-"))
                        {
                            
                            Main.sceneNode.move(Main.sceneNode.getLocalTranslation().add(0,-0.1f, 0));
                        }
                        if(target.getName().equals("moveZ-"))
                        {
                           
                            Main.sceneNode.move(Main.sceneNode.getLocalTranslation().add(0,0,-0.1f));
                        }

                        //code here for what to do with selection
                    } else
                    {
                        
                    }
            }
        }

Well, you see how in that code you are converting screen coordinates to world coordinates to make a Ray? World coordinates will only work in the world. For intersecting things in the guiNode (ie: on the screen) then your Ray would be made with… screen coordinates. Think about the space you are intersecting and what kind of Ray you would need to intersect it.

…I mean, presumably you have to change the coordinates of whatever you were putting in the guiNode, right? You will have to do the same thing with the ray.

ok I’ve tried doing some tests to see if I can get it to print the name of the arrows attached to the guiNode, I’ve tried this code,

 Vector2f location = inputManager.getCursorPosition();



                Vector3f origin = new Vector3f(location.x, location.y, 0);

                Vector3f dir = new Vector3f(0f, 0f, 1f);

                Ray ray = new Ray(origin, dir);



                CollisionResults results = new CollisionResults();

                guiNode.collideWith(ray, results);
                System.out.println(ray + "   " + guiNode.collideWith(ray, results) + "   " + results.getClosestCollision());

the following is the output I get from it

Ray [Origin: (628.0, 68.0, 0.0), Direction: (0.0, 0.0, 1.0)]   0   null
Ray [Origin: (630.0, 84.0, 0.0), Direction: (0.0, 0.0, 1.0)]   0   null
Ray [Origin: (610.0, 108.0, 0.0), Direction: (0.0, 0.0, 1.0)]   0   null

the ray is starting at the correct x and y location on screen, but results still remain at zero?
The code was tried from here Determining size of Geometry in guiNode using screenCoordinates? The arrows are all attached to 1 node which in turn is attached to the guiNode? I’m assuming this fact doesnt matter?

Well, at least your Ray is right now (well, I think it’s upside down but would still hit stuff)… but we don’t know what or where the objects are. Maybe they aren’t clickable? We don’t really have enough information to help further.

if you see the video I linked in my first post, its the rotating arrows in the bottom right corner I’m trying to make clickable, I’ve tried attaching the arrows to the rootnode and doing a regular ray on them, it works fine that way and prints the names of each arrow,

The code we can’t see looks fine from here. :wink:

…we don’t have enough information to help further.

sorry my bad, the following are pastebins of the code,

my main class

my canvas class

my controls class

and the camera class I’m using

the ray casting in the controls class was put back to working with the world because I was trying to find a way to attach the arrays to the scene node and just have them follow the camera hovering in front off to the lower right, alas I have no idea how to do that yet which is why I’m trying to get it working with the guiNode.