import com.borland.jbcl.layout.*;
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 objRoot = new BranchGroup();

    // Mouse rotation transform group.
    TransformGroup objRotate = new TransformGroup();
    objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
    objRoot.addChild(objRotate);

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

    // Mouse rotation.
    MouseRotate myMouseRotate = new MouseRotate(MouseBehavior.INVERT_INPUT);
    myMouseRotate.setTransformGroup(objRotate);
    myMouseRotate.setSchedulingBounds(boundingSphere);
    objRoot.addChild(myMouseRotate);

    // Mouse translation.
    TransformGroup viewPlatformTransform = universe.getViewingPlatform().getViewPlatformTransform();
    MouseTranslate myMouseTranslate = new MouseTranslate(MouseBehavior.INVERT_INPUT);
    myMouseTranslate.setTransformGroup(viewPlatformTransform);
    myMouseTranslate.setSchedulingBounds(boundingSphere);
    objRoot.addChild(myMouseTranslate);

    // Mouse zoom.
    MouseZoom myMouseZoom = new MouseZoom(MouseBehavior.INVERT_INPUT);
    myMouseZoom.setTransformGroup(viewPlatformTransform);
    myMouseZoom.setSchedulingBounds(boundingSphere);
    objRoot.addChild(myMouseZoom);

    // Directional lighting: lightOn = true; color = white; direction: towards -z.
    DirectionalLight directionalLight = new DirectionalLight();
    directionalLight.setInfluencingBounds(boundingSphere);
    objRoot.addChild(directionalLight);

    createContent(objRotate);

    return objRoot;
  }

  private void createContent(TransformGroup contentRoot) {
    // Shared appearance (red).
    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);
    Transform3D translate = new Transform3D();

    // Create 2160 (3x72x10) nodes.
    // Each node consists of a transform group and a red sphere shape.
    for(int i = 0; i < 3; i++) {
      for(int j = 0; j < 72; j++) {
        TransformGroup parent = contentRoot;

        double angle = j * Math.PI / 36.0;
        Vector3d translation = new Vector3d(0.03 * Math.cos(angle), 0.03 * Math.sin(angle), -0.01 * i);
        translate.setTranslation(translation);

        for(int k = 0; k < 10; k++) {
          TransformGroup node = new TransformGroup(translate);
          parent.addChild(node);
          node.addChild(new Sphere(0.01f, Sphere.GENERATE_NORMALS, 10, appearance));
          parent = node;
        }
      }
    }
  }

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