3D Graphics Java

/*******************************************************************************
 *                      Copyright (c) 1999 Justin Couch
 *                               Java Source
 *
 * Raw J3D Tutorial
 *
 * Version History
 * Date        Version  Programmer
 * ----------  -------  ------------------------------------------
 * 01/08/1998  1.0.0    Justin Couch
 *
 ******************************************************************************/
// no package
// Standard imports
import java.awt.Component;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.ColoringAttributes;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.GraphicsConfigTemplate3D;
import javax.media.j3d.Group;
import javax.media.j3d.ImageComponent;
import javax.media.j3d.ImageComponent2D;
import javax.media.j3d.IndexedQuadArray;
import javax.media.j3d.Light;
import javax.media.j3d.Locale;
import javax.media.j3d.Material;
import javax.media.j3d.Node;
import javax.media.j3d.PhysicalBody;
import javax.media.j3d.PhysicalEnvironment;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Texture;
import javax.media.j3d.Texture2D;
import javax.media.j3d.TextureAttributes;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.media.j3d.ViewPlatform;
import javax.media.j3d.VirtualUniverse;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.vecmath.AxisAngle4f;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;
// Application specific imports
// none
/**
 * Test frame class for the dealing with J3D experimentation that uses Swing
 * 


 * Basic window consists of a menubar and a J3D window
 * 
 * @author Justin Couch
 * @version Who Cares!
 */
public class J3dSwingFrame extends JFrame implements ActionListener {
  private JMenuItem close_menu;
  private Canvas3D canvas;
  private UniverseManager universe;
  /**
   * Construct the test frame with a menubar and 3D canvas
   */
  public J3dSwingFrame() {
    super("Java3D Tester");
    // Disable lightweight menus
    JPopupMenu.setDefaultLightWeightPopupEnabled(false);
    JMenuBar menubar = new JMenuBar();
    // File menu
    JMenu file_menu = new JMenu("File");
    menubar.add(file_menu);
    close_menu = new JMenuItem("Exit");
    close_menu.addActionListener(this);
    file_menu.add(close_menu);
    setJMenuBar(menubar);
    GraphicsConfigTemplate3D template = new GraphicsConfigTemplate3D();
    GraphicsEnvironment env = GraphicsEnvironment
        .getLocalGraphicsEnvironment();
    GraphicsDevice device = env.getDefaultScreenDevice();
    GraphicsConfiguration config = device.getBestConfiguration(template);
    canvas = new Canvas3D(config);
    // add the canvas to this frame. Since this is the only thing added to
    // the main frame we don't care about layout managers etc.
    getContentPane().add(canvas, "Center");
    constructWorld();
    setSize(600, 600);
  }
  /**
   * Construct everything that we want in the basic test world
   */
  private void constructWorld() {
    // create the basic universe
    universe = new UniverseManager();
    /*
     * // create a light grey coloured background Background bg = new
     * Background(0.5f, 0.5f, 0.5f); BoundingSphere bounds = new
     * BoundingSphere(); bounds.setRadius(1000);
     * bg.setApplicationBounds(bounds); universe.addWorldObject(bg);
     */
    Camera cam = new Camera();
    Vector3f loc = new Vector3f(0, 0, 10.0f);
    cam.setLocation(loc);
    cam.setHeadLight(true);
    universe.addCamera(cam);
    cam.setCanvas(canvas);
    // add some geometry
    ExampleGeometry geom = new ExampleGeometry();
    universe.addWorldObject(geom);
    universe.makeLive();
  }
  /**
   * An mouse action has occurred. Used to process menu item selection.
   * 
   * @param evt
   *            The event that caused this method to be called.
   */
  public void actionPerformed(ActionEvent evt) {
    Object src = evt.getSource();
    if (src == close_menu)
      System.exit(0);
  }
  /**
   * Start the application....
   */
  public static void main(String[] args) {
    Frame frame = new J3dSwingFrame();
    frame.setVisible(true);
  }
}
/*******************************************************************************
 * Copyright (c) 1999 Justin Couch Java Source
 * 
 * Raw J3D Tutorial
 * 
 * Version History Date Version Programmer ---------- -------
 * ------------------------------------------ 01/08/1998 1.0.0 Justin Couch
 *  
 ******************************************************************************/
// no package
// Application specific imports
// none
/**
 * Test class for representing a universe
 * 


 * Basic universe consisting of a default Locale and three branch graphs for
 * objects that exist in the display and world spaces, as well as a separate
 * branch for cameras.
 * 
 * @author Justin Couch
 * @version Who Cares!
 */
