import java.awt.*;
import java.awt.event.*;
import java.util.Enumeration;
import javax.vecmath.*;
import javax.media.j3d.*;

class PickingDemo extends Frame
{
	public static void main(String[] args)
	{
		new PickingDemo();
	}

	public PickingDemo()
	{
		setTitle("PickDemo - Press the mouse");
		setLayout(new BorderLayout());
		Canvas3D c = new Canvas3D(null);
		add("Center", c);

		UniverseBuilder u = new UniverseBuilder(c);
		BranchGroup scene = createSceneGraph(c);
		u.addBranchGraph(scene);

		setSize(300,270);
		show();
	}

	public BranchGroup createSceneGraph(Canvas3D canvas3D)
	{
		BranchGroup branchGroup = new BranchGroup();

		Transform3D transform3D1 = new Transform3D();
		Transform3D transform3D2 = new Transform3D();
		transform3D1.set(1.0f,new Vector3f(0.0f,1.6f,0.0f));
		transform3D2.set(1.0f,new Vector3f(0.0f,0.2f,0.0f));
	
		TransformGroup transformGroup1 = new TransformGroup(transform3D1);
		TransformGroup transformGroup2 = new TransformGroup(transform3D2);


		Font3D font3d = new Font3D(new Font("TestFont", Font.PLAIN, 1),new FontExtrusion());        

		Appearance appearance1 = new Appearance();
		Material material1 = new Material();
		material1.setAmbientColor(new Color3f(1.0f,0.0f,0.0f));
		material1.setDiffuseColor(new Color3f(0.5f,0.0f,0.0f));
		appearance1.setMaterial(material1);
		Text3D text3D1 = new Text3D(font3d, new String("CLICK1"),new Point3f(0.0f, -1.0f, 0.0f),Text3D.ALIGN_CENTER,Text3D.PATH_RIGHT);		
		Shape3D shape3D1 = new Shape3D(text3D1,appearance1);
		shape3D1.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
		appearance1.setCapability(Appearance.ALLOW_MATERIAL_READ);
		material1.setCapability(Material.ALLOW_COMPONENT_READ);
		material1.setCapability(Material.ALLOW_COMPONENT_WRITE);


		Appearance appearance2 = new Appearance();
		Material material2 = new Material();
		material2.setAmbientColor(new Color3f(0.0f,1.0f,0.0f));
		material2.setDiffuseColor(new Color3f(0.5f,1.0f,0.0f));
		appearance2.setMaterial(material2);
		Text3D text3D2 = new Text3D(font3d, new String("CLICK2"),new Point3f(0.0f, -1.0f, 0.0f),Text3D.ALIGN_CENTER,Text3D.PATH_RIGHT);
		Shape3D shape3D2 = new Shape3D(text3D2,appearance2);
		shape3D2.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
		appearance2.setCapability(Appearance.ALLOW_MATERIAL_READ);
		material2.setCapability(Material.ALLOW_COMPONENT_READ);
		material2.setCapability(Material.ALLOW_COMPONENT_WRITE);

		PickBehavior pickBehavior = new PickBehavior(branchGroup,canvas3D,shape3D1,shape3D2);	
		BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
		pickBehavior.setSchedulingBounds(bounds);
		

		AmbientLight ambientLight = new AmbientLight(new Color3f(0.6f,0.6f,0.6f));
		ambientLight.setInfluencingBounds(bounds);
	
		DirectionalLight directionalLight = new DirectionalLight(new Color3f(1.0f,1.0f,1.0f),new Vector3f(0.0f,0.0f,-1.0f));
		directionalLight.setInfluencingBounds(bounds);

		transformGroup1.addChild(shape3D1);
		transformGroup2.addChild(shape3D2);
		branchGroup.addChild(transformGroup1);
		branchGroup.addChild(transformGroup2);
		branchGroup.addChild(ambientLight);
		branchGroup.addChild(directionalLight);	
		branchGroup.addChild(pickBehavior);
		return branchGroup;
	}
}

class UniverseBuilder extends Object
{
	Locale			locale;

