/*
* @(#)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());
}
}