|
This Java tip shows how to use the Picking utilities on various GeometryArray
subclasses and Morph object.
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;
import javax.media.j3d.Alpha;
import javax.media.j3d.Appearance;
import javax.media.j3d.Behavior;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.CompressedGeometry;
import javax.media.j3d.CompressedGeometryHeader;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Geometry;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.Group;
import javax.media.j3d.IndexedLineArray;
import javax.media.j3d.IndexedLineStripArray;
import javax.media.j3d.IndexedPointArray;
import javax.media.j3d.IndexedQuadArray;
import javax.media.j3d.IndexedTriangleArray;
import javax.media.j3d.IndexedTriangleFanArray;
import javax.media.j3d.IndexedTriangleStripArray;
import javax.media.j3d.LineArray;
import javax.media.j3d.LineStripArray;
import javax.media.j3d.Material;
import javax.media.j3d.Morph;
import javax.media.j3d.PointArray;
import javax.media.j3d.PointAttributes;
import javax.media.j3d.QuadArray;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.TriangleArray;
import javax.media.j3d.TriangleFanArray;
import javax.media.j3d.TriangleStripArray;
import javax.media.j3d.View;
import javax.media.j3d.WakeupOnElapsedFrames;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.border.BevelBorder;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.picking.PickCanvas;
import com.sun.j3d.utils.picking.PickTool;
import com.sun.j3d.utils.picking.behaviors.PickRotateBehavior;
import com.sun.j3d.utils.picking.behaviors.PickTranslateBehavior;
import com.sun.j3d.utils.picking.behaviors.PickZoomBehavior;
import com.sun.j3d.utils.universe.SimpleUniverse;
/**
* PickTest shows how to use the Picking utilities on various GeometryArray
* subclasses and Morph object. Type of Geometry : CompressedGeometry (
* GullCG.java ) IndexedQuadArray ( CubeIQA.java ) TriangleArray (
* TetrahedronTA.java ) IndexedTriangleArray ( TetrahedronITA.java )
* TriangleFanArray ( OctahedronTFA.java ) IndexedTriangleFanArray (
* OctahedronITA.java ) TriangleStripArray ( IcosahedronTFA.java )
* IndexedTriangleStripArray ( IcosahedronITA.java ) PointArray(
* TetrahedronPA.java ) LineArray( TetrahedronLA.java ) IndexLineArray(
* TetrahedronILA.java ) LineStripArray( TetrahedronLSA.java )
* IndexLineStripArray( TetrahedronILSA.java )
*
* Morph Object uses : QuadArray ( ColorCube.java, ColorPyramidDown.java, and
* ColorPyramidUp.java ).
*/
public class PickTest extends Applet implements ActionListener {
private View view = null;
private QuadArray geomMorph[] = new QuadArray[3];
private Morph morph;
private PickRotateBehavior behavior1;
private PickZoomBehavior behavior2;
private PickTranslateBehavior behavior3;
private SimpleUniverse u = null;
public BranchGroup createSceneGraph(Canvas3D canvas) {
// Create the root of the branch graph
BranchGroup objRoot = new BranchGroup();
// Create a Transformgroup to scale all objects so they
// appear in the scene.
TransformGroup objScale = new TransformGroup();
Transform3D t3d = new Transform3D();
t3d.setScale(1.0);
objScale.setTransform(t3d);
objRoot.addChild(objScale);
// Create a bunch of objects with a behavior and add them
// into the scene graph.
int row, col;
int numRows = 4, numCols = 4;
for (int i = 0; i < numRows; i++) {
double ypos = (double) (i - numRows / 2) * 0.45 + 0.25;
for (int j = 0; j < numCols; j++) {
double xpos = (double) (j - numCols / 2) * 0.45 + 0.25;
objScale
.addChild(createObject(i * numCols + j, 0.1, xpos, ypos));
}
}
BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
100.0);
// Add a light.
Color3f lColor = new Color3f(1.0f, 1.0f, 1.0f);
Vector3f lDir = new Vector3f(0.0f, 0.0f, -1.0f);
DirectionalLight lgt = new DirectionalLight(lColor, lDir);
lgt.setInfluencingBounds(bounds);
objRoot.addChild(lgt);
// Now create the Alpha object that controls the speed of the
// morphing operation.
Alpha morphAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE
| Alpha.DECREASING_ENABLE, 0, 0, 4000, 1000, 500, 4000, 1000,
500);
// Finally, create the morphing behavior
MorphingBehavior mBeh = new MorphingBehavior(morphAlpha, morph);
mBeh.setSchedulingBounds(bounds);
objRoot.addChild(mBeh);
behavior1 = new PickRotateBehavior(objRoot, canvas, bounds);
objRoot.addChild(behavior1);
behavior2 = new PickZoomBehavior(objRoot, canvas, bounds);
objRoot.addChild(behavior2);
behavior3 = new PickTranslateBehavior(objRoot, canvas, bounds);
objRoot.addChild(behavior3);
// Let Java 3D perform optimizations on this scene graph.
objRoot.compile();
return objRoot;
}
private Group createObject(int index, double scale, double xpos, double ypos) {
Shape3D shape = null;
Geometry geom = null;
// Create a transform group node to scale and position the object.
Transform3D t = new Transform3D();
t.set(scale, new Vector3d(xpos, ypos, 0.0));
TransformGroup objTrans = new TransformGroup(t);
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
objTrans.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
// Create a second transform group node and initialize it to the
// identity. Enable the TRANSFORM_WRITE capability so that
// our behavior code can modify it at runtime.
TransformGroup spinTg = new TransformGroup();
spinTg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
spinTg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
spinTg.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
Appearance appearance = new Appearance();
switch (index) {
case 0:
geom = new GullCG();
break;
case 1:
geom = new TetrahedronTA();
break;
case 2:
geom = new OctahedronTFA();
break;
case 3:
geom = new IcosahedronTSA();
break;
case 4:
geom = new CubeIQA();
break;
case 5:
geom = new TetrahedronITA();
break;
case 6:
geom = new OctahedronITFA();
break;
case 7:
geom = new IcosahedronITSA();
break;
case 8:
geomMorph[0] = new ColorPyramidUp();
geomMorph[1] = new ColorCube();
geomMorph[2] = new ColorPyramidDown();
break;
case 9:
geom = new TetrahedronLA();
break;
case 10:
geom = new TetrahedronILA();
break;
case 11:
geom = new TetrahedronLSA();
break;
case 12:
geom = new TetrahedronILSA();
break;
case 13:
geom = new TetrahedronPA();
break;
case 14:
geom = new TetrahedronIPA();
break;
// TODO: other geo types, Text3D?
case 15:
geom = new TetrahedronTA();
break;
}
Material m = new Material();
if (index == 8) {
m.setLightingEnable(false);
appearance.setMaterial(m);
morph = new Morph((GeometryArray[]) geomMorph, appearance);
morph.setCapability(Morph.ALLOW_WEIGHTS_READ);
morph.setCapability(Morph.ALLOW_WEIGHTS_WRITE);
PickTool.setCapabilities(morph, PickTool.INTERSECT_FULL);
spinTg.addChild(morph);
} else {
// Geometry picking require this to be set.
if (index == 0)
m.setLightingEnable(true);
else
m.setLightingEnable(false);
appearance.setMaterial(m);
if ((index == 13) || (index == 14)) {
PointAttributes pa = new PointAttributes();
pa.setPointSize(4.0f);
appearance.setPointAttributes(pa);
}
shape = new Shape3D(geom, appearance);
shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
shape.setCapability(Shape3D.ENABLE_PICK_REPORTING);
PickTool.setCapabilities(shape, PickTool.INTERSECT_FULL);
spinTg.addChild(shape);
}
// add it to the scene graph.
objTrans.addChild(spinTg);
return objTrans;
}
private void setPickMode(int mode) {
behavior1.setMode(mode);
behavior2.setMode(mode);
behavior3.setMode(mode);
}
private void setPickTolerance(float tolerance) {
behavior1.setTolerance(tolerance);
behavior2.setTolerance(tolerance);
behavior3.setTolerance(tolerance);
}
private void setViewMode(int mode) {
view.setProjectionPolicy(mode);
}
// GUI stuff
String pickModeString = new String("Pick Mode");
String boundsString = new String("BOUNDS");
String geometryString = new String("GEOMETRY");
String geometryIntersectString = new String("GEOMETRY_INTERSECT_INFO");
String toleranceString = new String("Pick Tolerance");
String tolerance0String = new String("0");
String tolerance2String = new String("2");
String tolerance4String = new String("4");
String tolerance8String = new String("8");
String viewModeString = new String("View Mode");
String perspectiveString = new String("Perspective");
String parallelString = new String("Parallel");
private void addRadioButton(JPanel panel, ButtonGroup bg, String ownerName,
String buttonName, boolean selected) {
JRadioButton item;
item = new JRadioButton(buttonName);
item.setName(ownerName);
item.addActionListener(this);
if (selected) {
item.setSelected(true);
}
panel.add(item);
bg.add(item);
}
private void setupGUI(JPanel panel) {
ButtonGroup bg;
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(new BevelBorder(BevelBorder.RAISED));
panel.add(new JLabel(pickModeString));
bg = new ButtonGroup();
addRadioButton(panel, bg, pickModeString, boundsString, true);
addRadioButton(panel, bg, pickModeString, geometryString, false);
addRadioButton(panel, bg, pickModeString, geometryIntersectString,
false);
panel.add(new JLabel(toleranceString));
bg = new ButtonGroup();
addRadioButton(panel, bg, toleranceString, tolerance0String, false);
addRadioButton(panel, bg, toleranceString, tolerance2String, true);
addRadioButton(panel, bg, toleranceString, tolerance4String, false);
addRadioButton(panel, bg, toleranceString, tolerance8String, false);
panel.add(new JLabel(viewModeString));
bg = new ButtonGroup();
addRadioButton(panel, bg, viewModeString, perspectiveString, true);
addRadioButton(panel, bg, viewModeString, parallelString, false);
}
public void actionPerformed(ActionEvent e) {
String name = ((Component) e.getSource()).getName();
String value = e.getActionCommand();
//System.out.println("action: name = " + name + " value = " + value);
if (name == pickModeString) {
if (value == boundsString) {
setPickMode(PickCanvas.BOUNDS);
} else if (value == geometryString) {
setPickMode(PickCanvas.GEOMETRY);
} else if (value == geometryIntersectString) {
setPickMode(PickCanvas.GEOMETRY_INTERSECT_INFO);
} else {
System.out.println("Unknown pick mode: " + value);
}
} else if (name == toleranceString) {
if (value == tolerance0String) {
setPickTolerance(0.0f);
} else if (value == tolerance2String) {
setPickTolerance(2.0f);
} else if (value == tolerance4String) {
setPickTolerance(4.0f);
} else if (value == tolerance8String) {
setPickTolerance(8.0f);
} else {
System.out.println("Unknown tolerance: " + value);
}
} else if (name == viewModeString) {
if (value == perspectiveString) {
setViewMode(View.PERSPECTIVE_PROJECTION);
} else if (value == parallelString) {
setViewMode(View.PARALLEL_PROJECTION);
}
} else {
System.out.println("Unknown action name: " + name);
}
}
public PickTest() {
}
public void init() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
add("Center", c);
JPanel guiPanel = new JPanel();
setupGUI(guiPanel);
add(guiPanel, BorderLayout.EAST);
// Create a scene and attach it to the virtual universe
BranchGroup scene = createSceneGraph(c);
u = new SimpleUniverse(c);
// This will move the ViewPlatform back a bit so the
// objects in the scene can be viewed.
u.getViewingPlatform().setNominalViewingTransform();
view = u.getViewer().getView();
u.addBranchGraph(scene);
}
public void destroy() {
u.cleanup();
}
public static void main(String argv[]) {
BranchGroup group;
new MainFrame(new PickTest(), 750, 550);
}
}
class TetrahedronILSA extends IndexedLineStripArray {
private static final int[] lineLengths = { 4, 4 };
TetrahedronILSA() {
super(4, GeometryArray.COORDINATES | GeometryArray.COLOR_3, 8,
lineLengths);
Point3f verts[] = new Point3f[4];
Color3f colors[] = new Color3f[4];
verts[0] = new Point3f(1.0f, 1.0f, 1.0f);
verts[1] = new Point3f(1.0f, -1.0f, -1.0f);
verts[2] = new Point3f(-1.0f, -1.0f, 1.0f);
verts[3] = new Point3f(-1.0f, 1.0f, -1.0f);
colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
int pntsIndex[] = new int[8];
int clrsIndex[] = new int[8];
pntsIndex[0] = 0;
clrsIndex[0] = 0;
pntsIndex[1] = 1;
clrsIndex[1] = 1;
pntsIndex[2] = 3;
clrsIndex[2] = 3;
pntsIndex[3] = 2;
clrsIndex[3] = 2;
pntsIndex[4] = 1;
clrsIndex[4] = 1;
pntsIndex[5] = 2;
clrsIndex[5] = 2;
pntsIndex[6] = 0;
clrsIndex[6] = 0;
pntsIndex[7] = 3;
clrsIndex[7] = 3;
setCoordinates(0, verts);
setCoordinateIndices(0, pntsIndex);
setColors(0, colors);
setColorIndices(0, clrsIndex);
}
}
class TetrahedronILA extends IndexedLineArray {
TetrahedronILA() {
super(4, GeometryArray.COORDINATES | GeometryArray.COLOR_3, 12);
Point3f verts[] = new Point3f[4];
Color3f colors[] = new Color3f[4];
verts[0] = new Point3f(1.0f, 1.0f, 1.0f);
verts[1] = new Point3f(1.0f, -1.0f, -1.0f);
verts[2] = new Point3f(-1.0f, -1.0f, 1.0f);
verts[3] = new Point3f(-1.0f, 1.0f, -1.0f);
colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
colors[1] = new Color3f(0.0f, 1.0f, 0.0f);
colors[2] = new Color3f(0.0f, 0.0f, 1.0f);
colors[3] = new Color3f(1.0f, 1.0f, 0.0f);
int[] pntsIndex = new int[12];
int[] clrsIndex = new int[12];
pntsIndex[0] = 0;
clrsIndex[0] = 0;
pntsIndex[1] = 1;
clrsIndex[1] = 1;
pntsIndex[2] = 1;
clrsIndex[2] = 1;
pntsIndex[3] = 2;
clrsIndex[3] = 2;
pntsIndex[4] = 2;
clrsIndex[4] = 2;
pntsIndex[5] = 0;
clrsIndex[5] = 0;
pntsIndex[6] = 1;
clrsIndex[6] = 1;
pntsIndex[7] = 3;
clrsIndex[7] = 3;
pntsIndex[8] = 2;
clrsIndex[8] = 2;
pntsIndex[9] = 3;
clrsIndex[9] = 3;
pntsIndex[10] = 0;
clrsIndex[10] = 0;
pntsIndex[11] = 3;
clrsIndex[11] = 3;
setCoordinates(0, verts);
setCoordinateIndices(0, pntsIndex);
setColors(0, colors);
setColorIndices(0, clrsIndex);
}
}
class TetrahedronTA extends TriangleArray {
TetrahedronTA() {
super(12, GeometryArray.COORDINATES | GeometryArray.COLOR_3);
Point3f verts[] = new Point3f[4];
Color3f colors[] = new Color3f[4];
verts[0] = new Point3f(1.0f, 1.0f, 1.0f);
verts[1] = new Point3f(1.0f, -1.0f, -1.0f);
verts[2] = new Point3f(-1.0f, -1.0f, 1.0f);
verts[3] = new Point3f(-1.0f, 1.0f, -1.0f);
colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
colors[1] = new Color3f(0.0f, 1.0f, 0.0f | |