class UniverseManager extends VirtualUniverse {
  private Locale locale;
  private BranchGroup view_group;
  private BranchGroup world_object_group;
  /**
   * Create the basic universe and all of the supporting infrastructure that
   * is needed by a J3D application. The default setup just uses a single
   * local located at the origin.
   */
  public UniverseManager() {
    locale = new Locale(this);
    view_group = new BranchGroup();
    view_group.setCapability(Group.ALLOW_CHILDREN_EXTEND);
    world_object_group = new BranchGroup();
    world_object_group.setCapability(Group.ALLOW_CHILDREN_EXTEND);
  }
  /**
   * Add a camera to the world.
   * 
   * @param cam
   *            The camera that may be added
   */
  public void addCamera(Camera cam) {
    view_group.addChild(cam.getNode());
  }
  /**
   * Add an object to the world object group.
   * 
   * @param node
   *            The node that may be added
   */
  public void addWorldObject(Node node) {
    world_object_group.addChild(node);
  }
  /**
   * Make the universe live by adding the objects to the locale
   */
  public void makeLive() {
    view_group.compile();
    world_object_group.compile();
    locale.addBranchGraph(view_group);
    locale.addBranchGraph(world_object_group);
  }
}
/*******************************************************************************
 * Copyright (c) 1999 Justin Couch Java Source
 * 
 * Raw J3D Tutorial
 * 
 * Version History Date Version Programmer ---------- -------
 * ------------------------------------------ 01/08/1998 1.0.0 Justin Couch
 *  
 ******************************************************************************/
// Application specific imports
// none
/**
 * Test class for showing the use of a View and ViewPlatform
 * 


 * Basic view consists of the standard placement.
 * 
 * @author Justin Couch
 * @version Who Cares!
 */
class Camera {
  private static final double BACK_CLIP_DISTANCE = 100.0;
  private static final Color3f White = new Color3f(1, 1, 1);
  private static final BoundingSphere LIGHT_BOUNDS;
  private Group hud_group;
  private TransformGroup root_tx_grp;
  private Transform3D location;
  private ViewPlatform platform;
  private View view;
  private DirectionalLight headlight;
  private PhysicalBody body;
  private PhysicalEnvironment env;
  static {
    Point3d origin = new Point3d(0, 0, 0);
    LIGHT_BOUNDS = new BoundingSphere(origin, BACK_CLIP_DISTANCE);
  }
  public Camera() {
    hud_group = new Group();
    hud_group.setCapability(Group.ALLOW_CHILDREN_EXTEND);
    platform = new ViewPlatform();
    location = new Transform3D();
    root_tx_grp = new TransformGroup();
    root_tx_grp.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    root_tx_grp.setTransform(location);
    root_tx_grp.addChild(platform);
    root_tx_grp.addChild(hud_group);
    // now create the headlight
    headlight = new DirectionalLight();
    headlight.setCapability(Light.ALLOW_STATE_WRITE);
    headlight.setColor(White);
    headlight.setInfluencingBounds(LIGHT_BOUNDS);
    root_tx_grp.addChild(headlight);
    body = new PhysicalBody();
    env = new PhysicalEnvironment();
    view = new View();
    view.setBackClipDistance(BACK_CLIP_DISTANCE);
    view.setPhysicalBody(body);
    view.setPhysicalEnvironment(env);
    view.attachViewPlatform(platform);
  }
  /**
   * Set the canvas that this camera is using
   * 
   * @param canvas
   *            The canvas that is to be used for this camera
   */
  public void setCanvas(Canvas3D canvas) {
    view.addCanvas3D(canvas);
  }
  /**
   * Set the location of the camera. This is the location of the center of the
   * camera relative to whatever is used as its root group node.
   * 
   * @param loc
   *            The location of the camera
   */
  public void setLocation(Vector3f loc) {
    location.setTranslation(loc);
    root_tx_grp.setTransform(location);
  }
  /**
   * Set the orientation of the camera.
   * 
   * @param angle
   *            The orientation of the camera
   */
  public void setOrientation(AxisAngle4f angle) {
    location.setRotation(angle);
    root_tx_grp.setTransform(location);
  }
  /**
   * Add some goemetry to the HUD area. This geometry must come complete with
   * its own parent transform to offset the object by the appropriate amount.
   * The camera does not do any auto-offsets of geometry.
   * 
   * @param geom
   *            The geometry to add
   */
  public void addHUDObject(Node geom) {
    hud_group.addChild(geom);
  }
  /**
   * Enable the headlight that is attached to the camera.
   * 
   * @param enable
   *            True if the light is to be turned on
   */
  public void setHeadLight(boolean enable) {
    headlight.setEnable(enable);
  }
  /**
   * Get the J3D node that is used to represent the camera
   * 
   * @return The root TransformGroup of the camera
   */
  Node getNode() {
    return root_tx_grp;
  }
}
/*******************************************************************************
 * Copyright (c) 1999 Justin Couch Java Source
 * 
 * Raw J3D Tutorial
 * 
 * Version History Date Version Programmer ---------- -------
 * ------------------------------------------ 01/08/1998 1.0.0 Justin Couch
 *  
 ******************************************************************************/
