|
This class demonstrates the use of the CollisionDetector class to perform
processing when objects collide. When this program is run the white cube can
be selected and moved by dragging on it with the right mouse button. You
should notice that there is a problem if the movable cube comes into contact
with both of the static cubes at one time. This problem is solved in another
tip with the title: "Collision Detection with Java3D - 2".
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.Behavior;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Bounds;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.IndexedQuadArray;
import javax.media.j3d.Locale;
import javax.media.j3d.Material;
import javax.media.j3d.Node;
import javax.media.j3d.PhysicalBody;
import javax.media.j3d.PhysicalEnvironment;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.media.j3d.ViewPlatform;
import javax.media.j3d.VirtualUniverse;
import javax.media.j3d.WakeupCriterion;
import javax.media.j3d.WakeupOnCollisionEntry;
import javax.media.j3d.WakeupOnCollisionExit;
import javax.media.j3d.WakeupOnCollisionMovement;
import javax.media.j3d.WakeupOr;
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.picking.behaviors.PickTranslateBehavior;
/**
* This class demonstrates the use of the CollisionDetector class to perform
* processing when objects collide. When this program is run the white cube can
* be selected and moved by dragging on it with the right mouse button. You
* should notice that there is a problem if the movable cube comes into contact
* with both of the static cubes at one time. A way round this is given in the
* SimpleCollision2 application.
*
* @see CollisionDetector
* @see SimpleCollision2
* @author I.J.Palmer
* @version 1.0
*/
public class SimpleCollision extends Frame implements ActionListener {
protected Canvas3D myCanvas3D = new Canvas3D(null);
protected Button exitButton = new Button("Exit");
protected BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0,
0.0), 100.0);
/** Transform for the left cube. */
protected TransformGroup leftGroup;
/** Transform for the right cube */
protected TransformGroup rightGroup;
/**
* Transform for the movable cube. This has read, write and pick reporting
* capabilities enabled.
*/
protected TransformGroup moveGroup;
/** A transform to change the size of the movable cube. */
protected TransformGroup scaleGroup;
/** The left static cube. */
protected Shape3D leftCube;
/** The right static cube. */
protected Shape3D rightCube;
/** The movable cube that will collide with the other two cubes */
protected Shape3D moveCube;
/**
* This builds the view branch of the scene graph.
*/
protected BranchGroup buildViewBranch(Canvas3D c) {
BranchGroup viewBranch = new BranchGroup();
Transform3D viewXfm = new Transform3D();
viewXfm.set(new Vector3f(0.0f, 0.0f, 10.0f));
TransformGroup viewXfmGroup = new TransformGroup(viewXfm);
ViewPlatform myViewPlatform = new ViewPlatform();
PhysicalBody myBody = new PhysicalBody();
PhysicalEnvironment myEnvironment = new PhysicalEnvironment();
viewXfmGroup.addChild(myViewPlatform);
viewBranch.addChild(viewXfmGroup);
View myView = new View();
myView.addCanvas3D(c);
myView.attachViewPlatform(myViewPlatform);
myView.setPhysicalBody(myBody);
myView.setPhysicalEnvironment(myEnvironment);
return viewBranch;
}
/**
* This adds some lights to the content branch of the scene graph.
*
* @param b
* The BranchGroup to add the lights to.
*/
protected void addLights(BranchGroup b) {
Color3f ambLightColour = new Color3f(0.5f, 0.5f, 0.5f);
AmbientLight ambLight = new AmbientLight(ambLightColour);
ambLight.setInfluencingBounds(bounds);
Color3f dirLightColour = new Color3f(1.0f, 1.0f, 1.0f);
Vector3f dirLightDir = new Vector3f(-1.0f, -1.0f, -1.0f);
DirectionalLight dirLight = new DirectionalLight(dirLightColour,
dirLightDir);
dirLight.setInfluencingBounds(bounds);
b.addChild(ambLight);
b.addChild(dirLight);
}
/**
* Creates the content branch of the scene graph.
*
* @return BranchGroup with content attached.
*/
protected BranchGroup buildContentBranch() {
//First create a different appearance for each cube
Appearance app1 = new Appearance();
Appearance app2 = new Appearance();
Appearance app3 = new Appearance();
Color3f ambientColour1 = new Color3f(1.0f, 0.0f, 0.0f);
Color3f ambientColour2 = new Color3f(1.0f, 1.0f, 0.0f);
Color3f ambientColour3 = new Color3f(1.0f, 1.0f, 1.0f);
Color3f emissiveColour = new Color3f(0.0f, 0.0f, 0.0f);
Color3f specularColour = new Color3f(1.0f, 1.0f, 1.0f);
Color3f diffuseColour1 = new Color3f(1.0f, 0.0f, 0.0f);
Color3f diffuseColour2 = new Color3f(1.0f, 1.0f, 0.0f);
Color3f diffuseColour3 = new Color3f(1.0f, 1.0f, 1.0f);
float shininess = 20.0f;
app1.setMaterial(new Material(ambientColour1, emissiveColour,
diffuseColour1, specularColour, shininess));
app2.setMaterial(new Material(ambientColour2, emissiveColour,
diffuseColour2, specularColour, shininess));
app3.setMaterial(new Material(ambientColour3, emissiveColour,
diffuseColour3, specularColour, shininess));
//Create the vertex data for the cube. Since each shape is
//a cube we can use the same vertex data for each cube
IndexedQuadArray indexedCube = new IndexedQuadArray(8,
IndexedQuadArray.COORDINATES | IndexedQuadArray.NORMALS, 24);
Point3f[] cubeCoordinates = { new Point3f(1.0f, 1.0f, 1.0f),
new Point3f(-1.0f, 1.0f, 1.0f),
new Point3f(-1.0f, -1.0f, 1.0f),
new Point3f(1.0f, -1.0f, 1.0f), new Point3f(1.0f, 1.0f, -1.0f),
new Point3f(-1.0f, 1.0f, -1.0f),
new Point3f(-1.0f, -1.0f, -1.0f),
new Point3f(1.0f, -1.0f, -1.0f) };
Vector3f[] cubeNormals = { new Vector3f(0.0f, 0.0f, 1.0f),
new Vector3f(0.0f, 0.0f, -1.0f),
new Vector3f(1.0f, 0.0f, 0.0f),
new Vector3f(-1.0f, 0.0f, 0.0f),
new Vector3f(0.0f, 1.0f, 0.0f), new Vector3f(0.0f, -1.0f, 0.0f) };
int cubeCoordIndices[] = { 0, 1, 2, 3, 7, 6, 5, 4, 0, 3, 7, 4, 5, 6, 2,
1, 0, 4, 5, 1, 6, 7, 3, 2 };
int cubeNormalIndices[] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
3, 3, 4, 4, 4, 4, 5, 5, 5, 5 };
indexedCube.setCoordinates(0, cubeCoordinates);
indexedCube.setNormals(0, cubeNormals);
indexedCube.setCoordinateIndices(0, cubeCoordIndices);
indexedCube.setNormalIndices(0, cubeNormalIndices);
//Create the three cubes
leftCube = new Shape3D(indexedCube, app1);
rightCube = new Shape3D(indexedCube, app2);
moveCube = new Shape3D(indexedCube, app3);
//Define the user data so that we can print out the
//name of the colliding cube.
leftCube.setUserData(new String("left cube"));
rightCube.setUserData(new String("right cube"));
//Create the content branch and add the lights
BranchGroup contentBranch = new BranchGroup();
addLights(contentBranch);
//Create and set up the movable cube's TransformGroup.
//This scales and translates the cube and then sets the
// read, write and pick reporting capabilities.
Transform3D moveXfm = new Transform3D();
moveXfm.set(0.7, new Vector3d(0.0, 2.0, 1.0));
moveGroup = new TransformGroup(moveXfm);
moveGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
moveGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
moveGroup.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
//Create the left cube's TransformGroup
Transform3D leftGroupXfm = new Transform3D();
leftGroupXfm.set(new Vector3d(-1.5, 0.0, 0.0));
leftGroup = new TransformGroup(leftGroupXfm);
//Create the right cube's TransformGroup
Transform3D rightGroupXfm = new Transform3D();
rightGroupXfm.set(new Vector3d(1.5, 0.0, 0.0));
rightGroup = new TransformGroup(rightGroupXfm);
//Add the behaviour to allow us to move the cube
PickTranslateBehavior pickTranslate = new PickTranslateBehavior(
contentBranch, myCanvas3D, bounds);
contentBranch.addChild(pickTranslate);
//Add our CollisionDetector class to detect collisions with
//the movable cube.
CollisionDetector myColDet = new CollisionDetector(moveCube, bounds);
contentBranch.addChild(myColDet);
//Create the content branch hierarchy.
contentBranch.addChild(moveGroup);
contentBranch.addChild(leftGroup);
contentBranch.addChild(rightGroup);
moveGroup.addChild(moveCube);
leftGroup.addChild(leftCube);
rightGroup.addChild(rightCube);
return contentBranch;
}
/**
* Process the exit button action to exit the application.
*/
public void actionPerformed(ActionEvent e) {
if (e.getSource() == exitButton) {
dispose();
System.exit(0);
}
}
public SimpleCollision() {
VirtualUniverse myUniverse = new VirtualUniverse();
Locale myLocale = new Locale(myUniverse);
myLocale.addBranchGraph(buildViewBranch(myCanvas3D));
myLocale.addBranchGraph(buildContentBranch());
setTitle("SimpleWorld");
setSize(400 | |