/*
 *      @(#)SimpleVrml97Viewer.java 1.6 98/09/18 14:58:38
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
 * modify and redistribute this software in source and binary code form,
 * provided that i) this copyright notice and license appear on all copies of
 * the software; and ii) Licensee does not utilize the software in a manner
 * which is disparaging to Sun.
 *
 * 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.
 *
 * This software is not designed or intended for use in on-line control of
 * aircraft, air traffic, aircraft navigation or aircraft communications; or in
 * the design, construction, operation or maintenance of any nuclear
 * facility. Licensee represents and warrants that it will not use or
 * redistribute the Software for such purposes.
 *
 * @Author: Doug Gehringer
 * @Author: Rick Goldberg
 */



import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
import com.sun.j3d.utils.behaviors.mouse.MouseTranslate;
import javax.media.j3d.*;
import javax.vecmath.*;
import java.net.URL;
import java.net.MalformedURLException;

import com.sun.j3d.loaders.vrml97.VrmlLoader;
import com.sun.j3d.loaders.Scene;


public class SimpleVrml97Viewer extends Applet implements ActionListener {

    String   		location;
    Canvas3D		canvas;
    SimpleUniverse	universe;
    TransformGroup	vpTransGroup;
    VrmlLoader		loader;
    View		view;
    Panel		panel;
    Label		label;
    BranchGroup		sceneRoot;
    TransformGroup	examineGroup;
    BranchGroup		sceneGroup;
    BoundingSphere	sceneBounds;
    DirectionalLight	headLight;
    AmbientLight	ambLight;
    TextField 		textField;
    Cursor		waitCursor;
    Cursor		handCursor;

    SimpleVrml97Viewer(String initLocation) {
	setLayout(new BorderLayout());
	canvas = new Canvas3D(null);
	add("Center",canvas);

	panel = new Panel();
	panel.setLayout(new FlowLayout(FlowLayout.LEFT));
	textField = new TextField(initLocation,60);	
	textField.addActionListener(this);
	label = new Label("Location:");
	panel.add(label);
	panel.add(textField);
	add("North",panel);

	waitCursor = new Cursor(Cursor.WAIT_CURSOR);
	handCursor = new Cursor(Cursor.HAND_CURSOR);

	universe = new SimpleUniverse(canvas);
	ViewingPlatform viewingPlatform = universe.getViewingPlatform();
	vpTransGroup = viewingPlatform.getViewPlatformTransform();
	Viewer viewer = universe.getViewer();
	view = viewer.getView();

	setupBehavior();

	loader = new VrmlLoader();

	gotoLocation(initLocation);

    }

    public void actionPerformed(ActionEvent ae) {
	gotoLocation(textField.getText());
    }

    void gotoLocation(String location) {

	canvas.setCursor(waitCursor);

	if (sceneGroup != null) {
	    sceneGroup.detach();
	}
	Scene scene = null;
	try {
	    URL loadUrl = new URL(location);
	    try {
		// load the scene
		scene = loader.load(new URL(location));
	    } catch (Exception e) {
		System.out.println("Exception loading URL:" + e);
	    }
	} catch (MalformedURLException badUrl) {
	    // location may be a path name	
	    try {
		// load the scene
		scene = loader.load(location);
	    } catch (Exception e) {
		System.out.println("Exception loading file from path:" + e);
	    }
	}
	if (scene != null) {
	    // get the scene group
	    sceneGroup = scene.getSceneGroup();
	    sceneGroup.setCapability(BranchGroup.ALLOW_DETACH);
	    sceneGroup.setCapability(BranchGroup.ALLOW_BOUNDS_READ);

	    // add the scene group  to the scene
	    examineGroup.addChild(sceneGroup);

	    // now that the scene group is "live" we can inquire the bounds
	    sceneBounds = (BoundingSphere)sceneGroup.getBounds();

	    // set up a viewpoint to include the bounds
	    setViewpoint();
	}

	canvas.setCursor(handCursor);
    }

    void setViewpoint() {
	Transform3D viewTrans = new Transform3D();
	Transform3D eyeTrans = new Transform3D();

	// point the view at the center of the object
	Point3d center = new Point3d();
	sceneBounds.getCenter(center);
	double radius = sceneBounds.getRadius();
	Vector3d temp = new Vector3d(center);
	viewTrans.set(temp);

	// pull the eye back far enough to see the whole object
	double eyeDist = 1.4*radius / Math.tan(view.getFieldOfView() / 2.0);
	temp.x = 0.0;
	temp.y = 0.0;
	temp.z = eyeDist;
	eyeTrans.set(temp);
	viewTrans.mul(eyeTrans);

	// set the view transform 
	vpTransGroup.setTransform(viewTrans);
    }


    private void setupBehavior() {
	sceneRoot = new BranchGroup();

	examineGroup = new TransformGroup();
	examineGroup.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
	examineGroup.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
	examineGroup.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
	examineGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
	examineGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
	sceneRoot.addChild(examineGroup);

	BoundingSphere behaviorBounds = new BoundingSphere(new Point3d(),
		Double.MAX_VALUE);

	MouseRotate mr = new MouseRotate();
	mr.setTransformGroup(examineGroup);
	mr.setSchedulingBounds(behaviorBounds);
	sceneRoot.addChild(mr);

	MouseTranslate mt = new MouseTranslate();
	mt.setTransformGroup(examineGroup);
	mt.setSchedulingBounds(behaviorBounds);
	sceneRoot.addChild(mt);

	MouseZoom mz = new MouseZoom();
	mz.setTransformGroup(examineGroup);
	mz.setSchedulingBounds(behaviorBounds);
	sceneRoot.addChild(mz);

	BoundingSphere lightBounds =
	new BoundingSphere(new Point3d(), Double.MAX_VALUE);
        ambLight = new AmbientLight(true, new Color3f(1.0f, 1.0f, 1.0f));
        ambLight.setInfluencingBounds(lightBounds);
        ambLight.setCapability(Light.ALLOW_STATE_WRITE);
        sceneRoot.addChild(ambLight);
        headLight = new DirectionalLight();
        headLight.setCapability(Light.ALLOW_STATE_WRITE);
        headLight.setInfluencingBounds(lightBounds);
        sceneRoot.addChild(headLight);


	universe.addBranchGraph(sceneRoot);
    }



    public static void main(String[] args) {
	String locString = null;
	if (args.length == 0) {
	    locString = System.getProperties().getProperty("user.dir") +
		"/parts/simple.wrl";
	} else {
	    if (args.length != 1) {
		System.out.println("Usage: SimpleVrml97Viewer [pathname|URL]");
		System.exit(0);
	    } else {
		locString = args[0];
	    }
	}

        new MainFrame(new SimpleVrml97Viewer(locString), 780, 780);
    }

}

