import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.behaviors.keyboard.*;
import com.sun.j3d.utils.behaviors.mouse.*;

import java.awt.*;
import javax.swing.*;
import javax.media.j3d.*;
import javax.vecmath.*;

public class Java3DTest extends JDialog {
  private Canvas3D canvas3D = null;

  public Java3DTest() {
    super(new Frame(), "Java 3D Test", false);
  }

  public void init() {
    setSize(new Dimension(600, 400));
    getContentPane().setLayout(new BorderLayout());

    GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
    canvas3D = new Canvas3D(config);
    canvas3D.setDoubleBufferEnable(true);
    getContentPane().add(canvas3D, null);

    SimpleUniverse universe = new SimpleUniverse(canvas3D);
    universe.getViewingPlatform().setNominalViewingTransform();

    BranchGroup scene = createSceneGraph(universe);
    scene.compile();

    universe.addBranchGraph(scene);
  }

  private BranchGroup createSceneGraph(SimpleUniverse universe) {
    BranchGroup sceneRoot = new BranchGroup();

    // Add content.
    TransformGroup contentRoot = new TransformGroup();
    contentRoot.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
    contentRoot.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    sceneRoot.addChild(contentRoot);
    createContent(contentRoot);

    BoundingSphere boundingSphere = new BoundingSphere(new Point3d(), 1000.0);

    // Rotation by MOUSE of model
    MouseRotate mouseRotate = new MouseRotate();
    mouseRotate.setTransformGroup(contentRoot);
    mouseRotate.setSchedulingBounds(boundingSphere);
    sceneRoot.addChild(mouseRotate);

    // Movement of whole view by MOUSE
    MouseTranslate mouseTranslate = new MouseTranslate(MouseBehavior.INVERT_INPUT);
    mouseTranslate.setTransformGroup(universe.getViewingPlatform().getViewPlatformTransform());
    mouseTranslate.setSchedulingBounds(boundingSphere);
    sceneRoot.addChild(mouseTranslate);

    // Zooming of whole view by MOUSE
    MouseZoom mouseZoom = new MouseZoom(MouseBehavior.INVERT_INPUT);
    mouseZoom.setTransformGroup(universe.getViewingPlatform().getViewPlatformTransform());
    mouseZoom.setSchedulingBounds(boundingSphere);
    sceneRoot.addChild(mouseZoom);

    // Directional lighting.
    DirectionalLight light = new DirectionalLight();
    light.setInfluencingBounds(boundingSphere);
    sceneRoot.addChild(light);

    return sceneRoot;
  }

  private void createContent(TransformGroup contentRoot) {
    // Shared group (red cylinder).
    Appearance appearance = new Appearance();
    Material material = new Material(new Color3f(1.0f, 0.0f, 0.0f), new Color3f(0.0f, 0.0f, 0.0f), new Color3f(1.0f, 0.0f, 0.0f), new Color3f(1.0f, 1.0f, 1.0f), 64.0f);
    material.setLightingEnable(true);
    appearance.setMaterial(material);

    float radius = 0.2f;
    float height = 0.01f;
    SharedGroup sharedGroup = new SharedGroup();
    sharedGroup.addChild(new Cylinder(radius, height, Cylinder.GENERATE_NORMALS, appearance));
    Transform3D translate = new Transform3D();

    for(int i = 0; i < 100; i++) {
      Vector3d translation = new Vector3d(0.0, height * i, 0.0);
      translate.setTranslation(translation);
      TransformGroup node = new TransformGroup(translate);
      node.addChild(new Link(sharedGroup));
      contentRoot.addChild(node);
    }
  }

  public static void main(String[] args) {
    Java3DTest dialog = new Java3DTest();
    dialog.init();
    dialog.show();
  }
}
