Picking

Definition

Picking is the process of determining which object in the world is selected through user interaction, usually a mouse click. It can be used for game actions such as aiming at targets (for example shooting) and triggering (for example flicking switches or pressing door handles).


Typically, picking involves the selection of a 3D object from its 2D projection on the screen by pointing and clicking the mouse. The process involves casting a ray into the world from a selected point on the projection plane. Any objects the ray intersects after passing the projection plane are potential objects for selection. Picking is a specific case of Collision Detection. A ray is a line with a start point and a direction.


Support for picking in a hierarchical scene graph amounts to examining the graph recursively until each leaf node is either reached or thrown out. To exploit the scene graph, if a Node is determined to not to be selected all children of this Node not not selected for further tests.


Picking makes extensive use of BoundingVolume's intersection method (see Utility Methods in the BoundingVolume entry.) However, there is a complete Picking System built untop of this functionality to make Picking easier.

The Picking System

At the core of the picking system is Spatial's findPick method. A call to this method will cause one of two things to happen: If the Spatial is a Node, the BoundingVolume that contains this node is checked against a Ray, if that Ray collides with the volume, then each of the Node's children are processed (their respective findPick methods are called). If the Spatial is a Geometry then the Geometry's bounding is checked, and if that Ray collides, then the Geometry object is added to the PickResults.

findPick takes two parameters: The Ray to check against, and the PickResults to store them. The Ray is defined by the user as the line for picking. For example, the user might select the origin as the location of the Camera and the direction as the Camera's direction.

PickResults determines the accuracy of the Picking. It's subclasses define how the leaf node will be processed. BoundingPickResults defines accuracy to the leaf node's bounding volume. This is (in many cases) plenty of accuracy. If the bounding is a “good fit” for the geometry it contains, then the picking will also be fairly accurate. However, in some cases it may be necessary to obtain accuracy to the triangle's hit by the Ray. To do this, make use of the TrianglePickResults subclass.

Which ever accuracy value is used, when a leaf node is determined to have been selected, the PickResults addPick method is called. The Geometry that was selected is then added to a list (and in the case of TrianglePickResults further processed to determine which triangle was selected).

The final results that are contained can then be processed by the user as desired. As stated above, if TrianglePickResults is used, further processing will occur in the addPick method. If the Geometry passed to addPick is actually a TriMesh, then TriMesh's findTrianglePick is called. This runs through the OBBTree containing the mesh's triangles and determines which are touched by the Ray.

Once all elements are added to the PickResults they can be obtained from the list. These elements are called PickData and contain: The ray involved, the Geometry hit, and if TrianglePickResults is used the list of indices for the triangles hit.

Distances

Optionally, the distances for each Geometry can be calculated. This is the distance from the origin of the Ray to the nearest point on the BoundingVolume of the Geometry. This distance is stored in PickData and the PickData is ordered in PickResults from near to far. That is, the 0th element in the list will be the closest result.

Example 1 - Generating the results (Bounding)

Ray ray = new Ray(camera.getLocation(), camera.getDirection());
PickResults results = new BoundingPickResults();
scene.findPick(ray,results);

Example 2 - Generating the results (Triangle)

Sphere s = new Sphere("Sphere", 10, 10, 5);
s.updateCollisionTree(); //required to allow OBBTree interaction
//...
Ray ray = new Ray(camera.getLocation(), camera.getDirection());
PickResults results = new TrianglePickResults();
scene.findPick(ray,results);

Example 3 - Getting the closest PickData

Ray ray = new Ray(camera.getLocation(), camera.getDirection());
PickResults results = new TrianglePickResults();
results.setCheckDistance(true);
scene.findPick(ray,results);
//check if we hit something
if(results.getNumber() > 0) {
   PickData closest = results.getPickData(0);
   System.out.println("The closest hit: " + closest.getTargetMesh().getName());
}

Example 4 - Mouse Picking

private static void mousePick() {
    //Get the mouse position
    Vector2f mousePosition = new Vector2f(MouseInput.get().getXAbsolute(), MouseInput.get().getYAbsolute());
    //Create a pick ray from the display
    Ray ray = DisplaySystem.getDisplaySystem().getPickRay(mousePosition, false, new Ray());
    //Find the results (Use which ever method suits your needs
    PickResults results = new TrianglePickResults();
    //PickResults results = new BoundingPickResults();
    //We normally want the distance to see which object is closest
    results.setCheckDistance(true);
    //Get the results from a node
    rootNode.findPick(ray, results);
    //Loop the results
    for (int i = 0; i < results.getNumber(); i++) {
        PickData hit = results.getPickData(i);
        System.out.println("Hit: " + hit.getTargetMesh().getName() + "(" + hit.getDistance() + ")");
    }
}

/var/www/wiki/data/pages/picking.txt · Last modified: 2009/11/22 10:15 by zathras  
Recent changes · Show pagesource · Login

Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki

subscribe to jME latest jme headlines


site design by bleedcrimson designs © 2008