import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.geometry.Cylinder;
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.event.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import java.io.*;
import java.util.*;
import javax.media.j3d.*;
import javax.vecmath.*;

import java.lang.Math;

/**
 * scene : petit programme de test de Java 3D.
 */


public class SmallScene extends Applet {

    //public TransformGroup robot;              // robot node

    Sonar[] sonars = new Sonar[16];
    SceneGraphPath[] scgr = new SceneGraphPath[16];


    //--------------------------------------------------------------
    public void initSceneGraphPath()
    {
        System.out.println("Start initializing SceneGraphPath array...");
	for (int i = 0; i < 16; i++) {
	    scgr[i] = new SceneGraphPath();
	}
	System.out.println("SceneGraphPath has been initialized...");
    }

    //--------------------------------------------------------------
    public void initSonars()
    {
      System.out.println("Start initializing sonar array...");
      for (int i = 0 ; i < 16; i++) {
	  //System.out.println("     processing element :  " + i);
	  sonars[i] = new Sonar();
	  //sonars[i].pos = new Point3d(0.0, 0.0, 0.0);
	  
	  sonars[i].pos = new Point3d(1.01 * Math.cos((i * Math.PI * 2.0) / 16.0),
	  			      0.0,
	  			      1.01 * Math.sin((i * Math.PI * 2.0) / 16.0));
	  //System.out.println("          start position ok ");
	  sonars[i].dir = new Vector3d(Math.cos((i * Math.PI * 2.0) / 16.0),
				       0.0,
				       Math.sin((i * Math.PI * 2.0) / 16.0));
	  //System.out.println("          direction vector ok !");
      }
      System.out.println("Sonar array has been initialized...");
    }

    //--------------------------------------------------------------
    public TransformGroup CreateBox (Color3f color, 
				     Vector3d translation,
				     Vector3d scaling)
    {
        //Create a box.
        Material objMaterial = new Material();        
	objMaterial.setDiffuseColor(color);
	Appearance objAppearance = new Appearance();  
	objAppearance.setMaterial(objMaterial);

	TransformGroup boxTrans = new TransformGroup();
	Transform3D boxShift = new Transform3D();
	boxShift.setTranslation(translation);
	boxShift.setScale(scaling);
	boxTrans.setTransform(boxShift);
	Box boxObj = new Box();
	boxObj.setAppearance(objAppearance);
	boxObj.setCapability(Geometry.ALLOW_INTERSECT);
	boxObj.setPickable(true);
	boxObj.setCapability(Node.ENABLE_PICK_REPORTING);
	boxTrans.setCapability(Node.ENABLE_PICK_REPORTING);
	boxTrans.addChild(boxObj);
	return(boxTrans);
    }

