Mouse Picking always returns null

Basicly as it says in the title, I copied the mouse pointer code from the tutorial but instead of using an analog listener, I get the inputs another way and run the code in a void and the CollisionResults seem to always be null no matter what. The scene contains mostly boxes, cylinders and spheres that are in multiple layers of nodes and have RigidBodyControls attached. I am using a ChaseCamera, so that might interfiere with the raycasting or not… I’m not sure if the problem is really obvious so I’ll provide more detailed info as needed.

“I copied the code exactly, I just changed it and now it doesn’t work”

Best to show your code then.

As I said, its the same but without the AnalogListener -.-

         // Reset results list.
         CollisionResults results = new CollisionResults();
         // Aim the ray from camera location in camera direction
         // (assuming crosshairs in center of screen).
         Ray ray = new Ray(cam.getLocation(), cam.getDirection());
         // Collect intersections between ray and all nodes in results list.
         rootNode.collideWith(ray, results);
         // Print the results so we see what is going on
         for (int i = 0; i < results.size(); i++) {
           // For each “hit”, we know distance, impact point, geometry.
           float dist = results.getCollision(i).getDistance();
           Vector3f pt = results.getCollision(i).getContactPoint();
           String target = results.getCollision(i).getGeometry().getName();
           System.out.println("Selection #" + i + ": " + target + " at " + pt + ", " + dist + " WU away.");
         }
         // 5. Use the results -- we rotate the selected geometry.
         if (results.size() > 0) {
           // The closest result is the target that the player picked:
           Geometry target = results.getClosestCollision().getGeometry();
           // Here comes the action:
           if(target.getName().equals("Red Box"))
             target.rotate(0, - intensity, 0);
           else if(target.getName().equals("Blue Box"))
             target.rotate(0, intensity, 0);
         }

So what is null where now. And best include all your code…

The for loop should have printed out the object names? Or adding a System.out.print(results) after it always returns an empty array.
Shrinked code, in another class:

static Node target;
	
	public static void pick()
	{		
		CollisionResults results = new CollisionResults();
        
  	  	Vector2f click2d = CPU.game.getInputManager().getCursorPosition();
  	  	Vector3f click3d = CPU.game.getCamera().getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 0f).clone();
  	  	Vector3f dir = CPU.game.getCamera().getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 1f).subtractLocal(click3d).normalizeLocal();
      
  	  	Ray ray = new Ray(click3d, dir);
  	  	CPU.game.getRootNode().collideWith(ray, results);
  	  
  	  	System.out.println(results);
  	  	
  	  	if(results.getClosestCollision() != null)
  	  	{
  	  		target = results.getClosestCollision().getGeometry().getParent();
  	  		target.setLocalRotation(new Quaternion((float)Math.random()*3.14f,(float)Math.random()*3.14f,(float)Math.random()*3.14f,(float)Math.random()*3.14f));
  	  	}
	}

When and how do you call that code? And why is it completely different code now?

I call it with an ActionListener that logs all keyboard and mouse inputs; the method definitly gets called when I press the left mouse button. The second code is what I’ve come to after throwing away all the parts of the tutorial that i don’t currently need. I made the second one first and when it didn’t work I tried running the entire tutorial code in the main class when the method would get called to see if I missed anything. That didn’t work either.

It would still help if you made a complete test case. Your approach of making static methods makes the code a little diffuse. The tutorial test code works fine for me.

Here you go, I left the void static for the sake of testing:

import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.PhysicsTickListener;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.collision.CollisionResults;
import com.jme3.input.ChaseCamera;
import com.jme3.input.InputManager;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Ray;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Box;

public class MCVE extends SimpleApplication{

	private static Node object = new Node();;
	private static BulletAppState physics = new BulletAppState();
	private static RigidBodyControl ctrl = new RigidBodyControl(2f);
	private static boolean pick = false;
	private static Node target;

	public static boolean done = false;
	
	@Override
	public void simpleInitApp() {

		stateManager.attach(physics);
		flyCam.setEnabled(false);
		
                AmbientLight al=new AmbientLight();
                al.setColor(ColorRGBA.White);
                rootNode.addLight(al);

		cam.setFrustumPerspective(80f, (float) cam.getWidth() / cam.getHeight(), 0.01f, 800000f);		
		physics.getPhysicsSpace().setGravity(new Vector3f(0, 0f, 0));
		
		Material blank = new Material(assetManager,"Common/MatDefs/Light/Lighting.j3md");
		
		Geometry brick_geo = new Geometry("box", new Box(1,1,1));
		brick_geo.setMaterial(blank);		
		object.attachChild(brick_geo);
		object.addControl(ctrl);
		rootNode.attachChild(object);		
		physics.getPhysicsSpace().add(ctrl);	
		
		inputManager.addMapping("mouseprimary", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
		inputManager.addListener(keyboard, new String[] {"mouseprimary"});
	}
	
	private static ActionListener keyboard = new ActionListener(){
		@Override
		public void onAction(String name, boolean keyPressed, float tpf) {
			if (name.equals("mouseprimary") && !keyPressed)
				pick = true;
		}
	};
	
	@Override
	public void simpleUpdate(float tpf) {
		if(pick)
		{
			pickobject(inputManager, cam, rootNode);
			pick = false;
		}
	}

	public static void pickobject(InputManager inputManager, Camera cam, Node rootNode)
	{		
		CollisionResults results = new CollisionResults();
        
  	  	Vector2f click2d = inputManager.getCursorPosition();
  	  	Vector3f click3d = cam.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 0f).clone();
  	  	Vector3f dir = cam.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 1f).subtractLocal(click3d).normalizeLocal();
      
  	  	Ray ray = new Ray(click3d, dir);
  	  	rootNode.collideWith(ray, results);
  	  
  	  	System.out.println(results);
  	  	
  	  	if(results.getClosestCollision() != null)
  	  	{
  	  		target = results.getClosestCollision().getGeometry().getParent();
  	  		target.setLocalRotation(new Quaternion((float)Math.random()*3.14f,(float)Math.random()*3.14f,(float)Math.random()*3.14f,(float)Math.random()*3.14f));
  	  	}
	}
	public static void main(String args[]) {
		MCVE app = new MCVE();
		app.start();
	}

}

remove the cam.setFrustumPerspective line and try again.

Ah so that was the thing, thanks :smiley:

Just a note:
target.setLocalRotation(new Quaternion((float)Math.random()*3.14f,(float)Math.random()*3.14f,(float)Math.random()*3.14f,(float)Math.random()*3.14f));

…is complete nonsense and will probably turn your target unrenderable.

(starts recording playback)Quaternion values are magic. It’s a black box. The values aren’t angles…

Right forgot XD, but that was just some test code that i threw out immediatly anyway :smiley: