Click in a model

hi,



I need to perform an action when the user clicks upon a model of the scene …





how I do it? :?

pickResults.getNumber () is still equal to 0 …



… I click in the box and nothing happens … you could give me a sample program for me to implement on top?



I do not understand why this is not working … but is very important I put this functionality in my game …

here you go




import MouseWork.thestatemanager;
import MouseWork.theingame.gunAction;

import com.jme.app.BaseSimpleGame;
import com.jme.app.SimpleGame;
import com.jme.app.AbstractGame.ConfigShowMode;
import com.jme.bounding.BoundingSphere;
import com.jme.input.InputHandler;
import com.jme.input.MouseInput;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.intersection.TrianglePickResults;
import com.jme.light.DirectionalLight;
import com.jme.math.Ray;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.CameraNode;
import com.jme.scene.Node;
import com.jme.scene.TriMesh;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.LightState;
import com.jme.system.DisplaySystem;

public class MeshName extends SimpleGame{
   
   Node myStuff = new Node("pick this");
   public InputHandler input = new InputHandler();

   @Override
   protected void simpleInitGame() {
      MouseInput.get().setCursorVisible(true);
      CameraNode camNode = new CameraNode("cam node", cam);
      camNode.setCamera(cam);
      // moves the camera x,y,z coordinates currently 0,220,1 *edited need fix
      camNode.setLocalTranslation(0,0,-40);
      rootNode.attachChild(camNode);
       input.addAction( new pickit(),
                InputHandler.DEVICE_MOUSE, 0, InputHandler.AXIS_NONE, true );
       
       Sphere s = new Sphere("lol",new Vector3f(0,0,0), 20,20,10);
       s.setLocalTranslation(0,0,0);
       s.setModelBound(new BoundingSphere());
       s.updateWorldBound();
       s.updateModelBound();
       s.updateRenderState();
      s.updateGeometricState( 0, true );
       Sphere s2 = new Sphere("lol",new Vector3f(0,0,0), 20,20,10);
       s2.setLocalTranslation(-20,0,0);
       s2.setModelBound(new BoundingSphere());
       s2.updateWorldBound();
       s2.updateModelBound();
       s2.updateRenderState();
      s2.updateGeometricState( 0, true );
       Sphere s3 = new Sphere("lol",new Vector3f(0,0,0), 20,20,10);
       s3.setLocalTranslation(20,0,0);
       s3.setModelBound(new BoundingSphere());
       s3.updateWorldBound();
       s3.updateModelBound();
       s3.updateRenderState();
      s3.updateGeometricState( 0, true );
       myStuff.attachChild(s);
       myStuff.attachChild(s2);
       myStuff.attachChild(s3);
       myStuff.setModelBound(new BoundingSphere());
       myStuff.updateWorldBound();
       myStuff.updateModelBound();
       myStuff.updateRenderState();
      myStuff.updateGeometricState( 0, true );
       rootNode.attachChild(myStuff);
         /** Set up a basic, default light. */
          DirectionalLight light = new DirectionalLight();
        light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
          light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
          light.setDirection(new Vector3f(1,-1,0));
          light.setEnabled(true);
    
            /** Attach the light to a lightState and the lightState to rootNode. */
          LightState lightState = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
          lightState.setEnabled(true);
          lightState.attach(light);
          rootNode.setRenderState(lightState);
      rootNode.updateGeometricState( 0, true );
   }
    public void simpleUpdate(){
       input.update(tpf);
   }
   
    public static void main(String[] args){
        MeshName app = new MeshName();
        app.setConfigShowMode(ConfigShowMode.AlwaysShow);
        app.start();
    }
   
    public class pickit extends InputAction {

      public void performAction( InputActionEvent evt ) {
           Vector2f mousePos = new Vector2f();
         mousePos.x = MouseInput.get().getXAbsolute();
         mousePos.y = MouseInput.get().getYAbsolute();
           Ray pickRay = new Ray();
           DisplaySystem display = DisplaySystem.getDisplaySystem();
           display.getWorldCoordinates(mousePos, 0, pickRay.getOrigin());
           display.getWorldCoordinates(mousePos, 1, pickRay.getDirection());
           pickRay.getDirection().subtractLocal(pickRay.getOrigin()).normalizeLocal();

            // Does the mouse's ray intersect the box's world bounds?
          TrianglePickResults pr =  new TrianglePickResults();
            pr.clear();
            pr.setCheckDistance(true);
            myStuff.findPick(pickRay, pr);
           if(pr.getNumber() > 0) {
             for(int j=0; j<pr.getNumber(); j++) {
                pr.getPickData(0).getTargetMesh().removeFromParent();
                    
             
             }
           }
        }
    }
}



one problem I ran into making that. if you are using SimpleGame, the firstpersoncamera thingy causes problems with picking from the mouse.