    //------------------------------------------------------------
    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.2);
	objScale.setTransform(t3d);
	objScale.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
	objRoot.addChild(objScale);
	objRoot.setCapability(TransformGroup.ENABLE_PICK_REPORTING);

	Material objMaterial = new Material();        
	objMaterial.setDiffuseColor(new Color3f(1.0f, 1.0f, 1.0f));
	Appearance objAppearance = new Appearance();  
	objAppearance.setMaterial(objMaterial);


	// This Transformgroup is used by the mouse manipulators to
	// move the Box.
	TransformGroup objTrans = new TransformGroup();
	objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
	objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
	objTrans.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
	objScale.addChild(objTrans);

	// Create first box
	objTrans.addChild(CreateBox (new Color3f(0.8f, 0.8f, 0.9f),      // color of cube
				      new Vector3d(-10.0, -1.0, -10.0),   // translation
				      new Vector3d(0.4, 2.0, 20.0)));     // scaling
	// Create second box
	objTrans.addChild(CreateBox (new Color3f(0.5f, 0.8f, 0.9f),
				      new Vector3d(10.0, 0.0, 0.0), 
				      new Vector3d(0.2, 1.0, 10.0)));
	// Create third box
	objTrans.addChild(CreateBox (new Color3f(0.5f, 0.8f, 0.9f),
				      new Vector3d(0.0, 0.0, -10.0),
				      new Vector3d(10.0, 1.0, 0.2)));
	// Create fourth box
	objTrans.addChild(CreateBox (new Color3f(0.5f, 0.8f, 0.9f),
				      new Vector3d(0.0, 0.0, 10.0),
				      new Vector3d(10.0, 1.0, 0.2)));

	BoundingSphere bounds =
	    new BoundingSphere(new Point3d(0.0,0.0,0.0), 1000.0);
  
      
	// Create the rotate behavior node
	MouseRotate behavior = new MouseRotate(objTrans);
	objTrans.addChild(behavior);
	behavior.setSchedulingBounds(bounds);

	// Create the zoom behavior node
	MouseZoom behavior2 = new MouseZoom(objTrans);
	objTrans.addChild(behavior2);
	behavior2.setSchedulingBounds(bounds);
    

	//Shine it with two colored lights.
	Color3f lColor1 = new Color3f(1.0f, 1.0f, 1.0f);
	Color3f lColor2 = new Color3f(1.0f, 1.0f, 1.0f);
	Vector3f lDir1  = new Vector3f(-1.0f, -1.0f, -1.0f);
	Vector3f lDir2  = new Vector3f(0.0f, 0.0f, -1.0f);
	DirectionalLight lgt1 = new DirectionalLight(lColor1, lDir1);
	DirectionalLight lgt2 = new DirectionalLight(lColor2, lDir2);
	
	AmbientLight algt = new AmbientLight();

	lgt1.setInfluencingBounds(bounds);
	lgt2.setInfluencingBounds(bounds);
	algt.setInfluencingBounds(bounds);
	//objScale.addChild(lgt1);
	objScale.addChild(lgt2);
	objScale.addChild(algt);

	// Let Java 3D perform optimizations on this scene graph.
	objRoot.compile();

	return objRoot;
    }
  
    //--------------------------------------------------------------
  
    //--------------------------------------------------------------
    public SmallScene ()
    {
        setLayout(new BorderLayout());
	Canvas3D c = new Canvas3D(null);
	add("Center", c);
    
	Shape3D  hitObj = new Shape3D();

	this.initSonars();
	this.initSceneGraphPath();

	// Create a simple scene and attach it to the virtual universe
	BranchGroup scene = createSceneGraph();
	SimpleUniverse 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);

	PickRay pick;
	boolean isHit  = false;
	Node hitShape;
	for (int i = 0; i < 16; i++)
	{ 
	    System.out.println("Initializing pick ray for sonar["+i+"]...");
	    pick = new PickRay(sonars[i].pos, sonars[i].dir);
	    scgr[i] = scene.pickClosest(pick);
	    System.out.println(" pick ray for sonar["+i+"] initialized ...");
	    
	    if (scgr[i] == null) {
	      System.out.println("Scene graph for index " + i + "is null ");
	    } else {
	        System.out.println("Scene graphPath : " + scgr[i].toString() );
		System.out.println();
		try {
		    if (scgr[i] != null) {
			hitShape = scgr[i].getObject();
		    
			if (hitShape instanceof Shape3D) {
			    System.out.println("You have found a Shape3D object !!");
			    isHit= ((Shape3D)hitShape).intersect(scgr[i], pick, sonars[i].dist);
			    if (isHit) {
				System.out.println("Distance to shape " + sonars[i].dist);
			    }			    
			} else {
			    System.out.println("This node is not a Shape3D !!");
			}
		    }
		} catch (CapabilityNotSetException e) {
		    System.out.println ("Illegal operation on object[" + i + "] : " + e);
		}
	    }
	    System.out.println();
	}
    }
  
  
    //--------------------------------------------------------------
    //--------------------------------------------------------------
    public static void main(String argv[])
    {
    
        BranchGroup group;
    
	new MainFrame(new scene(), 700, 700);
    }
}

