import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.universe.*; import javax.media.j3d.*; import javax.vecmath.*; import java.awt.event.*; import java.awt.AWTEvent; import java.util.Enumeration; public class SimpleApp extends Applet { public final int END = 1; public class Translate extends Behavior { private WakeupCriterion pairPostCondition; private WakeupCriterion wakeupNextFrame; private WakeupCriterion AWTEventCondition; private TransformGroup targetTG; private Transform3D t3D = new Transform3D(); private Vector3d initialTranslation = new Vector3d(); private double alpha; private Vector3d translation; private long startTime; private long duration; Translate(TransformGroup targetTG, Vector3d translation, long duration ) { this.targetTG = targetTG; this.translation = translation; this.duration = duration; AWTEventCondition = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED); wakeupNextFrame = new WakeupOnElapsedFrames(0); } public void setStartSignal(Behavior behaviorObject, int signal) { pairPostCondition = new WakeupOnBehaviorPost(behaviorObject, signal); } public void initialize() { alpha = 0.0; this.wakeupOn(AWTEventCondition); } public void processStimulus(Enumeration criteria) { if ( !criteria.nextElement().equals(wakeupNextFrame)) { System.out.println("start translation"); alpha = 0.0; targetTG.getTransform(t3D); t3D.get( initialTranslation ); startTime = System.currentTimeMillis(); this.wakeupOn(wakeupNextFrame); } else { // nextFrame if (alpha < 1.0) { alpha = (double) (System.currentTimeMillis() - startTime)/duration; if (alpha > 1.0) alpha = 1.0; Vector3d value = new Vector3d( translation ); value.scale( alpha ); value.add( initialTranslation ); t3D.setTranslation( value ); targetTG.setTransform(t3D); this.wakeupOn(wakeupNextFrame); } else { // finished, signal other behavior System.out.println("end translation"); postId( END ); this.wakeupOn(pairPostCondition); } } } } // end of class Translate public class Rotate extends Behavior{ private TransformGroup targetTG; private WakeupCriterion pairPostCondition; private WakeupCriterion wakeupNextFrame; private WakeupCriterion AWTEventCondition; private Transform3D t3D = new Transform3D(); private Matrix3d rotMat = new Matrix3d(); private double alpha; Rotate(TransformGroup targetTG){ this.targetTG = targetTG; AWTEventCondition = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED); wakeupNextFrame = new WakeupOnElapsedFrames(0); } public void setStartSignal(Behavior behaviorObject, int signal){ pairPostCondition = new WakeupOnBehaviorPost(behaviorObject, signal); } public void initialize(){ this.wakeupOn(pairPostCondition); alpha = 1.6; } public void processStimulus(Enumeration criteria){ if (criteria.nextElement().equals(pairPostCondition)){ System.out.println("ready to close door"); this.wakeupOn(AWTEventCondition); alpha = 1.6f; } else { // could be KeyPress or nextFrame, in either case: close if (alpha > 0.0){ alpha -= 0.01; if (alpha < 0.0) alpha = 0.0; // get rotation and scale portion of transform targetTG.getTransform(t3D); t3D.getRotationScale(rotMat); // set y-axis rotation to alpha // (clobber any previous y-rotation, x and z scale) rotMat.m00 = Math.cos(alpha); rotMat.m22 = rotMat.m00; rotMat.m02 = Math.sin(alpha); rotMat.m20 = -rotMat.m02; t3D.setRotation(rotMat); targetTG.setTransform(t3D); this.wakeupOn(wakeupNextFrame); } else { // finished opening door, signal other behavior System.out.println("door is closed"); this.wakeupOn(pairPostCondition); postId(1); } } } } // end of class Rotate SimpleUniverse universe; BranchGroup scene; public BranchGroup createSceneGraph() { // Create the root of the branch graph BranchGroup objRoot = new BranchGroup(); TransformGroup doorTG = new TransformGroup(); doorTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); doorTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); Translate translateBehavior = new Translate(doorTG, new Vector3d(1,0,0), 500 ); Rotate rotateBehavior = new Rotate(doorTG); //prepare the behavior objects translateBehavior.setStartSignal(rotateBehavior, END); rotateBehavior.setStartSignal(translateBehavior, END); // set scheduling bounds for behavior objects BoundingSphere bounds = new BoundingSphere(); translateBehavior.setSchedulingBounds(bounds); rotateBehavior.setSchedulingBounds(bounds); // assemble scene graph objRoot.addChild(translateBehavior); objRoot.addChild(rotateBehavior); objRoot.addChild(doorTG); doorTG.addChild(new ColorCube(0.4)); return objRoot; } // end of CreateSceneGraph method of SimpleApp public SimpleApp() { setLayout(new BorderLayout()); Canvas3D canvas3D = new Canvas3D(null); add("Center", canvas3D); // SimpleUniverse is a Convenience Utility class universe = new SimpleUniverse(canvas3D); universe.getViewingPlatform().setNominalViewingTransform(); scene = createSceneGraph(); scene.setCapability( BranchGroup.ALLOW_BOUNDS_READ ); // Let Java 3D perform optimizations on this scene graph. scene.compile(); universe.addBranchGraph(scene); viewAll(20.0f); } // end of SimpleApp (constructor) // The following allows this to be run as an application // as well as an applet public static void main(String[] args) { System.out.print("SimpleApp.java \n- a demonstration of coordinating behavior "); System.out.println("objects for complex behaviors in a Java 3D scene."); System.out.println("When the app loads, press a key to move object."); Frame frame = new MainFrame(new SimpleApp(), 256, 256); } // end of main (method of SimpleApp) /** * Positionne la camera de maniere a pouvoir voir la totalite de la scene */ public void viewAll( float size ) { BoundingSphere mybounds = (BoundingSphere) scene.getBounds() ; double t[] = new double[3] ; Point3d center=new Point3d() ; mybounds.getCenter(center) ; center.get(t) ; // on positionne la camera de facon a voir la sphere TransformGroup cameraPosition = universe.getViewingPlatform(). getViewPlatformTransform() ; Transform3D trans = new Transform3D() ; trans.setTranslation(new Vector3f((float)t[0], (float)t[1], (float)t[2]+(float) mybounds.getRadius()*size )); cameraPosition.setTransform(trans) ; } } // end of class SimpleApp