JMU
Java 3D Basics
An Introduction


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu


Writing "Simple" Java3D Applications
  1. Create a Canvas3D object
  2. Create a SimpleUniverse object (which includes a view branch)
  3. Construct the content branch of the scene graph
  4. Compile the content branch
  5. Insert the content branch into the SimpleUniverse
Initialization
javaexamples/java3d/ApplicationWindow3D.java (Fragment: setup)
                // Get a GraphicsConfiguration object that describes the
        // properties of the display/graphics card
        graphicsConfiguration = SimpleUniverse.getPreferredConfiguration();

        // Construct a 3D rendering engine
        canvas3D = new Canvas3D(graphicsConfiguration);

        // Construct a SimpleUniverse object that creates the
        // "view" side of the scene graph
        simpleUniverse = new SimpleUniverse(canvas3D);

        // Get the ViewingPlatform so that we can set the
        // properties of the "view" side of the scene graph
        view = simpleUniverse.getViewingPlatform();
             
        // Move the projection plane back along the z-axis
        // so that the x interval [-1, 1] can be completely seen
        view.setNominalViewingTransform();
        
Windows
Windows (cont.)

Using the ApplicationWindow3D Class

javaexamples/java3d/basics/CubeDriver.java (Fragment: setup)
               ApplicationWindow3D      window;
       BranchGroup              scene;
       SimpleUniverse           universe;
       
       // Create an ApplicationWindow3D (for convenience)
       window   = new ApplicationWindow3D();

       // Get the SimpleUniverse associated with the window
       universe = window.getSimpleUniverse();
        
The Content Branch
The Content Branch (cont.)

Descendants of the Node Class

images/java3d_Node.gif
The Content Branch (cont.)

Descendants of the Node Class

javaexamples/java3d/basics/CubeDriver.java (Fragment: scene)
               // Create a BranchGroup containing a simple cube
       scene = new BranchGroup();
       scene.addChild(new Background(0.0f, 0.0f, 0.0f));
       
       // Add to the scene
       scene.addChild(CubeFactory.createColorCube());

       // Compile the scene
       scene.compile();
       

       // Add the scene to the SimpleUniverse
       universe.addBranchGraph(scene);
        
The Content Branch (cont.)

Descendants of the NodeComponent Class

images/java3d_NodeComponent.gif
Vertices
Shapes - Descendants of Geometry
Shapes (cont.)
images/java3d_scenegraph_CubeFactory.gif
Shapes(cont.)

An Example

javaexamples/java3d/basics/CubeFactory.java (Fragment: data)
            // Vertices
    private static final float vertices[][]   = {{-0.5f,-0.5f,-0.5f},
                                                 { 0.5f,-0.5f,-0.5f},
                                                 { 0.5f, 0.5f,-0.5f}, 
                                                 {-0.5f, 0.5f,-0.5f}, 
                                                 {-0.5f,-0.5f, 0.5f}, 
                                                 { 0.5f,-0.5f, 0.5f}, 
                                                 { 0.5f, 0.5f, 0.5f}, 
                                                 {-0.5f, 0.5f, 0.5f}
                                                };

    // Faces
    private static final int faces[][]  = {{4,5,6,7},
                                           {1,2,6,5},
                                           {0,1,5,4},
                                           {0,3,2,1},
                                           {0,4,7,3},
                                           {2,3,7,6}
                                          };

    // Face Colors
    private static final float colors[][]  = {{1.0f,0.0f,0.0f},
                                              {1.0f,1.0f,0.0f}, 
                                              {0.0f,1.0f,0.0f}, 
                                              {0.0f,0.0f,1.0f}, 
                                              {1.0f,0.0f,1.0f}, 
                                              {0.0f,1.0f,1.0f}
                                             };
        
javaexamples/java3d/basics/CubeFactory.java (Fragment: createCube)
            /**
     * Create a cube with white faces
     *
     * @return  The BranchGroup containing the cube
     */
    public static BranchGroup createCube()
    {
       BranchGroup       branchGroup;
       QuadArray         face;
       Shape3D           node;
       
       // Create an empty BranchGroup
       branchGroup = new BranchGroup();       

       // Create each face
       for (int f=0; f<faces.length; f++)
       {
          
          // Create a QuadArray to hold each face
          face = new QuadArray(4, GeometryArray.COORDINATES);

          // Add the vertices to the QuadArray
          for (int v=0; v<faces[f].length; v++)
          {
             face.setCoordinates(v, vertices[faces[f][v]]);             
          }
          
          // Create a Node to hold the face
          node = new Shape3D(face);
       
          // Add the Node to the BranchGroup
          branchGroup.addChild(node);          
       }
       
       return branchGroup;       
    }
        