// Application specific imports
// none
/**
 * Test class illustrating the use of geometry.
 * 


 * A simple Shape3D class that contains a flat square constructed from a raw
 * geometry array. The square is located at the origin with bounds 0.5 along
 * each axis and lies in the X,Y plain. The normals point along the +Z axis.
 * However, the geometry is set to do no backface culling so you should see it
 * regardless of viewing position.
 * 


 * The basic appearance is set uses color in each corner to blend towards the
 * others. An emissive color of red is set just in case other colors don't work.
 * 
 * @author Justin Couch
 * @version Who Cares!
 */
class ExampleGeometry extends Shape3D {
  private IndexedQuadArray geom;
  private Appearance appearance;
  private Texture texture;
  /**
   * Construct the test object with geometry
   */
  public ExampleGeometry() {
    constructGeometry();
    constructAppearance();
  }
  private void constructGeometry() {
    int flags = GeometryArray.COORDINATES | GeometryArray.COLOR_4
        | GeometryArray.NORMALS;
    geom = new IndexedQuadArray(4, flags, 4);
    double[] coordinates = { 0.5, 0.5, 0, 0.5, -0.5, 0, -0.5, -0.5, 0,
        -0.5, 0.5, 0 };
    int[] indices = { 0, 1, 2, 3 };
    geom.setCoordinates(0, coordinates);
    geom.setCoordinateIndices(0, indices);
    float[] colors = { 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0 };
    geom.setColors(0, colors);
    geom.setColorIndices(0, indices);
    float[] normal = { 0, 0, 1 };
    geom.setNormal(0, normal);
    geom.setNormal(1, normal);
    geom.setNormal(2, normal);
    geom.setNormal(3, normal);
    setGeometry(geom);
  }
  /**
   * Construct the default appearance.
   */
  private void constructAppearance() {
    appearance = new Appearance();
    TextureAttributes tex_attr = new TextureAttributes();
    tex_attr.setTextureMode(TextureAttributes.DECAL);
    tex_attr.setPerspectiveCorrectionMode(TextureAttributes.FASTEST);
    appearance.setTextureAttributes(tex_attr);
    ColoringAttributes col_attr = new ColoringAttributes();
    col_attr.setShadeModel(ColoringAttributes.SHADE_GOURAUD);
    appearance.setColoringAttributes(col_attr);
    PolygonAttributes rend_attr = new PolygonAttributes();
    rend_attr.setCullFace(PolygonAttributes.CULL_NONE);
    //  uncomment this if you want it to display in line draw mode
    //    rend_attr.setPolygonMode(PolygonAttributes.POLYGON_LINE);
    appearance.setPolygonAttributes(rend_attr);
    Material mat = new Material();
    //    Color3f col = new Color3f(1, 0, 0);
    //    mat.setEmissiveColor(col);
    appearance.setMaterial(mat);
    setAppearance(appearance);
  }
  /**
   * Set the texture on our goemetry
   * 


   * Always specified as a URL so that we may fetch it from anywhere.
   * 
   * @param url
   *            The url to the image.
   */
  public void setTexture(URL url) {
    Toolkit tk = Toolkit.getDefaultToolkit();
    Image src_img = tk.createImage(url);
    BufferedImage buf_img = null;
    if (!(src_img instanceof BufferedImage)) {
      // create a component anonymous inner class to give us the image
      // observer we need to get the width and height of the source image.
      Component obs = new Component() {
      };
      int width = src_img.getWidth(obs);
      int height = src_img.getHeight(obs);
      // construct the buffered image from the source data.
      buf_img = new BufferedImage(width, height,
          BufferedImage.TYPE_INT_ARGB);
      Graphics g = buf_img.getGraphics();
      g.drawImage(src_img, 0, 0, null);
      g.dispose();
    } else
      buf_img = (BufferedImage) src_img;
    src_img.flush();
    ImageComponent img_comp = new ImageComponent2D(
        ImageComponent.FORMAT_RGB, buf_img);
    texture = new Texture2D(Texture.BASE_LEVEL, Texture.RGB, img_comp
        .getWidth(), img_comp.getHeight());
    appearance.setTexture(texture);
    buf_img.flush();
  }
}