one way you can do this is through casting a Ray.



when the user clicks, do something along these lines:


       //get the position of the mouse on the screen
mousePos.x = MouseInput.get().getXAbsolute();
       mousePos.y = MouseInput.get().getYAbsolute();
//build the ray
               Ray pickRay = new Ray();
               DisplaySystem display = DisplaySystem.getDisplaySystem();
               display.getWorldCoordinates(mousePos, 0, pickRay.getOrigin());
               display.getWorldCoordinates(mousePos, 1, pickRay.getDirection());
//cast the ray
               pickRay.getDirection().subtractLocal(pickRay.getOrigin()).normalizeLocal();
               TrianglePickResults pr =  new TrianglePickResults();
                pr.clear();
//grab the closest object first
                pr.setCheckDistance(true);
//pick on your node
                yourNode.findPick(pickRay, pr);
               if(pr.getNumber() > 0) {
                 String name = pr.getPickData(0).getTargetMesh().getName();
               }


where mousePos is a vector2f and yourNode does not contain any physics Nodes.

This will give you the name of the mesh which you just clicked on. (As long as I didnt make any mistakes building that.

Yes,…picking is the 'topic' for this. Have a look at jmetest.intersection.TestPick

Eggsworth, I made a test with your code, but it dosent work…



my code test:




//in this test the objective was delet a clicked node ...

MouseInput.get().addListener( new MouseInputListener() {
            public void onButton( int button, boolean pressed, int x, int y ) {
              
                Vector2f mousePos = new Vector2f (x,y);

               Ray pickRay = new Ray();
               DisplaySystem display = DisplaySystem.getDisplaySystem();
               display.getWorldCoordinates(mousePos, 0, pickRay.getOrigin());
               display.getWorldCoordinates(mousePos, 1, pickRay.getDirection());
              
               pickRay.getDirection().subtractLocal(pickRay.getOrigin()).normalizeLocal();
                TrianglePickResults pr =  new TrianglePickResults();
                pr.clear();
                
                pr.setCheckDistance(true);
    
                 boxNode.findPick(pickRay, pr);          
               if(pr.getNumber() > 0)
                {
                 String name = pr.getPickData(0).getTargetMesh().getName();
                                rootNode.detachChildNamed(name);
           }



            }

            public void onWheel( int wheelDelta, int x, int y ) {
              
            }

            public void onMove( int xDelta, int yDelta, int newX, int newY ) {
                
            }
        } );






pr.getNumber() ever is equals 0...

whats the problem?

anybody can help-me?

well, what is happening is that the String "name" is referencing to the name of the object



Node node = new Node("name");



so, you need a way to reference String "name" to the node.



Some things you could try:

 rootNode.detachChild(pr.getPickData(0).getTargetMesh().getParent());



or you could use a switch statement and put all the possible mesh names into the switch, depending on the name returned by .getName() you could delete different nodes.

but the problem is that pr.getNumber () is always  0 …



when i make this:




boxNode.findPick(pickRay, pr);
          JOptionPane.showMessageDialog(null,pr.getNumber(),"", JOptionPane.INFORMATION_MESSAGE);
               if(pr.getNumber() > 0)
                {

                      // never get into here :|


                 String name = pr.getPickData(0).getTargetMesh().getName();
                    rootNode.detachChildNamed(name);
               }




pr.getNumber() is always 0.... then, never get into that if...

whats the problem?

hmm… perhaps try with BoundingPickResults rather than triangle pick, because you dont need the triangle pick, just the name of the model



Make sure you set the bounding volume for the models and updateModelBound()


      BoundingPickResults pickResults = new BoundingPickResults();
         pickResults.clear();
         players.findPick(pickRay, pickResults); 
         pickResults.setCheckDistance(true);  
         for (int i = 0; i < pickResults.getNumber(); i++) {
            System.out.println("Results: " + "n");
            String s = pickResults.getPickData(i).getTargetMesh().getName();
            System.out.println(s + "n");
            if(s == "name1"){
               //dostuff
            }else if(s == "name2"){
                                        //dostuff
            }else if(s == "name3"){
                                        //dostuff
            }else{
               System.out.println("Unknown Result");
            }
         }



Try that and let me know what happens.
Eggsworth said:

one problem I ran into making that. if you are using SimpleGame, the firstpersoncamera thingy causes problems with picking from the mouse.


If desired, you can set the first person controller to only look around on mouse click (as well as select which button to require)

oh! that is very interesting. i never knew that.



All I did was steal the camera and put it in a Node to stop that problem, as well as set the mouse visible.



Although… your solution would probably work too.

@sarkozy : Did you set a boundingvolume?

e.g.:    box.setModelBound(new BoundingSphere());

            box.updateModelBound();

Eggsworth, put your code in my program and implemented what I needed on top and worked perfectly … thanks


no problem, im glad it worked.