Shapes - com.sun.j3d.utils.geometry
Transforms
Transformations (cont.)

An Example

javaexamples/java3d/basics/RotationDriver.java
        import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;

import java3d.*;
import java3d.basics.CubeFactory;


/**
 * An application that demonstrates the use of transforms
 * in Java3D

 * Note:  Under MS-Windows with Direct3D this application
 * must be run as follows:
 *
 *   java -Dj3d.rend=d3d Rotationriver
 *
 * because OpenGL is the default rendering technology (and some
 * MS-Windows installations do not support OpenGL)
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class RotationDriver
{
    /**
     * The entry-point of the application
     *
     * @param args  The command line arguments
     */
    public static void main(String[] args)
    {
       ApplicationWindow3D      window;
       BranchGroup              scene;
       SimpleUniverse           universe;
       
       window   = new ApplicationWindow3D();
       universe = window.getSimpleUniverse();
       scene = new BranchGroup();

       
       // Create the transformations
       Transform3D rotationX, rotationY, transform;

       rotationX = new Transform3D();
       rotationY = new Transform3D();
       transform = new Transform3D(); // The identity matrix
       
       // Initialize the rotation matrices
       rotationX.rotX(Math.PI/4.0d);
       rotationY.rotY(Math.PI/5.0d);

       // Concatenate the rotations
       transform.mul(rotationX);
       transform.mul(rotationY);
       
       // Create a TransformGroup from the
       // concatenated rotations
       TransformGroup transformGroup;
       transformGroup = new TransformGroup(transform);

       // Add a geometry Node to the TransformGroup
       transformGroup.addChild(CubeFactory.createColorCube());

       // Add the TransformGroup to the scene
       scene.addChild(transformGroup);
       


       scene.compile();
       universe.addBranchGraph(scene);
    }
}
        
Shapes (cont.)

The Scene Graph in RotationDriver

images/java3d_scenegraph_RotationDriver.gif
User Interaction
User Interaction (cont.)

A Behavior

javaexamples/java3d/basics/KeyboardBehavior.java
        package java3d.basics;

import java.awt.event.*;
import java.util.*;
import javax.media.j3d.*;

/**
 * A Behavior that changes the rotation of a TransformGroup
 * in response to KEY_PRESSED events
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class KeyboardBehavior extends Behavior
{
    private double                 angle;
    private Transform3D            transform;
    
    private TransformGroup         transformGroup; // Not owned


    /**
     * Explicit Value Constructor
     *
     * @param tg  The TransformGroup to adjust in response to key presses
     */
    public KeyboardBehavior(TransformGroup tg)
    {
       transformGroup = tg;
       angle          = 0.0;
       transform      = new Transform3D();       
    }
    
    
    /**
     * Initialize this Behavior
     * (required by Behavior)
     */
    public void initialize()
    {
       wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
    }
    

    /**
     * Process a stimulus meant for this Behavior
     * (required by Behavior)
     *
     * @param criteria  The triggered wakeup criteria
     */
    public void processStimulus(Enumeration criteria)
    {
       angle += 0.1;
       
       transform.rotY(angle);
       transformGroup.setTransform(transform);
       wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
    }
    
}
        
User Interaction (cont.)

Using a Behavior

javaexamples/java3d/basics/KeyboardDriver.java
        import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;

import java3d.*;
import java3d.basics.CubeFactory;
import java3d.basics.KeyboardBehavior;


