J3dSwingFrame.java Source code

Java tutorial

Introduction

Here is the source code for J3dSwingFrame.java

Source

/*******************************************************************************
 *                      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
 * <P>
 * 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
 * <P>
 * 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
 * <P>
 * 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.
 * <P>
 * 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.
 * <P>
 * 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
     * <P>
     * 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();
    }
}