import java.applet.Applet;
import java.awt.event.*;
import java.awt.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.applet.MainFrame;
import java.util.Enumeration;
import com.sun.j3d.utils.behaviors.mouse.*;


public class Buggy2 extends Applet {
	
        BranchGroup myBranch = null;
        TransformGroup transAll = null;
        Cylinder rcyl = null;
	
        public Buggy2() {
                setLayout(new BorderLayout());
                Canvas3D myCanvas3D = new Canvas3D(null);
                add("Center",myCanvas3D);
                SimpleUniverse u = new SimpleUniverse(myCanvas3D);
                u.getViewingPlatform().setNominalViewingTransform();
        	
                myBranch = makeBranch();
                setCircum();  // set lights
                addMouseReaction(); // set mouse behaviors
                myBranch.compile();
                u.addBranchGraph(myBranch);
        }
	
        private BranchGroup makeBranch() {
                BranchGroup root = new BranchGroup();
        	
                /* left object */
                Transform3D LT3D = new Transform3D();
                LT3D.setTranslation(new Vector3f(-0.2f,0.0f,0.0f));
                TransformGroup LTG = new TransformGroup(LT3D);
                LTG.setCollidable(false);
                Sphere lcyl = new Sphere(0.1f);
                lcyl.setAppearance(makeAppearance());
                LTG.addChild(lcyl);
        	
                /* right cylinder */
                Transform3D RT3D = new Transform3D();
                RT3D.setTranslation(new Vector3f(0.1f,0.3f,0.0f));
                TransformGroup RTG = new TransformGroup(RT3D);
        	
                rcyl = new Cylinder(0.05f,0.4f);
                RTG.addChild(rcyl);

        	
                /* TransformGroup for rotation */
                transAll = new TransformGroup();
                transAll.setCapability(transAll.ALLOW_TRANSFORM_WRITE);
                transAll.setCapability(transAll.ALLOW_TRANSFORM_READ);

                transAll.addChild(LTG);
                transAll.addChild(RTG);
                root.addChild(transAll);
        	
                /* Collision Detection */
                CollBehavior sb = new CollBehavior(lcyl);
                sb.setSchedulingBounds(new BoundingSphere(new Point3d(),100.0d));
                transAll.addChild(sb);

                return root;
        }
	
        private Appearance makeAppearance() {
        	
                Appearance a = new Appearance();
        	
                ColoringAttributes ca = new ColoringAttributes();
                ca.setColor(new Color3f(Color.red));
                ca.setCapability(ca.ALLOW_COLOR_READ);
                ca.setCapability(ca.ALLOW_COLOR_WRITE);
        	
                a.setColoringAttributes(ca);
        	
                return a;
        }
	
        public static void main(String[] Args) {
                new MainFrame(new Buggy2(),640,480);
        }
	
        private void setCircum() {
        	
        AmbientLight a = new AmbientLight(new Color3f(Color.white));
        a.setInfluencingBounds(new BoundingSphere(new Point3d(0,0,0),100.0d));
        myBranch.addChild(a);
	
        DirectionalLight d = new DirectionalLight();
        d.setInfluencingBounds(new BoundingSphere(new Point3d(0,0,0),100.0f));
        Vector3f myVektor = new Vector3f(-1,-1,-1);
        myVektor.normalize();
        d.setDirection(myVektor);
        d.setColor(new Color3f(Color.white));
        myBranch.addChild(d);
        }
	
        /* add the possibility for interaction */
        private void addMouseReaction() {
        	
                /* rotate */
                MouseRotate myMouseRotate = new MouseRotate(transAll);
                myMouseRotate.setSchedulingBounds(new BoundingSphere());
                myBranch.addChild(myMouseRotate);
        	
                /* scale */
                MouseZoom myMouseZoom = new MouseZoom(transAll);
                myMouseZoom.setSchedulingBounds(new BoundingSphere());
                myBranch.addChild(myMouseZoom);
        	
                /* translate */
                MouseTranslate myMouseTranslate = new MouseTranslate(transAll);
                myMouseTranslate.setSchedulingBounds(new BoundingSphere());
                myBranch.addChild(myMouseTranslate);
        }
	

class CollBehavior extends Behavior {

        Primitive shape;
        private ColoringAttributes ca;
        private WakeupOnCollisionEntry cEntry;
        private WakeupOnCollisionExit cExit;
	
        CollBehavior(Primitive bs) {

                Appearance app = bs.getAppearance();
                this.shape = bs;                      	
                this.ca = app.getColoringAttributes();
        }
	
        public void initialize() {
                cEntry = new WakeupOnCollisionEntry(shape, WakeupOnCollisionEntry.USE_GEOMETRY);
                cExit = new WakeupOnCollisionExit(shape, WakeupOnCollisionExit.USE_GEOMETRY);
                	
                wakeupOn(cEntry);
        }
	
        public void processStimulus(Enumeration criteria) {
        	
                WakeupCriterion event = (WakeupCriterion) criteria.nextElement();
        	
                if (event==cEntry) {
                        this.ca.setColor(0.0f,0.0f,1.0f);
                        this.wakeupOn(cExit);
                } else  	
                if (event==cExit) {
                                this.ca.setColor(1.0f,0.0f,0.0f);
                                this.wakeupOn(cEntry);
                }	
        }
}
}
