Java tutorial
/* * @(#)TickTockCollision.java 1.16 02/10/21 13:58:00 * * Copyright (c) 1996-2002 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY * OF SUCH DAMAGES. * * You acknowledge that Software is not designed,licensed or intended for use in * the design, construction, operation or maintenance of any nuclear facility. */ import java.applet.Applet; import java.awt.BorderLayout; import java.awt.GraphicsConfiguration; import java.util.Enumeration; import javax.media.j3d.Alpha; import javax.media.j3d.Appearance; import javax.media.j3d.Background; import javax.media.j3d.Behavior; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.ColoringAttributes; import javax.media.j3d.Group; import javax.media.j3d.QuadArray; import javax.media.j3d.RotationInterpolator; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.WakeupOnCollisionEntry; import javax.media.j3d.WakeupOnCollisionExit; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.universe.SimpleUniverse; public class TickTockCollision extends Applet { private SimpleUniverse u = null; public BranchGroup createSceneGraph() { // 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(0.4); objScale.setTransform(t3d); objRoot.addChild(objScale); // Create a bounds for the background and behaviors BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); // Set up the background Color3f bgColor = new Color3f(0.05f, 0.05f, 0.2f); Background bg = new Background(bgColor); bg.setApplicationBounds(bounds); objScale.addChild(bg); // Create a pair of transform group nodes and initialize them to // identity. Enable the TRANSFORM_WRITE capability so that // our behaviors can modify them at runtime. Add them to the // root of the subgraph. TransformGroup objTrans1 = new TransformGroup(); objTrans1.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); objScale.addChild(objTrans1); TransformGroup objTrans2 = new TransformGroup(); objTrans2.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); objTrans1.addChild(objTrans2); // Create the positioning and scaling transform group node. Transform3D t = new Transform3D(); t.set(0.3, new Vector3d(0.0, -1.5, 0.0)); TransformGroup objTrans3 = new TransformGroup(t); objTrans2.addChild(objTrans3); // Create a simple shape leaf node, add it to the scene graph. objTrans3.addChild(new ColorCube()); // Create a new Behavior object that will perform the desired // rotation on the specified transform object and add it into // the scene graph. Transform3D yAxis1 = new Transform3D(); yAxis1.rotX(Math.PI / 2.0); Alpha tickTockAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE | Alpha.DECREASING_ENABLE, 0, 0, 5000, 2500, 200, 5000, 2500, 200); RotationInterpolator tickTock = new RotationInterpolator(tickTockAlpha, objTrans1, yAxis1, -(float) Math.PI / 2.0f, (float) Math.PI / 2.0f); tickTock.setSchedulingBounds(bounds); objTrans2.addChild(tickTock); // Create a new Behavior object that will perform the desired // rotation on the specified transform object and add it into // the scene graph. Transform3D yAxis2 = new Transform3D(); Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0, 4000, 0, 0, 0, 0, 0); RotationInterpolator rotator = new RotationInterpolator(rotationAlpha, objTrans2, yAxis2, 0.0f, (float) Math.PI * 2.0f); rotator.setSchedulingBounds(bounds); objTrans2.addChild(rotator); // Now create a pair of rectangular boxes, each with a collision // detection behavior attached. The behavior will highlight the // object when it is in a state of collision. Group box1 = createBox(0.3, new Vector3d(-1.3, 0.0, 0.0)); Group box2 = createBox(0.3, new Vector3d(1.3, 0.0, 0.0)); objScale.addChild(box1); objScale.addChild(box2); // Have Java 3D perform optimizations on this scene graph. objRoot.compile(); return objRoot; } private Group createBox(double scale, Vector3d pos) { // Create a transform group node to scale and position the object. Transform3D t = new Transform3D(); t.set(scale, pos); TransformGroup objTrans = new TransformGroup(t); // Create a simple shape leaf node and add it to the scene graph Shape3D shape = new Box(0.5, 5.0, 1.0); objTrans.addChild(shape); // Create a new ColoringAttributes object for the shape's // appearance and make it writable at runtime. Appearance app = shape.getAppearance(); ColoringAttributes ca = new ColoringAttributes(); ca.setColor(0.6f, 0.3f, 0.0f); app.setCapability(app.ALLOW_COLORING_ATTRIBUTES_WRITE); app.setColoringAttributes(ca); // Create a new Behavior object that will perform the collision // detection on the specified object, and add it into // the scene graph. CollisionDetector cd = new CollisionDetector(shape); BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); cd.setSchedulingBounds(bounds); // Add the behavior to the scene graph objTrans.addChild(cd); return objTrans; } public TickTockCollision() { } public void init() { setLayout(new BorderLayout()); GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration(); Canvas3D c = new Canvas3D(config); add("Center", c); // Create a simple scene and attach it to the virtual universe BranchGroup scene = createSceneGraph(); u = new SimpleUniverse(c); // This will move the ViewPlatform back a bit so the // objects in the scene can be viewed. u.getViewingPlatform().setNominalViewingTransform(); u.addBranchGraph(scene); } public void destroy() { u.cleanup(); } // // The following allows TickTockCollision to be run as an application // as well as an applet // public static void main(String[] args) { new MainFrame(new TickTockCollision(), 700, 700); } } class CollisionDetector extends Behavior { private static final Color3f highlightColor = new Color3f(0.0f, 1.0f, 0.0f); private static final ColoringAttributes highlight = new ColoringAttributes(highlightColor, ColoringAttributes.SHADE_GOURAUD); private boolean inCollision = false; private Shape3D shape; private ColoringAttributes shapeColoring; private Appearance shapeAppearance; private WakeupOnCollisionEntry wEnter; private WakeupOnCollisionExit wExit; public CollisionDetector(Shape3D s) { shape = s; shapeAppearance = shape.getAppearance(); shapeColoring = shapeAppearance.getColoringAttributes(); inCollision = false; } public void initialize() { wEnter = new WakeupOnCollisionEntry(shape); wExit = new WakeupOnCollisionExit(shape); wakeupOn(wEnter); } public void processStimulus(Enumeration criteria) { inCollision = !inCollision; if (inCollision) { shapeAppearance.setColoringAttributes(highlight); wakeupOn(wExit); } else { shapeAppearance.setColoringAttributes(shapeColoring); wakeupOn(wEnter); } } } class Box extends Shape3D { public Box(double xsize, double ysize, double zsize) { super(); double xmin = -xsize / 2.0; double xmax = xsize / 2.0; double ymin = -ysize / 2.0; double ymax = ysize / 2.0; double zmin = -zsize / 2.0; double zmax = zsize / 2.0; QuadArray box = new QuadArray(24, QuadArray.COORDINATES); Point3d verts[] = new Point3d[24]; // front face verts[0] = new Point3d(xmax, ymin, zmax); verts[1] = new Point3d(xmax, ymax, zmax); verts[2] = new Point3d(xmin, ymax, zmax); verts[3] = new Point3d(xmin, ymin, zmax); // back face verts[4] = new Point3d(xmin, ymin, zmin); verts[5] = new Point3d(xmin, ymax, zmin); verts[6] = new Point3d(xmax, ymax, zmin); verts[7] = new Point3d(xmax, ymin, zmin); // right face verts[8] = new Point3d(xmax, ymin, zmin); verts[9] = new Point3d(xmax, ymax, zmin); verts[10] = new Point3d(xmax, ymax, zmax); verts[11] = new Point3d(xmax, ymin, zmax); // left face verts[12] = new Point3d(xmin, ymin, zmax); verts[13] = new Point3d(xmin, ymax, zmax); verts[14] = new Point3d(xmin, ymax, zmin); verts[15] = new Point3d(xmin, ymin, zmin); // top face verts[16] = new Point3d(xmax, ymax, zmax); verts[17] = new Point3d(xmax, ymax, zmin); verts[18] = new Point3d(xmin, ymax, zmin); verts[19] = new Point3d(xmin, ymax, zmax); // bottom face verts[20] = new Point3d(xmin, ymin, zmax); verts[21] = new Point3d(xmin, ymin, zmin); verts[22] = new Point3d(xmax, ymin, zmin); verts[23] = new Point3d(xmax, ymin, zmax); box.setCoordinates(0, verts); setGeometry(box); setAppearance(new Appearance()); } }