/**
 * An application that demonstrates the use of interaction
 * in Java3D

 * Note:  Under MS-Windows with Direct3D this application
 * must be run as follows:
 *
 *   java -Dj3d.rend=d3d KeyboardDriver
 *
 * because OpenGL is the default rendering technology (and some
 * MS-Windows installations do not support OpenGL)
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class KeyboardDriver
{
    /**
     * The entry-point of the application
     *
     * @param args  The command line arguments
     */
    public static void main(String[] args)
    {
       ApplicationWindow3D      window;
       BranchGroup              scene;
       SimpleUniverse           universe;
       
       window   = new ApplicationWindow3D();
       universe = window.getSimpleUniverse();
       scene = new BranchGroup();
       
       // Create the transformations
       Transform3D transform;
       transform = new Transform3D(); // The identity matrix
       
       // Create a TransformGroup from the
       // concatenated rotations
       TransformGroup transformGroup;
       transformGroup = new TransformGroup(transform);

       // Allow the TransformGroup to be modified
       transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

       // Add a geometry Node to the TransformGroup
       transformGroup.addChild(CubeFactory.createColorCube());

       // Add the TransformGroup to the scene
       scene.addChild(transformGroup);
       
       // Construct the KeyboardBehavior
       KeyboardBehavior   keyboard;       
       keyboard = new KeyboardBehavior(transformGroup);
       keyboard.setSchedulingBounds(new BoundingSphere());
       

       // Add the KeyboardBehavior to the scene
       scene.addChild(keyboard);
       



       scene.compile();
       universe.addBranchGraph(scene);
    }
}
        
Shapes (cont.)

The Scene Graph in KeyboardDriver

images/java3d_scenegraph_KeyboardDriver.gif
Loaders
Loaders (cont.)

Loading Wavefront Files

javaexamples/java3d/basics/LoaderDriver.java
        import com.sun.j3d.loaders.*;
import com.sun.j3d.loaders.objectfile.*;
import com.sun.j3d.utils.behaviors.vp.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;

import java3d.*;
import java3d.basics.CubeFactory;


/**
 * An application that displays a cube in Java3D
 *
 * Note:  Under MS-Windows with Direct3D this application
 * must be run as follows:
 *
 *   java -Dj3d.rend=d3d LoaderDriver
 *
 * because OpenGL is the default rendering technology (and some
 * MS-Windows installations do not support OpenGL)
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class LoaderDriver
{
    private static Color3f      GRAY  = new Color3f(0.75f, 0.75f, 0.75f);
    private static Color3f      WHITE = new Color3f(1.00f, 1.00f, 1.00f);
    

    /**
     * The entry-point of the application
     *
     * @param args  The command line arguments
     */
    public static void main(String[] args)
    {
       AmbientLight             ambientLight;       
       ApplicationWindow3D      window;
       DirectionalLight         backLight, frontLight;       
       BranchGroup              root;
       BoundingSphere           bounds;       
       ObjectFile               objectFile;       
       OrbitBehavior            orbitBehavior;       
       Scene                    scene;       
       SimpleUniverse           universe;
       Transform3D              transform;       
       TransformGroup           transformGroup;
       Vector3f                 back, front;
       
       
       window   = new ApplicationWindow3D();
       universe = window.getSimpleUniverse();
       root = new BranchGroup();

       objectFile = new ObjectFile();
       objectFile.setFlags(ObjectFile.RESIZE | ObjectFile.TRIANGULATE | ObjectFile.STRIPIFY);
       

       try
       {
          // Read the .obj file
          scene = objectFile.load(args[0]);          
          root.addChild(scene.getSceneGroup());


          // Setup the ambient light
          ambientLight = new AmbientLight(GRAY);
          bounds = new BoundingSphere (new Point3d (0.0, 0.0, 0.0), 100.0);
          ambientLight.setInfluencingBounds(bounds);
          root.addChild(ambientLight);        


          // Set up the directional lights
          back  = new Vector3f(-1.0f, -1.0f, -1.0f);
          backLight = new DirectionalLight(WHITE, back);
          backLight.setInfluencingBounds(bounds);
          root.addChild(backLight);

          front = new Vector3f(1.0f, 1.0f, 1.0f);
          frontLight = new DirectionalLight(WHITE, front);
          frontLight.setInfluencingBounds(bounds);
          root.addChild(frontLight);


          // Setup the transform
          transformGroup = new TransformGroup();
          transform = new Transform3D();
          transform.setTranslation(new Vector3f(0f,0f,-5f));
          transformGroup.setTransform(transform);
          root.addChild(transformGroup);


          // Setup the user-interaction behavior so the user
          // can click-and-drag to rotate the scene
          orbitBehavior = new OrbitBehavior(window.getCanvas3D(),
                                            OrbitBehavior.REVERSE_ALL);
          orbitBehavior.setSchedulingBounds(bounds);
          universe.getViewingPlatform().setViewPlatformBehavior(orbitBehavior);            

       }
       catch (Exception e)
       {
          e.printStackTrace();          
       }
       
       universe.addBranchGraph(root);
    }
}