getWorldCoordinates to real world coordinates

I have a small problem here.



I have played around with mouse picking for some time now, but I can't just get it right.



I have a plane at y(0) that extends most of the scene. I'm trying to take screen coordinates (mouse) and turn them into world coordinates (that are on the plane, hence y can be ignored).



The problem, however, is that I can quite understand what coordinates getWorldCoordinates is returning. If my object is in the middle of the screen, and my mouse is on it, how do I transform the coordinates returned by getWorldCoordinates into coordinates that are on the plane? Does getWorldCoordinates do merely inverse projection or does it do z buffer test?



Just to make this clearer:



I can get it working if I view everything from above with only camera offset of (0,  y, 0), but not when (x, y, z) for example.



Furthermore, if getWorldCoordinates doesn't do z-test, how should I go about it?




Mouse picking is a multi step dance; first get screen coords, then translate screen coords to world coords, take world coords and draw a ray, check if any thing was intersected by the ray inside the defined distance.



Here is a mouse picking class I use that supports triangle accurate picking, feel free to use it.  Basically it's self contained, just create it and set the pick node (node to search), then call checkPicks( [true/false] );




import com.jme.input.MouseInput;
import com.jme.intersection.BoundingPickResults;
import com.jme.intersection.PickResults;
import com.jme.math.Ray;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.TriMesh;
import com.jme.system.DisplaySystem;
import java.util.ArrayList;



public class MousePicker {

    private TriMesh mesh = null;
    private TriMesh savedMesh = null;
    private Node pickNode = null;                             // Typically this will be the rootNode
    private ArrayList<String> pickedNames = new ArrayList<String>( 1 );
    private Vector2f screenPos = new Vector2f();
    private Vector3f worldCoords = new Vector3f();
    private Vector3f worldCoords2 = new Vector3f();
    private Vector3f[] triangleVerticies = new Vector3f[ 3 ];
    private boolean objectWasPicked = false,  triangleWasPicked = false;

    public MousePicker() {
    }

    public MousePicker( Node node ) {
        pickNode = node;
    }

    public void setPickNode( Node node ) {
        pickNode = node;
    }

    public boolean checkMousePicks() {

        if( pickNode == null ){
            return false;
        }

        return checkMousePicks( false );
    }

    public boolean checkMousePicks( boolean triangleAccurate ) {

        if( pickNode == null ){
            return false;
        }

        pickedNames.clear();
        return runPicker( pickNode, triangleAccurate );
    }

    private boolean runPicker( Node node, boolean triangleAccurate ) {

        savedMesh = null;
        screenPos.set( MouseInput.get().getXAbsolute(), MouseInput.get().getYAbsolute() );
        worldCoords.set( DisplaySystem.getDisplaySystem().getWorldCoordinates( screenPos, 0 ) );
        worldCoords2.set( DisplaySystem.getDisplaySystem().getWorldCoordinates( screenPos, 1 ) );

        Ray ray = new Ray( worldCoords, worldCoords2.subtractLocal( worldCoords ).normalizeLocal() );
        PickResults results = new BoundingPickResults();
        results.setCheckDistance( true );
        node.findPick( ray, results );

        if( results.getNumber() > 0 ){

            objectWasPicked = true;
            for( int i = 0; i < results.getNumber(); i++ ){
                pickedNames.add( results.getPickData( i ).getTargetMesh().getParentGeom().getParent().getName() );

                System.out.println( results.getPickData( i ).getTargetMesh().getParentGeom().getParent().getName() );

                if( triangleAccurate ){
                    mesh = (TriMesh) results.getPickData( i ).getTargetMesh().getParentGeom();

                    for( int j = 0; j < mesh.getTriangleCount(); j++ ){
                        mesh.getTriangle( j, triangleVerticies );

                        triangleWasPicked = ( ray.intersect( triangleVerticies[0].addLocal( mesh.getWorldTranslation() ),
                                triangleVerticies[1].addLocal( mesh.getWorldTranslation() ),
                                triangleVerticies[2].addLocal( mesh.getWorldTranslation() ) ) );

                        if( triangleWasPicked ){
                            savedMesh = mesh;
                            return true;
                        }
                    }
                }

            }

        }

        return ( objectWasPicked || triangleWasPicked );
    }

    public boolean wasObjectPicked() {
        return !pickedNames.isEmpty();
    }

    public void clearPickedResults() {
        pickedNames.clear();
    }

    public boolean wasObjectPicked( String query ) {
        return pickedNames.contains( query );
    }

    public String getAllPickedObjects() {
        return pickedNames.toString();
    }

    public Vector3f[] getPickedTriangle() {
        return triangleVerticies;
    }

    public TriMesh getSavedMesh() {
        return savedMesh;
    }
}

basixs said:

Mouse picking is a multi step dance; first get screen coords, then translate screen coords to world coords, take world coords and draw a ray, check if any thing was intersected by the ray inside the defined distance.

Here is a mouse picking class I use that supports triangle accurate picking, feel free to use it.  Basically it's self contained, just create it and set the pick node (node to search), then call checkPicks( [true/false] );

...


How does this give me the world position of the mouse cursor? I am not really interested in the object that has been picked, but the accurate mouse position in the scene projected onto the XZ plane. Am I missing something obvious here?

I just spend a lame amount of time with the same question, but finally got my answer. Check out this thread - http://www.jmonkeyengine.com/jmeforum/index.php?topic=7517.0, it has code examples also.



You will just have to adjust which coordinates you take from the ray as I use the code for looking for X and Y where Z=0