	UniverseBuilder(Canvas3D c)
	{
		Transform3D t = new Transform3D();
		Transform3D t2 = new Transform3D();
		t2.setEuler( new Vector3d(-30.0*(Math.PI/180.0),22.5*(Math.PI/180.0),0.0));
		t.set(4,new Vector3d(2.0,3.0,4.0));
		t.mul(t,t2);


		VirtualUniverse	universe = new VirtualUniverse();
		locale = new Locale(universe);

		PhysicalBody body = new PhysicalBody();
		PhysicalEnvironment environment = new PhysicalEnvironment();
		BranchGroup viewPlatformBranchGroup = new BranchGroup();
		TransformGroup viewPlatformTransformGroup = new TransformGroup(t);
		ViewPlatform viewPlatform = new ViewPlatform();

		View view = new View();
		view.addCanvas3D(c);
		view.setPhysicalBody(body);
		view.setPhysicalEnvironment(environment);
		view.attachViewPlatform(viewPlatform);
		
		viewPlatformTransformGroup.addChild(viewPlatform);
		viewPlatformBranchGroup.addChild(viewPlatformTransformGroup);
		locale.addBranchGraph(viewPlatformBranchGroup);
	}

	void addBranchGraph(BranchGroup bg)
	{
		locale.addBranchGraph(bg);
	}
}


class PickBehavior extends Behavior 
{
	WakeupCriterion mouseCriterion;
	BranchGroup branchGroup;	
	Canvas3D canvas3D;
	Shape3D shape3D1, shape3D2;

	public PickBehavior(BranchGroup branchGroup, Canvas3D canvas3D, Shape3D shape3D1, Shape3D shape3D2)
	{
		this.branchGroup = branchGroup;		
		this.canvas3D = canvas3D;
		this.shape3D1 = shape3D1;
		this.shape3D2 = shape3D2;
	}

	public void initialize() 
	{
		mouseCriterion = new WakeupOnAWTEvent(MouseEvent.MOUSE_PRESSED);    

		System.out.println("Initialize");
		wakeupOn (mouseCriterion);
	}

	public void processStimulus (Enumeration criteria) 
	{
		AWTEvent[] event = ((WakeupOnAWTEvent)criteria.nextElement()).getAWTEvent();
		for (int i=0; i<event.length; i++) 
		{ 
			int x = ((MouseEvent)event[i]).getX();
			int y = ((MouseEvent)event[i]).getY();

			PickRay pickRay = generatePickRay(x,y);					
			SceneGraphPath sceneGraphPath = branchGroup.pickAny(pickRay);
			Shape3D actualShape3D = (Shape3D)sceneGraphPath.getObject();			
			
			if (actualShape3D.equals(shape3D1))
			{
				Appearance appearance1 = shape3D1.getAppearance();
				Material material1 = appearance1.getMaterial();
				material1.setAmbientColor(new Color3f(1.0f,0.0f,0.0f));
				material1.setDiffuseColor(new Color3f(0.5f,0.0f,0.0f));

				Appearance appearance2 = shape3D2.getAppearance();
				Material material2 = appearance2.getMaterial();
				material2.setAmbientColor(new Color3f(0.0f,1.0f,0.0f));
				material2.setDiffuseColor(new Color3f(0.5f,1.0f,0.0f));
			}
			else 
			{
				Appearance appearance1 = shape3D1.getAppearance();
				Material material1 = appearance1.getMaterial();
				material1.setAmbientColor(new Color3f(0.0f,1.0f,0.0f));
				material1.setDiffuseColor(new Color3f(0.5f,1.0f,0.0f));				

				Appearance appearance2 = shape3D2.getAppearance();
				Material material2 = appearance2.getMaterial();
				material2.setAmbientColor(new Color3f(1.0f,0.0f,0.0f));
				material2.setDiffuseColor(new Color3f(0.5f,0.0f,0.0f));
			}				

		System.out.println("generate pickray");
		System.out.println(sceneGraphPath);

		}

		wakeupOn(mouseCriterion);
	}

	public PickRay generatePickRay(int xpos, int ypos)    
	{
		Transform3D motion=new Transform3D();
		Point3d eyePosn = new Point3d();
		Point3d mousePosn = new Point3d();
		Vector3d mouseVec=new Vector3d();
		canvas3D.getCenterEyeInImagePlate(eyePosn);
		canvas3D.getPixelLocationInImagePlate(xpos,ypos,mousePosn);
		canvas3D.getImagePlateToVworld(motion);

		motion.transform(eyePosn);
		motion.transform(mousePosn);
		mouseVec.sub(mousePosn, eyePosn);
		mouseVec.normalize();

		return new PickRay(eyePosn, mouseVec);
	}


} //class

