/** * Picks a point out of a PointArray using a mouse press. * */ import java.awt.AWTEvent; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.awt.event.InputEvent; import java.util.Enumeration; import java.util.ArrayList; import com.sun.j3d.utils.picking.PickCanvas; import com.sun.j3d.utils.picking.PickResult; import com.sun.j3d.utils.picking.PickIntersection; import javax.media.j3d.Behavior; import javax.media.j3d.BranchGroup; import javax.media.j3d.WakeupOnAWTEvent; import javax.media.j3d.WakeupCriterion; import javax.media.j3d.Canvas3D; import javax.media.j3d.PointArray; import javax.vecmath.Point3d; import java.util.ArrayList; import java.util.Iterator; import com.sun.j3d.utils.picking.PickTool; /* * In the code the index of the vertex that was picked is written to the standard error. A more elegant * way to get this info to your other classes would be to maintain a list of PointPickedListeners which * you manage with the following methods: * * addPointPickedListener(PointPickedListener listener) * removePointPickedListener(PointPickedListener listener) * firePointPickedEvent(PointPickedEvent event) * */ public class PointPicker extends Behavior { protected PickCanvas pickCanvas; protected WakeupOnAWTEvent wakeupCriterion; protected int x; protected int y; public PointPicker(Canvas3D canvas, BranchGroup scene) { pickCanvas = new PickCanvas(canvas, scene); // Objects within this disstance from the mouse location will be picked. pickCanvas.setTolerance(3.0f); // We want to get info (indices of points) from the intersected geometry (the PointArray). pickCanvas.setMode(PickCanvas.GEOMETRY_INTERSECT_INFO); } public void initialize() { // Wake up when a mouse button is pressed. wakeupCriterion = new WakeupOnAWTEvent(MouseEvent.MOUSE_PRESSED); wakeupOn(wakeupCriterion); } public void processStimulus(Enumeration criteria) { while (criteria.hasMoreElements()) { WakeupCriterion wakeup = (WakeupCriterion)criteria.nextElement(); if (wakeup instanceof WakeupOnAWTEvent) { AWTEvent[] events = ((WakeupOnAWTEvent)wakeup).getAWTEvent(); if (events.length > 0 && events[events.length-1] instanceof MouseEvent) { MouseEvent event = (MouseEvent)events[events.length-1]; int id = event.getID(); int mod = event.getModifiers(); // If you wanted to pick only when you press certain mouse buttons // you would use an if statement similar to the following: // if (mod == InputEvent.BUTTON1_MASK) // { // THE CODE BELOW // } // The location of the mouse event. x = event.getX(); y = event.getY(); // Pick the closest node pickCanvas.setShapeLocation(x, y); Point3d eyePos = pickCanvas.getStartPosition(); PickResult pickResult = pickCanvas.pickClosest(); // If nothing was picked (didn't click on one of the points) the PickResult // will be null. If we continue with a null result a NullPointerException // will be thrown and the wakeupOn(wakeupCriterion) method will not be // called, effectivly disabling the behavior. if (pickResult != null) { // Get the closest intersection with the geometry. PickIntersection pickIntersection = pickResult.getClosestIntersection(eyePos); // Check that a PointArray was picked if (pickIntersection.getGeometryArray() instanceof PointArray) { // Get the vertex indices of the intersected primitive, // in this case the index of the intersected point in the PointArray. int[] indices = pickIntersection.getPrimitiveVertexIndices(); // There should only be one index since this is a PointArray, // so we use indices[0]. System.err.println("Index of picked point: " + String.valueOf(indices[0])); } } } } } wakeupOn(wakeupCriterion); } }