Hi All,
I attached a simple program of picking multiple objects by dragging mouse to
draw a window on the screen. This program draws 2 polygons. If my window is near or
enclosing the right common point of the 2 polygons, it works fine.
Otherwise, it can't get the right result.
The picking process is simple. I constructed a BoundingPolytope type bounds,
which consists of 5 planes. One plane is the backClipPlane, the other 4 planes are
constructed by combining the 4 points of the picking window and
the eye point. Then, setPickShape to the PickBounds for a PickTool object.
BTW, it also works fine for certain other shapes. I don't know why it's not working
for this case. Did I do sth wrong? or the Java3D picking utility
functions have some constraints?
Thanks a lot---white
/*
* PickAllTest.java
*
* Created on July 23, 2002, 10:15 AM
*/
/**
*
* @author
*/
import javax.vecmath.*;
import javax.media.j3d.*;
import com.sun.j3d.utils.picking.PickTool;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import java.awt.*;
public class PickAllTest extends javax.swing.JFrame {
/** Creates new form PickAllTest */
public PickAllTest() {
initComponents();
initGraphics();
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
private void initComponents() {
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
exitForm(evt);
}
});
pack();
java.awt.Dimension screenSize =
java.awt.Toolkit.getDefaultToolkit().getScreenSize();
setSize(new java.awt.Dimension(640, 480));
setLocation((screenSize.width-640)/2,(screenSize.height-480)/2);
}
/** Exit the Application */
private void exitForm(java.awt.event.WindowEvent evt) {
System.exit(0);
}
private void initGraphics(){
GraphicsConfiguration config =
SimpleUniverse.getPreferredConfiguration();
canvas = new Canvas3D(config);
u = new SimpleUniverse(canvas);
imagePanel = new javax.swing.JPanel(new java.awt.BorderLayout());
getContentPane().add(imagePanel, java.awt.BorderLayout.CENTER);
imagePanel.add(canvas, java.awt.BorderLayout.CENTER);
BranchGroup scene = createSceneGraph();
ViewingPlatform viewingPlatform = u.getViewingPlatform();
Transform3D t = new Transform3D();
Point3d cp = new Point3d();
bounds.getCenter(cp);
System.out.println("The bounding center is "+cp.x+", "+cp.y+", "+cp.z);
t.set(new Vector3d(cp.x, cp.y, cp.z + 3.0*bounds.getRadius()));
(viewingPlatform.getViewPlatformTransform()).setTransform(t);
u.addBranchGraph(scene);
imagePanel.updateUI();
}
private BranchGroup createSceneGraph(){
/*
double vertices[] = {0.0525,0,0.726, -0.9779,0,0.397007, -0.85,0.5263,0.4213,
-0.52633,0.732855,0.521687, 0.236547,0.76,0.699422,
0.253872,-0.753073,0.697205, -0.5155,-0.74767,0.520049,
-0.849,-0.5263,0.4213};
*/
double vertices[] = {0.236547,0.76,0.699422, -0.52633,0.732855,0.521687,
-0.85,0.5263,0.4213, -0.9779,0,0.397007, 0.0525,0,0.726};
double vertices1[] = {0.0525,0,0.726, -0.9779,0,0.397007,
-0.849,-0.5263,0.4213, -0.5155,-0.74767,0.520049,
0.253872,-0.753073,0.697205};
Shape3D part1 = new Shape3D();
// Clockwise order
//int []part1Index = {0, 1, 2, 3, 4};
//int []part2Index = {5, 6, 7, 1, 0};
// Counterclockwise order
int []part1Index = {4, 3, 2, 1, 0};
int []part2Index = {0, 1, 7, 6, 5};
int []stripCounts1 = new int[1];
int []stripCounts2 = new int[1];
stripCounts1[0] = part1Index.length;
GeometryInfo gi1 = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
gi1.setCoordinates(vertices);
//gi1.setCoordinateIndices(part1Index);
gi1.setStripCounts(stripCounts1);
//IndexedGeometryArray ga1 = gi1.getIndexedGeometryArray();
GeometryArray ga1 = gi1.getGeometryArray();
part1.setGeometry(ga1);
Appearance myApp1 = new Appearance();
ColoringAttributes colorAttr1 = new ColoringAttributes(0.5f, 0.4f, 0.0f,
ColoringAttributes.SHADE_GOURAUD);
myApp1.setColoringAttributes(colorAttr1);
part1.setAppearance(myApp1);
//part1.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
PickTool.setCapabilities(part1, PickTool.INTERSECT_FULL);
Shape3D part2 = new Shape3D();
// Construct triangleArrays using GeometryInfo Class
GeometryInfo gi2 = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
gi2.setCoordinates(vertices1);
//gi2.setCoordinates(vertices);
//gi2.setCoordinateIndices(part2Index);
stripCounts2[0] = part2Index.length;
gi2.setStripCounts(stripCounts2);
//IndexedGeometryArray ga2 = gi2.getIndexedGeometryArray();
GeometryArray ga2 = gi2.getGeometryArray();
part2.setGeometry(ga2);
Appearance myApp2 = new Appearance();
ColoringAttributes colorAttr2 = new ColoringAttributes(0.2f, 0.7f, 0.0f,
ColoringAttributes.SHADE_GOURAUD);
myApp2.setColoringAttributes(colorAttr2);
part2.setAppearance(myApp2);
//part2.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
//part2.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
//part2.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
PickTool.setCapabilities(part2, PickTool.INTERSECT_FULL);
BranchGroup group = new BranchGroup();
group.addChild(part1);
group.addChild(part2);
bounds = new BoundingSphere(group.getBounds());
WindowPickBehavior pick = new WindowPickBehavior(group, canvas, bounds);
pick.setEnable(true);
group.addChild(pick);
group.compile();
return group;
}
public static void main(String args[]) {
new PickAllTest().show();
}
// Variables declaration - do not modify
// End of variables declaration
private BoundingSphere bounds;
private SimpleUniverse u;
private Canvas3D canvas;
private javax.swing.JPanel imagePanel;
}
/*
* WindowPickBehavior.java
*
* Created on October 29, 2002, 2:09 PM
*/
/**
*
* @author
*/
import javax.media.j3d.*;
import java.awt.event.*;
import java.awt.*;
import javax.vecmath.*;
import javax.media.j3d.*;
import com.sun.j3d.utils.picking.*;
public class WindowPickBehavior extends javax.media.j3d.Behavior {
private WakeupCriterion[] mouseEvents;
private WakeupOr mouseCriterion;
private int orgX, orgY;
private int oldX, oldY;
private int newX, newY;
private boolean activeOn;
private boolean buttonPress;
private Color rubberColor;
private Graphics2D g2d;
private Canvas3D canvas;
private BranchGroup branchGroup;
/** Creates a new instance of WindowPickBehavior */
public WindowPickBehavior(BranchGroup group, Canvas3D canvas, Bounds bounds) {
g2d = (Graphics2D)(canvas.getGraphics());
activeOn = false;
rubberColor = Color.white;
this.canvas = canvas;
branchGroup = group;
oldX = oldY = -1;
g2d.setXORMode(rubberColor);
setSchedulingBounds(bounds);
}
public void setEnable(boolean flag) {
activeOn = flag;
}
public void initialize() {
mouseEvents = new WakeupCriterion[3];
mouseEvents[0] = new WakeupOnAWTEvent(MouseEvent.MOUSE_DRAGGED);
mouseEvents[1] = new WakeupOnAWTEvent(MouseEvent.MOUSE_PRESSED);
mouseEvents[2] = new WakeupOnAWTEvent(MouseEvent.MOUSE_RELEASED);
mouseCriterion = new WakeupOr(mouseEvents);
wakeupOn(mouseCriterion);
}
public void processStimulus(java.util.Enumeration criteria) {
WakeupCriterion wakeup;
AWTEvent[] evt = null;
MouseEvent mevent = null;
if (!activeOn) {
wakeupOn(mouseCriterion);
return;
}
while(criteria.hasMoreElements()) {
wakeup = (WakeupCriterion)criteria.nextElement();
if (wakeup instanceof WakeupOnAWTEvent)
evt = ((WakeupOnAWTEvent)wakeup).getAWTEvent();
}
if (evt[evt.length-1] instanceof MouseEvent){
mevent = (MouseEvent) evt[evt.length-1];
processMouseEvent(mevent);
newX = mevent.getPoint().x;
newY = mevent.getPoint().y;
}
if (buttonPress){
updateScene();
}
wakeupOn(mouseCriterion);
}
/*
* Handles mouse events
*/
public void processMouseEvent(AWTEvent evt) {
if (evt.getID()==MouseEvent.MOUSE_PRESSED) {
buttonPress = true;
orgX = ((MouseEvent)evt).getPoint().x;
orgY = ((MouseEvent)evt).getPoint().y;
return;
}
else if (evt.getID()==MouseEvent.MOUSE_RELEASED) {
buttonPress = false;
//activeOn = false;
oldX = -1;
oldY = -1;
int wd = Math.abs(newX - orgX);
int ht = Math.abs(newY - orgY);
if (wd > 0 || ht > 0) {
g2d.drawRect(orgX, orgY, wd, ht);
// call the function to pick objects
pickObjects();
}
}
else if (evt.getID() == MouseEvent.MOUSE_MOVED) {
// Process mouse move event
}
}
/**
* Draw the rubber wand
*/
private void updateScene() {
int width = 0, height = 0;
/* Before use the new position to draw the rectangle, make the following
* calls using the old position, which in fact erases the old rectangle
*/
if(oldX >= 0 && oldY >= 0) {
width = Math.abs(oldX - orgX);
height = Math.abs(oldY - orgY);
if (width > 0 || height > 0)
g2d.drawRect(orgX, orgY, width, height);
}
width = Math.abs(newX - orgX);
height = Math.abs(newY - orgY);
if (width > 0 || height > 0)
g2d.drawRect(orgX, orgY, width, height);
/*
System.out.println("The org point: ("+ orgX + ", " + orgY + "), old point: ("
+ oldX + ", " + oldY + "), new point: (" + newX + ", " + newY + ")");
*/
oldX = newX;
oldY = newY;
}
/**
* Compute the plane function, return it
*
* @param p1 The 1rst point
* @param p2 The 2nd point
* @param p3 The 3rd point
*
* @return An object of Vector4d, which represents a plane function
*/
private Vector4d getPlaneFunc(Point3d p1, Point3d p2, Point3d p3) {
Point3d pt = new Point3d();
pt.sub(p1, p2);
Vector3d v1 = new Vector3d(pt);
pt.sub(p3, p2);
Vector3d v2 = new Vector3d(pt);
Vector3d planeVec = new Vector3d();
planeVec.cross(v2, v1);
planeVec.normalize();
//double d0 = -planeVec.dot(new Vector3d(p1));
double d1 = -planeVec.dot(new Vector3d(p2));
return new Vector4d(planeVec.x, planeVec.y, planeVec.z, d1);
}
/**
* Function to construct the pickBounds for multiple object picking
*/
private void pickObjects() {
Point3d []pyramVertex = new Point3d[6];
Point2d []rectPoint = new Point2d[5];
for (int ii=0; ii<pyramVertex.length; ii++)
pyramVertex[ii] = new Point3d();
rectPoint[0] = new Point2d(orgX, orgY);
rectPoint[1] = new Point2d(orgX, newY);
rectPoint[2] = new Point2d(newX, newY);
rectPoint[3] = new Point2d(newX, orgY);
java.awt.Dimension dim = canvas.getSize();
rectPoint[4] = new Point2d(dim.width/2.0, dim.height/2.0);
//rectPoint[4] = new Point2d(orgX + (newX - orgX)/2.0,
// orgY + (newY - orgY)/2.0);
for (int ii=0; ii<rectPoint.length; ii++)
canvas.getPixelLocationInImagePlate(rectPoint[ii], pyramVertex[ii]);
canvas.getCenterEyeInImagePlate(pyramVertex[5]);
Transform3D trans = new Transform3D();
canvas.getImagePlateToVworld(trans);
for (int ii=0; ii<pyramVertex.length; ii++)
trans.transform(pyramVertex[ii], pyramVertex[ii]);
//Compute the plane function of the bottom face of the pyramid bounds
double farClipLength = canvas.getView().getBackClipDistance();
Vector3d farClipVect = new Vector3d();
farClipVect.sub(pyramVertex[4], pyramVertex[5]);
farClipVect.normalize();
Vector3d farClipPt = new Vector3d();
farClipPt.scale(farClipLength, farClipVect);
double d0 = -farClipVect.dot(farClipPt);
//Define an array of Vector4d for all the planes of the pickBounds
Vector4d []planeFunc = new Vector4d[5];
planeFunc[0] = new Vector4d(farClipVect.x, farClipVect.y, farClipVect.z, d0);
planeFunc[1] = getPlaneFunc(pyramVertex[0], pyramVertex[1], pyramVertex[5]);
planeFunc[2] = getPlaneFunc(pyramVertex[1], pyramVertex[2], pyramVertex[5]);
planeFunc[3] = getPlaneFunc(pyramVertex[2], pyramVertex[3], pyramVertex[5]);
planeFunc[4] = getPlaneFunc(pyramVertex[3], pyramVertex[0], pyramVertex[5]);
//Define the BoundingPolytope bounds object for picking
BoundingPolytope bounds = new BoundingPolytope(planeFunc);
//PickBounds pickBounds = new PickBounds(bounds);
PickTool pickTool = new PickTool(branchGroup);
pickTool.setMode(PickTool.GEOMETRY);
//pickTool.setShape(pickBounds, pyramVertex[4]);
pickTool.setShapeBounds(bounds, pyramVertex[4]);
PickResult []pr = pickTool.pickAllSorted();
if (pr == null)
return;
else
System.out.println("The number of geometries picked is " + pr.length);
}
}
===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA3D-INTEREST". For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".